C# - Displaying character count without counting spaces? - c#

This program counts and displays the number of words and the number of characters as the user is typing. The "word counter" is working fine, but I cannot figure out how to count the characters without counting the spaces in between.
private void userTextBox_TextChanged(object sender, EventArgs e)
{
string userInput = userTextBox.Text;
userInput = userInput.Trim();
string[] wordCount = userInput.Split(null);
//Here is my error
string[] charCount = wordCount.Length;
wordCountOutput.Text = wordCount.Length.ToString();
charCountOutput.Text = charCount.Length.ToString();
}

Since you're name is "Learning2Code" I thought I'd give you an answer that fixes your original attempt using the least advanced technique:
private void userTextBox_TextChanged(object sender, EventArgs e)
{
string userInput = userTextBox.Text;
userInput = userInput.Trim();
string[] wordCount = userInput.Split(null);
int charCount = 0;
foreach (var word in wordCount)
charCount += word.Length;
wordCountOutput.Text = wordCount.Length.ToString();
charCountOutput.Text = charCount.ToString();
}

You could use LINQ to count characters without white-spaces:
int charCount = userInput.Count(c => !Char.IsWhiteSpace(c));
However, your code suggests that you just don't know how to count the words, so
replace
string[] charCount = wordCount.Length;
with
int words = wordCount.Length;

You have each word already, so count the characters in each word and sum the total:
var charCount = words.Sum(w => w.Length);
Note: you stored the word array as 'wordCount' - I renamed it to just 'words' in the above snippet to be semantically correct. ie:
string[] words = userInput.Split(null);

Just replace all the spaces (and new lines characters) with Regex:
Regex.Replace(inputString, "[\s\n]", "");

There is one space less than the number of words (for example "once upon a time" contains four words and three spaces), so you can calculate the number of spaces. Then just subtract the number of spaces from the length of the input string:
int charCount = userInput.Length - (wordCount.Length - 1);
As that is an integer and not a string array, don't use Length when you output the result:
charCountOutput.Text = charCount.ToString();

Related

Split string into multiple smaller strings

I have a multiline textbox that contains 10 digit mobile numbers separated by comma. I need to achieve string in group of at least 100 mobile numbers.
100 mobile numbers will be separated by 99 comma in total. What i am trying to code is to split the strings containing commas less than 100
public static IEnumerable<string> SplitByLength(this string str, int maxLength)
{
for (int index = 0; index < str.Length; index += maxLength) {
yield return str.Substring(index, Math.Min(maxLength, str.Length - index));
}
}
By using above code, I can achieve 100 numbers as 100 numbers will have 10*100(for mobile number)+99(for comma) text length. But the problem here is user may enter wrong mobile number like 9 digits or even 11 digits.
Can anyone guide me on how can I achieve this.
Thank you in advance.
You could use this extension method to put them into max-100 number groups:
public static IEnumerable<string[]> SplitByLength(this string str, string[] splitBy, StringSplitOptions options, int maxLength = int.MaxValue)
{
var allTokens = str.Split(splitBy, options);
for (int index = 0; index < allTokens.Length; index += maxLength)
{
int length = Math.Min(maxLength, allTokens.Length - index);
string[] part = new string[length];
Array.Copy(allTokens, index, part, 0, length);
yield return part;
}
}
Sample:
string text = string.Join(",", Enumerable.Range(0, 1111).Select(i => "123456789"));
var phoneNumbersIn100Groups = text.SplitByLength(new[] { "," }, StringSplitOptions.None, 100);
foreach (string[] part in phoneNumbersIn100Groups)
{
Assert.IsTrue(part.Length <= 100);
Console.WriteLine(String.Join("|", part));
}
You have a few options,
Put some kind of mask on the input data to prevent the user entering invalid data. In your UI you could then flag the error and prompt the user to reenter correct information. If you go down this route then something like this string[] nums = numbers.Split(','); will be fine.
Alternatively, you could use regex.split or regex.match and match on the pattern. Something like this should work assuming your numbers are in a string with a leading comma or space
Regex regex = new Regex("(\s|,)\d{10},)";
string[] nums = regex.Split(numbers);
This be can resolved with a simple Linq code
public static IEnumerable<string> SplitByLength(this string input, int groupSize)
{
// First split the input to the comma.
// this will give us an array of all single numbers
string[] numbers = input.Split(',');
// Now loop over this array in groupSize blocks
for (int index = 0; index < numbers.Length; index+=groupSize)
{
// Skip numbers from the starting position and
// take the following groupSize numbers,
// join them in a string comma separated and return
yield return string.Join(",", numbers.Skip(index).Take(groupSize));
}
}

Count Words and Extract numbers from string and sum them

1) I need to count how much words i have in the sentence.
But what if i have more than one white space? It will count as a word. Need solution for this.
There is four words. / count as 4 words
There is four words. / count as 5 words
I use:
int countWords = txt.Split().Length;
2) I need to extract numbers from string and then get sum. My code is not working, No overload for method error.
All my code:
Console.Write("Ievadiet tekstu: ");
string txt = Console.ReadLine();
int sum = 0;
int countWords = txt.Split().Length;
foreach (char num in txt)
{
if (char.IsDigit(num))
sum += Int32.TryParse(num).ToString();
}
Console.WriteLine("There are {0} words in this sentence.",countWords);
Console.WriteLine("Summ is "+sum);
Use the overload of String.Split with StringSplitOptions.RemoveEmptyEntries. You can use an empty char[](or string[]) to get the same behaviour as String.Split without an argument, so that it splits by all white-space characters like space,tab or new-line characters.
If you want to sum the "words" which could be parsed to int then do that, use int.TryParse on all words which were extracted by String.Split. You could use LINQ:
string[] words = text.Split(new char[] {}, StringSplitOptions.RemoveEmptyEntries);
int wordCount = words.Length;
int num = 0;
int sum = words.Where(w => int.TryParse(w, out num)).Sum(w => num);
Here is a simple console app to do what you intend to.
It uses a Regular expression to capture number characters and sums them. The TryParse is just a fail-safe (i believe it is not needed in this case since the regex ensures only digits are captured).
static void Main(string[] args)
{
Regex digitRegex = new Regex("(\\d)");
string text = Console.ReadLine();
int wordCount = text.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries).Length;
int sum = 0;
foreach (Match x in digitRegex.Matches(text, 0))
{
int num;
if (int.TryParse(x.Value, out num))
sum += num;
}
Console.WriteLine("Word Count:{0}, Digits Total:{1}", wordCount, sum);
Console.ReadLine();
}
Hope it helps. Cheers

Split big text string into small ones

I'm reading text file into one string and then spliting the whole file into array of strings with this code:
string[] split_text = Regex.Split(whole_text, #"\W+");
But when I do that every word is alone on one index and I don't want that.
I want biger string on one index let say about 10 words on one index in array and then 10 words on second index and so on.
So if I read file of 90 words I want to have size of array 9 and on every index 10 words.
You can use Batch method:
string[] split_text = Regex.Split(whole_text, #"\W+")
.Batch(10)
.Select(x => string.Concat(x))
.ToArray();
ok there is full sollution :
class Program
{
static void Main(string[] args)
{
List<string> result = new List<string>();
string text = "Now im checking first ten chars from sentence and some random chars : asdasdasdasdasdasdasdasd";
try
{
for (int i = 0; i < text.Length; i = i + 10)
{
string res = text.Substring(i,10);
result.Add(res);
Console.WriteLine(res);
}
}
catch (Exception)
{
}
}
}
I recommend use List<string> instead of array of strings.

C# StreamReader, trouble splitting at new line

I have a global string variable - "word".
string word = "";
List<Label> labels = new List<Label>();
int amount = 0;
That word is then defined/assigned in the following two functions by parsing a text document (new line delimited)
void MakeLabels()
{
word = GetRandomWord();
char[] chars = word.ToCharArray();
...
}
string GetRandomWord()
{
System.IO.StreamReader myFile = new System.IO.StreamReader(...);
string myString = myFile.ReadToEnd();
string[] words = myString.Split('\n');
Random ran = new Random();
return words[ran.Next(0, words.Length - 1)];
}
And, finally, an event that validates the contents of a textbox against the "word" variable.
private void button2_Click(object sender, EventArgs e)
{
if (textBox2.Text == word)
{
MessageBox.Show(...);
}
else
{
MessageBox.Show(...);
textBox2.Text = "";
textBox1.Focus();
Reset();
}
The problem I'm having is that even when textBox2 is equivalent to "word", I'm receiving the MessageBox related to the else statement. I think it has to do with the "word" variable carrying in the '\n'; meaning that textBox2.Text = apple and word = apple\n, thus the two variables not being equivalent. Any suggestions?
1) Newlines in windows environments are \r\n, not \n. Splitting on \n is insufficient.
2) Contrary to suggestions, you cannot simply call someString.Split(Environment.NewLine).
There is no overload that simply takes a string. You could call someString.Split(Environment.NewLine.ToCharArray()) but will have additional concerns you need to consider.
Say we have an input, string test = "test1\r\ntest2". If you call test.Split('\n'), the resulting array will have two elements: array[0] will be "test1\r" and array[1] will be "test2"... But if you call test.Split(Environment.NewLine.ToCharArray()) then you'll get an array with three elements: array[0] will be "test1", array[1] will be "", and array[2] will be "test2"... Edited to add: You can combat that by calling test.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).
3) As one person suggested, calling string.Trim() would remove \r. Thus, return words[ran.Next(0, words.Length - 1)] could be changed to return words[ran.Next(0, words.Length - 1)].Trim() to eliminate the \r without making changes to your current split code.
If you're sure that your problem is the line break at the end of the string, you should take a look at the String.Trim() method.
Use something like the following
string[] parseStr = myTest.Split(new string[]{Environment.NewLine},StringSplitOptions.None);
CRLF parsing blues in C#
string GetRandomWord()
{
string[] linse= System .IO.File .ReadAllLines (......) ;
string mlines = "";
foreach (string line in linse)
{
if (line.Trim() != "")
if(mlines=="")
mlines = line;
else
mlines = mlines +"\n"+ line;
}
string[] words = mlines. Split('\n');
Random ran = new Random();
return words[ran.Next(0, words.Length - 1)];
}

Getting parts of a string and combine them in C#?

I have a string like this: C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg
Now, what I want to do is to dynamically combine the last 4 numbers, in this case its 10000080 as result. My idea was ti split this and combine them in some way, is there an easier way? I cant rely on the array index, because the path can be longer or shorter as well.
Is there a nice way to do that?
Thanks :)
A compact way using string.Join and Regex.Split.
string text = #"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
string newString = string.Join(null, Regex.Split(text, #"[^\d]")); //10000080
Use String.Split
String toSplit = "C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
String[] parts = toSplit.Split(new String[] { #"\" });
String result = String.Empty;
for (int i = 5, i > 1; i--)
{
result += parts[parts.Length - i];
}
// Gives the result 10000080
You can rely on array index if the last part always is the filename.
since the last part is always
array_name[array_name.length - 1]
the 4 parts before that can be found by
array_name[array_name.length - 2]
array_name[array_name.length - 3]
etc
If you always want to combine the last four numbers, split the string (use \ as the separator), start counting from the last part and take 4 numbers, or the 4 almost last parts.
If you want to take all the digits, just scan the string from start to finish and copy just the digits to a new string.
string input = "C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
string[] parts = toSplit.Split(new char[] {'\\'});
IEnumerable<string> reversed = parts.Reverse();
IEnumerable<string> selected = reversed.Skip(1).Take(4).Reverse();
string result = string.Concat(selected);
The idea is to extract the parts, reverse them to keep only the last 4 (excluding the file name) and re reversing to rollback to the initial order, then concat.
Using LINQ:
string path = #"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
var parts = Path.GetDirectoryName(path).Split('\\');
string numbersPart = parts.Skip(parts.Count() - 4)
.Aggregate((acc, next) => acc + next);
Result: "10000080"
var r = new Regex(#"[^\d+]");
var match = r
.Split(#"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg")
.Aggregate((i, j) => i + j);
return match.ToString();
to find the number you can use regex:
(([0-9]{2})\\){4}
use concat all inner Group ([0-9]{2}) to get your searched number.
This will always find your searched number in any position in the given string.
Sample Code:
static class TestClass {
static void Main(string[] args) {
string[] tests = { #"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg",
#"C:\Projects\test\whatever\files\media\10\00\00\80\some\foldertest.jpg",
#"C:\10\00\00\80\test.jpg",
#"C:\10\00\00\80\test.jpg"};
foreach (string test in tests) {
int number = ExtractNumber(test);
Console.WriteLine(number);
}
Console.ReadLine();
}
static int ExtractNumber(string path) {
Match match = Regex.Match(path, #"(([0-9]{2})\\){4}");
if (!match.Success) {
throw new Exception("The string does not contain the defined Number");
}
//get second group that is where the number is
Group #group = match.Groups[2];
//now concat all captures
StringBuilder builder = new StringBuilder();
foreach (var capture in #group.Captures) {
builder.Append(capture);
}
//pares it as string and off we go!
return int.Parse(builder.ToString());
}
}

Categories

Resources