I have text file so it looks like this.
Some old wounds never truly heal, and bleed again at the slightest word.
Fear cuts deeper than swords.
Winter is coming.
If I look back I am lost.
Nothing burns like the cold.
and I need to make that lines to be same length as longest one adding spaces
static void Reading(string fd, out int nr)
{
string[] lines = File.ReadAllLines(fd, Encoding.GetEncoding(1257));
int length = 0;
nr = 0;
int nreil = 0;
foreach (string line in lines)
{
if (line.Length > length)
{
length = line.Length;
nr = nreil;
}
nreil++;
}
}
edit: simply padding the sentences with whitespaces between words
EDIT: Since OP specified they wanted spacing between words, I have removed my end of line padding example, leaving only the justify code.
string[] lines = File.ReadAllLines(fd, Encoding.GetEncoding(1257));
int maxLength = lines.Max(l => l.Length);
lines = lines.Select(l => l.Justify(maxLength)).ToArray();
public static string Justify(this string input, int length)
{
string[] words = input.Split(' ');
if (words.Length == 1)
{
return input.PadRight(length);
}
string output = string.Join(" ", words);
while (output.Length < length)
{
for (int w = 0; w < words.Length - 1; w++)
{
words[w] += " ";
output = string.Join(" ", words);
if (output.Length == length)
{
break;
}
}
}
return output;
}
Related
I created following to count number of words. Now I need to remove all spaces using IndexOf. I'm stuck. Can someone help? It has to be something simple, but I cant figure it out.
string text = "Hello. What time is it?";
int position = 0;
int noSpaces = 0;
for (int i = 0; i < text.Length; i++)
{
position = text.IndexOf(' ', position + 1);
if (position != -1)
{ noSpaces++; }
if (position == -1) break;
}
Console.WriteLine(noSpaces + 1);
If you are looking to just remove the spaces in your text so it would look like: Hello.Whattimeisit? then all you need to do is use String.Replace:
string text = "Hello. What time is it?";
string textWithNoSpaces = text.Replace(" ", "");
Console.WriteLine(textWithNoSpaces); // will print "Hello.Whattimeisit?"
If you are looking to split the text into separate words then you would want to use String.Split:
string text = "Hello. What time is it?";
string[] words = text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // "RemoveEmptyEntries" will remove any entries which are empty: ""
// words[0] > Hello.
// words[1] > What
// etc.
You then can get a count of how many words are in the text and then combine them, using String.Concat, if you need text in the form of Hello.Whattimeisit?:
int numberOfWords = words.Length;
string textWithNoSpaces = string.Concat(words);
Update: This is how you would count the number of words and remove spaces using String.IndexOf & String.Substring:
This is a really sloppy example, but it gets the job done
string text = "Hello. What time is it?";
string newText = string.Empty;
int prevIndex = 0;
int index1 = 0;
int index2 = 0;
int numberOfWords = 0;
while (true)
{
index1 = text.IndexOf(' ', prevIndex);
if (index1 == -1)
{
if (prevIndex < text.Length)
{
newText += text.Substring(prevIndex, (text.Length - prevIndex));
numberOfWords += 1;
}
break;
}
index2 = text.IndexOf(' ', (index1 + 1));
if ((index2 == -1) || (index2 > (index1 + 1)))
{
newText += text.Substring(prevIndex, (index1 - prevIndex));
numberOfWords += 1;
}
prevIndex = (index1 + 1);
}
Console.WriteLine(numberOfWords); // will print 5
Console.WriteLine(newText); // will print "Hello.Whattimeisit?"
Console.ReadLine();
If your requirement is to count the number of words, can't you try this?
string text = "Hello. What time is it?";
var arr = text.Split(' ');
var count = arr.Length;
.Net Fiddle
Strings are immutable so you cant achieve it with only IndexOf that will require multiple changes. if you need to achieve it with that particular method I think that StringBuilder is the only way. However if this is not some assignment and you plan to use it in real application I strongly dissuade because it is really process heavy.
I am aiming to replace words within an array (input by the user) that appear in a sentence. I want to then output this sentence but with the replace version which would be either ***** or for example censor would become c****r.
static void CensorSelectedWords(string _sentence, int _wordCount)
{
string[] words = new string[_wordCount];
string[] splitSentence = new string[_wordCount];
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Type in the words you wish to be censored: ");
words[i] = Console.ReadLine();
splitSentence = _sentence.Split(' ', '.', '?', ',', '!');
for (int j = 0; j < splitSentence.Length; j++)
if (splitSentence[j] == words[i])
splitSentence[j] = words[i].Replace(words[i], "*");
}
Console.WriteLine(splitSentence);
}
You can replace every word within _sentence like this:
static void CensorSelectedWords(string _sentence, int _wordCount)
{
string astr;
string[] words = new string[_wordCount];
string[] splitSentence = new string[_wordCount];
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Type in the words you wish to be censored: ");
words[i] = Console.ReadLine();
astr = "";
for (int j = 0; j < words[I].Length; j++)
astr += "*";
_sentence = _sentence.Replace(word[i], astr);
}
Console.WriteLine(_sentence);
}
I'm slightly confused at what the output should be, but here's one way to do it. I've extracted the functionality of replacing a word with censored text into separate function so it can be modified independently.
The rest is very simple - get a sentence, get a list of censored words, then replace all the words with their censored counterparts in the sentence and display it:
public static string HideAllButFirstAndLast(string word)
{
if (word == null) return null;
if (word.Length < 4) return new string('*', word.Length);
return word[0] + new string('*', word.Length - 2) + word[word.Length - 1];
}
private static void Main()
{
Console.WriteLine("Enter a sentence: ");
var sentence = Console.ReadLine();
Console.WriteLine("Enter a comma-separated list of censored words:");
var censoredWords = Console.ReadLine()
.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
.Select(word => word.Trim())
.ToList();
// Split sentence into words, replace words as needed, and join the words again
sentence = string.Join(" ", sentence.Split().Select(word =>
censoredWords.Contains(word, StringComparer.OrdinalIgnoreCase)
? HideAllButFirstAndLast(word)
: word));
Console.WriteLine(sentence);
GetKeyFromUser("\n\nDone! Press any key to exit...");
}
Output
I am using the following function to split a string into chunks
public static IList<string> SplitChunks(string text, int chunkSize)
{
List<string> chunks = new List<string>();
int offset = 0;
while (offset < text.Length)
{
int size = Math.Min(chunkSize, text.Length - offset);
chunks.Add(text.Substring(offset, size));
offset += size;
}
return chunks;
}
Works fine but the issue is in many cases the chunk ends with an incomplete word such as
Input:
String: Hello Everyone. How are you?
Size: 10
Output:
Hello Ever
where I want it to return a full last word such as Hello Everyone
How can I modify my function so the last word is a full word regardless of the size of the chunk
You could split the string into words and then try to generate chunks of at least chunkSize size:
public static IList<string> SplitChunks(string text, int chunkSize)
{
var words = text.Split(' ');
var result = new List<string>();
int length = 0;
string current = "";
foreach(var word in words)
{
current += word + " ";
length += word.Length + 1;
if (length > chunkSize) {
result.Add(current);
current = "";
length = 0;
}
}
if (current != "")
result.Add(current);
return result;
}
You could do something like this, but it's a bit ugly because it's producing a side effect in the TakeWhile:
int count = 0;
const string text = "Hello Everyone. How are you?";
var ret = text.TakeWhile(s =>
{
var keepTaking = count < max;
count += s.Length + 1; // +1 for the space between words
return keepTaking;
});
Try this one too:
public static IList<string> SplitChunks(string text, int chunkSize)
{
var parts = text.Split(' ');
return parts.Skip(1).Aggregate(parts.Take(1).ToList(), (a, x) =>
{
if ((a.Last() + x).Length > chunkSize)
a.Add(x);
else
a[a.Count - 1] += " " + x;
return a;
});
}
When I call SplitChunks("Hello Everyone. How are you?", 10) I get this:
Hello
Everyone.
How are
you?
I would like to check if file containing some strings, separated with # contains double repeat sign. Example:
I have a file like this:
1234#224859#123567
I am reading this file and putting strings separated with # it into array.
I would like to find which strings have a digit repeated next to each other (in this case 224859) and return position of first digit that repeats in this string?
This is what I have so far:
ArrayList list = new ArrayList();
OpenFileDialog openFile1 = new OpenFileDialog();
int size = -1;
DialogResult dr = openFile1.ShowDialog();
string file = openFile1.FileName;
try
{
string text = File.ReadAllText(file);
size = text.Length;
string temp = "";
for (int i = 0; i < text.Length; i++)
{
if (text[i] != '#')
{
temp += text[i].ToString();
}
else
{
list.Add(temp);
temp = "";
}
}
}
catch (IOException)
{
}
string all_values = "";
foreach (Object obj in list)
{
all_values += obj.ToString() + " => ";
Console.WriteLine(" => ", obj);
}
textBox1.Text = (all_values);
This regex should do the trick.
var subject = "1234#224859#123567";
foreach(var item in subject.Split('#'))
{
var regex = new Regex(#"(?<grp>\d)\k<grp>");
var match =regex.Match(item);
if(match.Success)
{
Console.WriteLine("Index : {0}, Item:{1}", match.Index, item);
//prints Index : 0, Item:224859
}
}
This is a more procedural approach than Sriram's, but the main benefit is remembering your results in order to use them later in your program.
Basically, the string is split based on the # delimiter, which returns a string[] which holds each number inside. Then, for each string you iterate through the characters and check to see if the current character at i matches the next character at i + 1. If so, the earliest appearance of a duplicate digit is at i, so i is remembered and we break out of the loop that processes chars.
Since int is a non-nullable type, I decided to use -1 to indicate that a match was not found in a string.
Dictionary<string, int> results = new Dictionary<string, int>();
string text = "1234#224859#123567#11#4322#43#155";
string[] list = text.Split('#');
foreach (string s in list)
{
int tempResult = -1;
for (int i = 0; i < s.Length - 1; i++)
{
if(s.ElementAt(i) == s.ElementAt(i + 1))
{
tempResult = i;
break;
}
}
results.Add(s, tempResult);
}
foreach (KeyValuePair<string, int> pair in results)
{
Console.WriteLine(pair.Key + ": " + pair.Value);
}
Output:
1234: -1
224859: 0
123567: -1
11: 0
4322: 2
43: -1
155: 1
here's another Regex that works
int indexof = -1;
String input = "3492883#32280948093284#990303294";
string[] numbers = input.Split('#');
foreach(string n in numbers)
{
Match m=Regex.Match(n, #"(\d)\1+");
if (m.Success)
{
indexof = m.Index;
}
}
Would this do what you are looking for?
string text = File.ReadAllText(file);
string[] list = text.Split(new char[] { '#' });
Then, after you have the strings separated:
foreach (string s in list)
{
int pos = HasDoubleCharacter(s);
if (pos > -1)
{
// do something
}
}
private static int HasDoubleCharacter(string text)
{
int pos = 0;
char[] c3 = text.ToCharArray();
char lastChar = (char)0;
foreach (char c in c3)
{
if (lastChar == c)
return pos;
lastChar = c;
pos++;
}
return -1;
}
Or are you just looking for the list of positions of all doubles in the original text. If so (and you don't need to act on the various strings separately, you might try this:
private static List<int> FindAllDoublePositions(string text)
{
List<int> positions = new List<int>();
char[] ca = text.ToCharArray();
char lastChar = (char)0;
for (int pos = 0; pos < ca.Length; pos++)
{
if (Char.IsNumber(ca[pos]) && lastChar == ca[pos])
positions.Add(pos);
lastChar = ca[pos];
}
return positions;
}
If your looking for a specific string pattern, Regex is most likely to be your best friend :
string text = "1234#224859#123567asdashjehqwjk4234#244859#123567asdhajksdhqjkw1434#244859#123567";
var results = Regex.Matches(text, #"\d{4}#(?<Value>\d{6})#\d{4}");
var allValues = "";
foreach (Match result in results)
{
allValues = result.Groups["Value"].Value + " => ";
Console.WriteLine(" => ", result.Value);
}
I have the following text in my RIchTextBox:
foo:baa#done baa
a:b#pending ee
and I want highlight all after # and before " "(espace)
How I do this? I tried make the end as IndexOf of \t or " " but it returns -1.
My code(not working as expected):
string[] lines = list.Lines;
string line;
for (int i = 0, max = lines.Length; i < max; i++)
{
line = lines[i];
int start = list.Find("#");
int end = ??? // I tried list.Find("\t") and list.Find(" ")
if (-1 != start || -1 != end)
{
list.Select(start, end);
list.SelectionColor = color;
}
}
list is an RichTextBox
Use GetLineFromCharIndex() to get the line number of the Find() method return value. Then GetFirstCharIndexFromLine(line + 1) to know where the next line starts. That gives you the SelectionStart and SelectionLength values you need to highlight the text.
try this:
string[] lines = list.Lines;
string line;
int len = 0;
for (int i = 0, max = lines.Length; i < max; i++)
{
line = lines[i];
int j = i == 0 ? 0 : len;
string str = Regex.Match(line, #"#.*$").Value;
if (!string.IsNullOrEmpty(str))
{
int start = list.Find(str, j, RichTextBoxFinds.None);
if (start != -1)
{
list.Select(start, str.Length);
list.SelectionColor = Color.Red;
}
len += line.Length;
}
}
Maybe you should use line.IndexOf instead of list.Find?
In short, you seem to be searching for characters in your List control, not in the string line.