i'd appreciate if someone could help!
I need to replace each character in my text(encrypted,which i read from file) with another character, which i have in my Dictionary.
StreamReader st = new StreamReader(#"C:\path of text");
string text = st.ReadToEnd();
st.Close();
char[] textChar = text.ToCharArray(); //splitting text into characters
So, in my Dictionary Dictionary<char, char> keys = new Dictionary<char,char>(); for key i have some letter, say 'n' and for value - another letter, say 'a'. So i need to replace each 'n' with 'a' in my text. Dictionary has 26 letters for keys and 26 letters for values respectively.
Now i try to replace letters and write 'decrypted' text into some file
StreamWriter sw = new StreamWriter(#"path for decrypted file");
foreach(KeyValuePair<char, char> c in keys)
{
for(int i =0; i< textChar.Length; i++)
{
if (textChar.Contains(c.Key))
{ //if text has char as a Key in Dictionary
textChar[i] = keys[c.Key]; //replace with its value
}
else
{
sw.Write(textChar[i]); //if not, just write (in case of punctuatuons in text which i dont want to replace)
}
}
}
st.Close();
file.Close();
This code does not work correctly, because the replacement is wrong.
I'd be so grateful for any help!
Try the code similar to this, I written it without Visual Studio so maybe it needs some corrections :)
string text = File.ReadAllText(#"path for decrypted file");
foreach(var key in keys)
{
text = text.Replace(key.Key, key.Value);
}
try this:
StreamReader st = new StreamReader(#"C:\path of text");
string text = st.ReadToEnd();
st.Close();
foreach(KeyValuePair<char, char> c in keys)
{
text = text.Replace(c.Key, c.Value);
}
String.Replace returns a new string in which all occurrences of a specified Unicode character in this instance are replaced with another specified Unicode character.
Why do you use char[] textChar ? In most cases using string is preferable.
There is a problem with your code ...
What happens if (for example) you have a key (a,z) and a key (z,b). If you just apply a straight swap all your a's will get turned to z's, and then all your z's to b's. (This means all your a's and z's got turned to b's).
You need to convert items to some intermediate value, then you can then decode as necessary.
(a,z)
(z,b)
encode
(a,[26])
(z,[02])
decode
([26],z)
([02],b)
Related
I have a list of bad words, that if found in the text string, will be replaced by a cleaned word.
eg. badwords{woof} is replaced by w$$f
But is currently only working when the array list is in the same case as the matched word in the sentence.
var badWords = new List<string>{"woof", "meow"}
var string = "I have a cat named meow and a dog name Woof."
Should become === "I have a cat named m$$w and a dog name W$$f"
public string CensorText(string text)
{
if (string.IsNullOrWhiteSpace(text))
{
return text;
}
foreach (string word in CensoredWords)
{
text = text.Replace(word, WordCleaner(word));
}
return text;
}
private static string WordCleaner(string wordToClean)
{
string firstChar = wordToClean.Substring(0,1);
string lastChar = wordToClean.Substring(wordToClean.Length - 1);
string centerHash = new string('$', wordToClean.Length-2);
return string.Concat(firstChar, centerHash, lastChar);
}
How can make it so that its case insensitive when looping through the words and cleaning them. Simpler the answer is better.
Try replacing:
text = text.Replace(word, WordCleaner(word));
with
text = text.Replace(word.ToLower(), WordCleaner(word));
This converts any upper case letter to a lower case one.
Edit
I've realised that I've made the wrong variable into lower case.
Change:
public string CensorText(string text)
{
To:
public string CensorText(string text)
{
text = text.ToLower();
Edit 2
To retain the original sentence with the censored words changed, it would be much easier to use re instead. First, revert your file back to how it was in the question.
Now replace:
text = text.Replace(word, WordCleaner(word));
with:
text = regex.replace(text,word,WordCleaner(word),RegexOptions.Ignorecase);
Here's a simple option you can use.
The benefit is you don't care which of the word is lower case, it'll work for either cases. Note that compare returns an int, hence why we check it's 0 for a match.
string input = "the Woof is on Fire, we don't need no bucket, leT the ...";
string[] bad_words = new string[] {"woof","fire","BucKet", "Let"};
foreach (var word in input.Split(' ')) {
if (bad_words.Any( b => String.Compare( word, b // Following line does what you want:
, StringComparison.OrdinalIgnoreCase) == 0))
Console.Write(WordCleaner(word));
else
Console.Write(word);
}
Output:
the W$$f is on F$$e we don't need no b$$$$t l$T the ...
Seems fine to me. Note that if you split on space, a word with a comma right after will have that comma as part of the word
So here is the deal. Suppose i have a ".txt" file which contains some kind of text(any). I need a program to read each character in the text including symbols, numbers, white space and etc. After I need it to count amount of occurrence of each character that was read.
Now reading text char by char is easy:
string text = File.ReadAllText("text.txt");
foreach (char c in text) Console.WriteLine(c);
What will be the best way to save each character from a .txt file and work with them after?
Since you need the characters as well as the number of occurrence of the appearing characters. Consider of using Dictionary<char,int> to help you:
Dictionary<char,int> dict = new Dictionary<char,int>();
for (char c in text){
if (dict.ContainsKey(c)) //exist add count of the existing item
dict[c] = dict[c] + 1;
else //does not exist, create new item
dict.Add(c,1);
}
By using Dictionary, you could do things like these, which seem to fit your needs best:
dict.Keys; //to get all characters (Keys) you store in the dictionary before
dict.ContainsKey('a'); //to check if the Dictionary has 'a' as one of its keys
dict['a']; //to get the value dictionary item with character 'a' as its Key
dict.Add('a',1); //add new key 'a' to the dictionary with the value of 1
I would say using List would work in this case.
I have a text file that has several hundred configuration values. The general format of the configuration data is "Label:Value". Using C# .net, I would like to read these configurations, and use the Values in other portions of the code. My first thought is that I would use a string search to look for the Labels then parse out the values following the labels and add them to a dictionary, but this seems rather tedious considering the number of labels/values that I would have to search for. I am interested to hear some thoughts on a possible architecture to perform this task. I have included a small section of a sample text file that contains some of the labels and values (below). A couple of notes: The Values are not always numeric (as seen in the AUX Serial Number); For whatever reason, the text files were formatted using spaces (\s) rather than tabs (\t). Thanks in advance for any time you spend thinking about this.
Sample Text:
AUX Serial Number: 445P000023 AUX Hardware Rev: 1
Barometric Pressure Slope: -1.452153E-02
Barometric Pressure Intercept: 9.524336E+02
This is a nice little brain tickler. I think this code might be able to point you in the right direction. Keep in mind, this fills a Dictionary<string, string>, so there are no conversions of values into ints or the like. Also, please excuse the mess (and the poor naming conventions). It was a quick write-up based on my train of thought.
Dictionary<string, string> allTheThings = new Dictionary<string, string>();
public void ReadIt()
{
// Open the file into a streamreader
using (System.IO.StreamReader sr = new System.IO.StreamReader("text_path_here.txt"))
{
while (!sr.EndOfStream) // Keep reading until we get to the end
{
string splitMe = sr.ReadLine();
string[] bananaSplits = splitMe.Split(new char[] { ':' }); //Split at the colons
if (bananaSplits.Length < 2) // If we get less than 2 results, discard them
continue;
else if (bananaSplits.Length == 2) // Easy part. If there are 2 results, add them to the dictionary
allTheThings.Add(bananaSplits[0].Trim(), bananaSplits[1].Trim());
else if (bananaSplits.Length > 2)
SplitItGood(splitMe, allTheThings); // Hard part. If there are more than 2 results, use the method below.
}
}
}
public void SplitItGood(string stringInput, Dictionary<string, string> dictInput)
{
StringBuilder sb = new StringBuilder();
List<string> fish = new List<string>(); // This list will hold the keys and values as we find them
bool hasFirstValue = false;
foreach (char c in stringInput) // Iterate through each character in the input
{
if (c != ':') // Keep building the string until we reach a colon
sb.Append(c);
else if (c == ':' && !hasFirstValue)
{
fish.Add(sb.ToString().Trim());
sb.Clear();
hasFirstValue = true;
}
else if (c == ':' && hasFirstValue)
{
// Below, the StringBuilder currently has something like this:
// " 235235 Some Text Here"
// We trim the leading whitespace, then split at the first sign of a double space
string[] bananaSplit = sb.ToString()
.Trim()
.Split(new string[] { " " },
StringSplitOptions.RemoveEmptyEntries);
// Add both results to the list
fish.Add(bananaSplit[0].Trim());
fish.Add(bananaSplit[1].Trim());
sb.Clear();
}
}
fish.Add(sb.ToString().Trim()); // Add the last result to the list
for (int i = 0; i < fish.Count; i += 2)
{
// This for loop assumes that the amount of keys and values added together
// is an even number. If it comes out odd, then one of the lines on the input
// text file wasn't parsed correctly or wasn't generated correctly.
dictInput.Add(fish[i], fish[i + 1]);
}
}
So the only general approach that I can think of, given the format that you're limited to, is to first find the first colon on the line and take everything before it as the label. Skip all whilespace characters until you get to the first non-whitespace character. Take all non-whitespace characters as the value of the label. If there is a colon after the end of that value take everything after the end of the previous value to the colon as the next value and repeat. You'll also probably need to trim whitespace around the labels.
You might be able to capture that meaning with a regex, but it wouldn't likely be a pretty one if you could; I'd avoid it for something this complex unless you're entire development team is very proficient with them.
I would try something like this:
While string contains triple space, replace it with double space.
Replace all ": " and ": " (: with double space) with ":".
Replace all " " (double space) with '\n' (new line).
If line don't contain ':' than skip the line. Else, use string.Split(':'). This way you receive arrays of 2 strings (key and value). Some of them may contain empty characters at the beginning or at the end.
Use string.Trim() to get rid of those empty characters.
Add received key and value to Dictionary.
I am not sure if it solves all your cases but it's a general clue how I would try to do it.
If it works you could think about performance (use StringBuilder instead of string wherever it is possible etc.).
This is probably the dirtiest function I´ve ever written, but it works.
StreamReader reader = new StreamReader("c:/yourFile.txt");
Dictionary<string, string> yourDic = new Dictionary<string, string>();
StreamReader reader = new StreamReader("c:/yourFile.txt");
Dictionary<string, string> yourDic = new Dictionary<string, string>();
while (reader.Peek() >= 0)
{
string line = reader.ReadLine();
string[] data = line.Split(':');
if (line != String.Empty)
{
for (int i = 0; i < data.Length - 1; i++)
{
if (i != 0)
{
bool isPair;
if (i % 2 == 0)
{
isPair = true;
}
else
{
isPair = false;
}
if (isPair)
{
string keyOdd = data[i].Trim();
try { keyOdd = keyOdd.Substring(keyOdd.IndexOf(' ')).TrimStart(); }
catch { }
string valueOdd = data[i + 1].TrimStart();
try { valueOdd = valueOdd.Remove(valueOdd.IndexOf(' ')); } catch{}
yourDic.Add(keyOdd, valueOdd);
}
else
{
string keyPair = data[i].TrimStart();
keyPair = keyPair.Substring(keyPair.IndexOf(' ')).Trim();
string valuePair = data[i + 1].TrimStart();
try { valuePair = valuePair.Remove(valuePair.IndexOf(' ')); } catch { }
yourDic.Add(keyPair, valuePair);
}
}
else
{
string key = data[i].Trim();
string value = data[i + 1].TrimStart();
try { value = value.Remove(value.IndexOf(' ')); } catch{}
yourDic.Add(key, value);
}
}
}
}
How does it works?, well splitting the line you can know what you can get in every position of the array, so I just play with the even and odd values.
You will understand me when you debug this function :D. It fills the Dictionary that you need.
I have another idea. Does values contain spaces? If not you could do like this:
Ignore white spaces until you read some other char (first char of key).
Read string until ':' occures.
Trim key that you get.
Ignore white spaces until you read some other char (first char of value).
Read until you get empty char.
Trim value that you get.
If it is the end than stop. Else, go back to step 1.
Good luck.
Maybe something like this would work, be careful with the ':' character
StreamReader reader = new StreamReader("c:/yourFile.txt");
Dictionary<string, string> yourDic = new Dictionary<string, string>();
while (reader.Peek() >= 0)
{
string line = reader.ReadLine();
yourDic.Add(line.Split(':')[0], line.Split(':')[1]);
}
Anyway, I recommend to organize that file in some way that you´ll always know in what format it comes.
I have got a problem with my exercise. The input data is a set of sentences - string[] sentences - The exercise's requirement is that how to find and replace emoticon (ex: :D) to according smiley image in each sentences, and then export them to .html file.
File text data define emoticon and smiley has a structure like that:
[imagename] tab [emoticon1] space [emoticon2] space [emoticon2]
smile.gif :) :-) :=) (smile)
sadsmile.gif :( :-( :=( (sad)
laugh.gif :D :-D (laugh)
...
The first issue is which C#'s data structure to store emoticon and smiley.
I'm happy :). How are you? -> I'm happy <img src="smile"> How are you?
The second issue is how I code to search and replace emoticon.
the last issue is, because the export file is html format, so we must encode html, may be we use HttpUtility.HtmlEncode(...) But the resultSentence contain <img ...> tag, so I think it invole to the sencond issue...
Please help me to solve those above problem. Thanks so much!
First, you need to load the smiley "mappings" into a dictionary:
Dictionary<string, string> LoadSmileys(string fileName)
{
var smileys = new Dictionary<string, string>();
using (var reader = new StreamReader(fileName))
{
string line;
while ((line = reader.ReadLine()) != null)
{
string[] parts = line.Split(new[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 1; i < parts.Length; i++)
{
smileys[parts[i]] = parts[0];
}
}
}
return smileys;
}
Then, just loop over the keys, and replace each occurrence of the key with the corresponding image. To avoid the problem mentionned in your comment to Carra's answer, just replace the longest keys first:
StringBuilder tmp = new StringBuilder(originalText);
foreach (var key in smileys.Keys.OrderByDescending(s => s.Length))
{
tmp.Replace(key, GetImageLink(smileys[key]));
}
Note the use of a StringBuilder, to avoid creating many instances of String.
It's obviously not the most efficient approach, but at least it's simple... you can always try to optimize it later if it turns out to be a performance bottleneck.
UPDATE
OK, so there is still a problem if some of your smileys include reserved HTML characters like '<' or '>'... If you encode the text to HTML before replacing the smileys, these characters will be replaced with < or >, so the smileys won't be recognized. On the other hand, if you encode the text after replacing the smileys with <img> tags, the tags will be encoded as well.
Here's what you could do:
assign a unique identifier to each smiley, something unlikely to appear in the original text, like a GUID
replace each occurrence of each smiley by the corresponding identifier (again, starting with the longest smiley)
encode the resulting text to HTML
replace each occurrence of each smiley identifier by the appropriate <img> tag
var mapping = LoadSmileys(#"D:\tmp\smileys.txt");
var smileys = mapping.Keys.OrderByDescending(s => s.Length)
.ToArray();
// Assign an ID like "{93e8b75a-6837-43f8-95ec-801ed59bc167}" to each smiley
var ids = smileys.Select(key => Guid.NewGuid().ToString("B"))
.ToArray();
string text = File.ReadAllText(#"D:\tmp\test_smileys.txt");
// Replace each smiley with its id
StringBuilder tmp = new StringBuilder(text);
for (int i = 0; i < smileys.Length; i++)
{
tmp.Replace(smileys[i], ids[i]);
}
// Encode the text to HTML
text = HttpUtility.HtmlEncode(tmp.ToString());
// Replace each id with the appropriate <img> tag
tmp = new StringBuilder(text);
for (int i = 0; i < smileys.Length; i++)
{
string image = mapping[smileys[i]];
tmp.Replace(ids[i], GetImageLink(image));
}
text = tmp.ToString();
You can use simple string.replace here.
foreach(string text in sentences)
{
foreach(var kvp in dict)
{
text = text.replace(kvp.Key, GetImageLink(kvp.Value));
}
}
To create the html you're better of using the native C# classes like HtmlTextWriter or an XmlWriter.
That's what I've written so far:
string omgwut;
omgwut = textBox1.Text;
omgwut = omgwut.Replace(" ", "snd\\space.wav");
omgwut = omgwut.Replace("a", "snd\\a.wav");
Now, the problem is that this code would turn
"snd\space.wav"
into
"snd\spsnd\a.wavce.wsnd\a.wavv"
in line four. Not what I'd want! Now I know I'm not good at C#, so that's why I'm asking.
Solutions would be great! Thanks!
You'll still need to write the getSoundForChar() function, but this should do what you're asking. I'm not sure, though, that what you're asking will do what you want, i.e., play the sound for the associated character. You might be better off putting them in a List<string> for that.
StringBuilder builder = new StringBuilder();
foreach (char c in textBox1.Text)
{
string sound = getSoundForChar( c );
builder.Append( sound );
}
string omgwut = builder.ToString();
Here's a start:
public string getSoundForChar( char c )
{
string sound = null;
if (sound == " ")
{
sound = "snd\\space.wav";
}
... handle other special characters
else
{
sound = string.Format( "snd\\{0}.wav", c );
}
return sound;
}
The problem is that you are doing multiple passes of the data. Try just stepping through the characters of the string in a loop and replacing each 'from' character by its 'to' string. That way you're not going back over the string and re-doing those characters already replaced.
Also, create a separate output string or array, instead of modifying the original. Ideally use a StringBuilder, and append the new string (or the original character if not replacing this character) to it.
I do not know of a way to simultaneously replace different characters in C#.
You could loop over all characters and build a result string from that (use a stringbuilder if the input string can be long). For each character, you append its replacement to the result string(builder).
But what are you trying to do? I cannot think of a useful application of appending file paths without any separator.