Replacing a string with an equal amount of underscores - c#

I'm trying to replace all characters of a string with underscores. From my readings a string is ordinarily immutable which means it cannot be modified superficially once it has been created.
I've decided to use StringBuilder to carry out the modification, though I need the underscores to be for display purposes only (hangman game) and not actually alter the value.
I've read through the Microsoft docs and feel like I'm doing the right thing but cannot understand why it won't work. Code below.
using System;
using System.Text;
namespace randomtesting
{
internal class Program
{
static void Main(string[] args)
{
string str = "hello";
StringBuilder sb = new StringBuilder(str);
sb.Replace(str, "_", 0, str.Length);
Console.WriteLine(str);
}
}
}
Edit -
What I ended up doing to get it to do what I wanted - unsure if ideal. Please provide feedback if there's a better way to do it, feel like it's not the most efficient way, but it works.
using System;
using System.Text;
namespace randomtesting
{
internal class Program
{
static void Main(string[] args)
{
string str = "hello";
string strDisplayedAsUnderscores = new string('_', str.Length);
Console.WriteLine(strDisplayedAsUnderscores);
char guess = Convert.ToChar(Console.ReadLine().ToLower()); //reads the user's guess
int guessIndex = str.IndexOf(guess); //gets the index of the character guessed in relation to the original word
StringBuilder word = new StringBuilder(strDisplayedAsUnderscores); //converts the underscores into a StringBuilder string
if (str.Contains(guess))
{
Console.WriteLine(word.Replace('_', guess, guessIndex, 1));
//if guess is contained in the original word
//replace the indexed underscore with the
//guessed character
}
}
}
}

You want this System.String constructor
string result = new string('_', str.Length);

Related

How to dynamically remove the last Char in a String in C#

I am creating a console application upon which the user can type in a train station and find the train stations. For this, I am appending the Console.ReadKey().Key to a String each time.
When the user types an incorrect letter, I want the ConsoleKey.Backspace to remove the last Char in the String.
private void SetDepartingFrom()
{
String searchQuery = "";
ConsoleKey keyIn;
while ((keyIn = readKey(searchQuery)) != ConsoleKey.Enter)
{
if (keyIn == ConsoleKey.Backspace)
{
searchQuery.TrimEnd(searchQuery[searchQuery.Length - 1]);
}
else
{
searchQuery += keyIn.ToString();
}
}
}
private ConsoleKey readKey(String searchQuery)
{
Console.Clear();
Console.WriteLine("Stations Found:");
if (searchQuery != "")
App.Stations.FindAll(x => x.GetName().ToUpper().Contains(searchQuery.ToUpper())).ForEach(x => Console.WriteLine(x.GetName()));
else
Console.WriteLine("No Stations found...");
Console.Write("Search: " + searchQuery);
return Console.ReadKey().Key;
}
I have tried the following:
if (keyIn == ConsoleKey.Backspace)
searchQuery.TrimEnd(searchQuery[searchQuery.Length - 1]);
if (keyIn == ConsoleKey.Backspace)
searchQuery.Remove(searchQuery.Length -1);
if (keyIn == ConsoleKey.Backspace)
searchQuery[searchQuery.Length -1] = "";
None have worked. I understand Strings are immutable in C#, however, is this possible or is there a better way to achieve this?
Thanks in advance.
String is immutable so you have to use the value returned by TrimEnd.
searchQuery = searchQuery.TrimEnd(searchQuery[searchQuery.Length - 1]);
In this case I think Substring method would be more appropriate.
As you noted, strings are immutable. All of the instance methods on the string type (at least those related to "modifying" it) return a new string. This means that calling something like the following returns a new string which is immediately discarded:
// value is discarded
searchQuery.Substring(0, searchQuery.Length - 1);
The solution is to reassign the variable with the new value. For example:
searchQuery = searchQuery.Substring(0, searchQuery.Length - 1);
SharpLab example
If you are using C# 8 you can make use of the range operator via the Index/Range classes. This provides a bit cleaner version:
// backspace one character
searchQuery = searchQuery[..^1];
SharpLab example
I will also note that TrimEnd is most likely not what you want. It will trim more than one character at a time which isn't what a single press of the Backspace key would do. For example consider the following:
var str = "Abcdeee";
var result = str.TrimEnd('e');
Console.WriteLine(result); // prints "Abcd"
SharpLab example
Any method you use to manipulate the string will return the new string so you need to capture that.
string newString = searchQuery.Substring(0, searchQuery.Length -1);
It will return a new string, so you need to assign it to a string like this.
string newStr = earchQuery.Remove(searchQuery.Length -1);
Or to same string you can do like this.
earchQuery= earchQuery.Remove(searchQuery.Length -1);
You can also use TrimEnd and SubString methods.
You may try the following code example which removes the last character from a string.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
string founder = "Hell World from Big_Data_Analyst!";
string founderMinus1 = founder.Remove(founder.Length - 1, 1);
Console.WriteLine(founderMinus1);
}
}
}
The input string in the code is
Hell World from Big_Data_Analyst!
The output string is
Hell World from Big_Data_Analyst
As you see the last character which is ! is being removed in the output

Remove characters from List<string> in between separators (from text file)

Fast way to replace text in text file.
From this: somename#somedomain.com:hello_world
To This: somename:hello_world
It needs to be FAST and support multiple lines of text file.
I tried spiting the string into three parts but it seems slow. Example in the code below.
<pre><code>
public static void Conversion()
{
List<string> list = File.ReadAllLines("ETU/Tut.txt").ToList();
Console.WriteLine("Please wait, converting in progress !");
foreach (string combination in list)
{
if (combination.Contains("#"))
{
write: try
{
using (StreamWriter sw = new
StreamWriter("ETU/UPCombination.txt", true))
{
sw.WriteLine(combination.Split('#', ':')[0] + ":"
+ combination.Split('#', ':')[2]);
}
}
catch
{
goto write;
}
}
else
{
Console.WriteLine("At least one line doesn't contain #");
}
}
}</code></pre>
So a fast way to convert every line in text file from
somename#somedomain.com:hello_world
To: somename:hello_world
then save it different text file.
!Remember the domain bit always changes!
Most likely not the fastest, but it is pretty fast with an expression similar to,
#[^:]+
and replace that with an empty string.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = #"#[^:]+";
string substitution = #"";
string input = #"somename#somedomain.com:hello_world1
somename#some_other_domain.com:hello_world2";
RegexOptions options = RegexOptions.Multiline;
Regex regex = new Regex(pattern, options);
string result = regex.Replace(input, substitution);
}
}
If you wish to simplify/modify/explore the expression, it's been explained on the top right panel of regex101.com. If you'd like, you can also watch in this link, how it would match against some sample inputs.
RegEx Circuit
jex.im visualizes regular expressions:

Attempting to convert a char array to a string and then comparing length

My char[] both consist of exactly one element. My job is to compare the length of the element of the first array to the one of the second.
using System;
using System.Linq;
namespace FirstLecture
{
class Program
{
static void Main(string[] args)
{
char[] ints = {char.Parse(Console.ReadLine())};
char[] ints2 = {char.Parse(Console.ReadLine())};
string s1 = new string(ints);
string s2 = new string(ints2);
if (s1.Length > s2.Length)
{
Console.WriteLine(">");
}
else if (s1.Length < s2.Length)
{
Console.WriteLine("<");
}
else {
Console.WriteLine("=");
}
}
}
}
When I run the program in the console, I get String must be exactly one character long. I'm assuming there is some sort of a data type conversion error, cannot pin point it. Is this the case?
char.Parse only parses one single character, not the entire string you read from Console.ReadLine (so if you just type 'A' in your console, it should work).
Instead, you could just assign the string to the character array:
char[] ints = Console.ReadLine().ToArray();
It seems useless though since you immediate after assigning the characters construct a string out of it again. Both input and resulting strings should be the same.
This should be okay:
string s1 = Console.ReadLine();

TextElement Enumerator Class Bug or (Tamil) Unicode Bug

why the TextElementEnumerator not properly parsing the Tamil Unicode character.
using System;
using System.Collections.Generic;
using System.Globalization;
namespace Glyphtest
{
internal class Program
{
private static void Main()
{
const string unicodetxt1 = "ஊரவர் கெளவை";
List<string> output = Syllabify(unicodetxt1);
Console.WriteLine(output.Count);
const string unicodetxt2 = "கௌவை";
output = Syllabify(unicodetxt2);
Console.WriteLine(output.Count);
}
public static List<string> Syllabify(string unicodetext)
{
if (string.IsNullOrEmpty(unicodetext)) return null;
TextElementEnumerator enumerator = StringInfo.GetTextElementEnumerator(unicodetext);
var data = new List<string>();
while (enumerator.MoveNext())
data.Add(enumerator.Current.ToString());
return data;
}
}
}
Following above code sample deals with Unicode character
'கௌ'-> 0x0bc8 (க) +0xbcc(ௌ). (Correct Form)
'கௌ'->0x0bc8 (க) +0xbc6(ெ) + 0xbb3(ள) (In Correct Form)
Is it bug in Text Element Enumerator Class ,
why its not to Enumerate it properly from the string.
i.e
கெளவை => 'கெள'+ 'வை' has to enumerated in Correct form
கெளவை => 'கெ' +'ள' +'வை' not to be enumerated in Incorrect form.
If so how to overcome this issue.
Its not been bug with Unicode character or TextElementEnumerator Class,
As specific to the lanaguage (Tamil)
letter made by any Tamil consonants followed by visual glyph
for eg-
க -\u0b95
ெ -\u0bc6
ள -\u0bb3
form Tamil character 'கெள' while its seems similar to formation of visual glyph
க -\u0b95
ௌ-\u0bcc
and its right form to solution.
hence before enumerating Tamil character we have replace irregular formation of character.
As with rule of Tamil Grammar (ஔகாரக் குறுக்கம்)
the visual glyph (ௌ) will come as starting letter of a word.
so that. the above code is to be should processed as
internal class Program
{
private static void Main()
{
const string unicodetxt1 = "ஊரவர் கெளவை";
List<string> output = Syllabify(unicodetxt1);
Console.WriteLine(output.Count);
const string unicodetxt2 = "கௌவை";
output = Syllabify(unicodetxt2);
Console.WriteLine(output.Count);
}
public static string CheckVisualGlyphPattern(string txt)
{
string[] data = txt.Split(new[] { ' ', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
string list = string.Empty;
var rx = new Regex("^(.*?){1}(\u0bc6){1}(\u0bb3){1}");
foreach (string s in data)
{
var matches = new List<Match>();
string outputs = rx.Replace(s, match =>
{
matches.Add(match);
return string.Format("{0}\u0bcc", match.Groups[1].Value);
});
list += string.Format("{0} ", outputs);
}
return list.Trim();
}
public static List<string> Syllabify(string unicodetext)
{
var processdata = CheckVisualGlyphPattern(unicodetext);
if (string.IsNullOrEmpty(processdata)) return null;
TextElementEnumerator enumerator = StringInfo.GetTextElementEnumerator(processdata);
var data = new List<string>();
while (enumerator.MoveNext())
data.Add(enumerator.Current.ToString());
return data;
}
}
It produce the appropriate visual glyph while enumerating.
U+0BB3 ᴛᴀᴍɪʟ ʟᴇᴛᴛᴇʀ ʟʟᴀ has Grapheme_Cluster_Break=XX (Other). This makes the grapheme clusters <U+0BC8 U+0BC6><U+0BB3> the correct ones since there is always a grapheme cluster break before characters with Grapheme_Cluster_Break equal to Other.
<U+0BC8 U+0BCC> has no internal grapheme cluster breaks because U+0BCC has Grapheme_Cluster_Break=SpacingMark and there are usually no breaks before such characters (exceptions are at the start of text or when preceded by a control character).
Well, at least this is what the Unicode standard has to say (http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries).
Now, I have no idea of how Tamil works, so take what follows with a pinch of salt.
U+0BCC decomposes into <U+0BC6 U+0BD7>, meaning the two sequences (<U+0BC8 U+0BC6 U+0BB3> and <U+0BC8 U+0BCC>) not canonically equivalent, so there is no requirement for grapheme cluster segmentation to yield the same results.
When I look at it with my Tamil-ignorant eyes, it seems U+0BCC ᴛᴀᴍɪʟ ᴀᴜ ʟᴇɴɢᴛʜ ᴍᴀʀᴋ and U+0BB3 ᴛᴀᴍɪʟ ʟᴇᴛᴛᴇʀ ʟʟᴀ look exactly the same. However, U+0BCC is a spacing mark, but U+0BB3 isn't. If you use U+0BCC in the input instead of U+0BB3, the result is what you expected.
Going on a limb, I will say that you are using the wrong character but, again, I don't know Tamil at all so I can't be sure.

C# preg_replace?

What is the PHP preg_replace in C#?
I have an array of string that I would like to replace by an other array of string. Here is an example in PHP. How can I do something like that in C# without using .Replace("old","new").
$patterns[0] = '/=C0/';
$patterns[1] = '/=E9/';
$patterns[2] = '/=C9/';
$replacements[0] = 'à';
$replacements[1] = 'é';
$replacements[2] = 'é';
return preg_replace($patterns, $replacements, $text);
Real men use regular expressions, but here is an extension method that adds it to String if you wanted it:
public static class ExtensionMethods
{
public static String PregReplace(this String input, string[] pattern, string[] replacements)
{
if (replacements.Length != pattern.Length)
throw new ArgumentException("Replacement and Pattern Arrays must be balanced");
for (var i = 0; i < pattern.Length; i++)
{
input = Regex.Replace(input, pattern[i], replacements[i]);
}
return input;
}
}
You use it like this:
class Program
{
static void Main(string[] args)
{
String[] pattern = new String[4];
String[] replacement = new String[4];
pattern[0] = "Quick";
pattern[1] = "Fox";
pattern[2] = "Jumped";
pattern[3] = "Lazy";
replacement[0] = "Slow";
replacement[1] = "Turtle";
replacement[2] = "Crawled";
replacement[3] = "Dead";
String DemoText = "The Quick Brown Fox Jumped Over the Lazy Dog";
Console.WriteLine(DemoText.PregReplace(pattern, replacement));
}
}
You can use .Select() (in .NET 3.5 and C# 3) to ease applying functions to members of a collection.
stringsList.Select( s => replacementsList.Select( r => s.Replace(s,r) ) );
You don't need regexp support, you just want an easy way to iterate over the arrays.
public static class StringManipulation
{
public static string PregReplace(string input, string[] pattern, string[] replacements)
{
if (replacements.Length != pattern.Length)
throw new ArgumentException("Replacement and Pattern Arrays must be balanced");
for (int i = 0; i < pattern.Length; i++)
{
input = Regex.Replace(input, pattern[i], replacements[i]);
}
return input;
}
}
Here is what I will use. Some code of Jonathan Holland but not in C#3.5 but in C#2.0 :)
Thx all.
You are looking for System.Text.RegularExpressions;
using System.Text.RegularExpressions;
Regex r = new Regex("=C0");
string output = r.Replace(text);
To get PHP's array behaviour the way you have you need multiple instances of `Regex
However, in your example, you'd be much better served by .Replace(old, new), it's much faster than compiling state machines.
Edit: Uhg I just realized this question was for 2.0, but I'll leave it in case you do have access to 3.5.
Just another take on the Linq thing. Now I used List<Char> instead of Char[] but that's just to make it look a little cleaner. There is no IndexOf method on arrays but there is one on List. Why did I need this? Well from what I am guessing, there is no direct correlation between the replacement list and the list of ones to be replaced. Just the index.
So with that in mind, you can do this with Char[] just fine. But when you see the IndexOf method, you have to add in a .ToList() before it.
Like this: someArray.ToList().IndexOf
String text;
List<Char> patternsToReplace;
List<Char> patternsToUse;
patternsToReplace = new List<Char>();
patternsToReplace.Add('a');
patternsToReplace.Add('c');
patternsToUse = new List<Char>();
patternsToUse.Add('X');
patternsToUse.Add('Z');
text = "This is a thing to replace stuff with";
var allAsAndCs = text.ToCharArray()
.Select
(
currentItem => patternsToReplace.Contains(currentItem)
? patternsToUse[patternsToReplace.IndexOf(currentItem)]
: currentItem
)
.ToArray();
text = new String(allAsAndCs);
This just converts the text to a character array, selects through each one. If the current character is not in the replacement list, just send back the character as is. If it is in the replacement list, return the character in the same index of the replacement characters list. Last thing is to create a string from the character array.
using System;
using System.Collections.Generic;
using System.Linq;

Categories

Resources