I'm new to programming so I wasn't really sure how to title this, but I'm trying to replace letters in a string builder object by comparing it to a strings Substrings but it will only work with the last letter, why? And how do I replace the middle letters in the same fashion?
string S = "Hello";
StringBuilder sB = new StringBuilder("*****");
Console.WriteLine(sB);
string userInput = Console.ReadLine();
for (int i = 0; i < 5; i++)
{
if (userInput == S.Substring(i))
{
sB.Remove(i, 1);
sB.Insert(i, userInput);
Console.WriteLine(sB);
}
}
Console.ReadKey();
Any help would be appreciated.
The string.Substring(int) method returns the whole substring starting at the indicated character index, not just one character.
For retrieving the ith caracter of S, use S[i].
Substring with only 1 parameter will take everything from that position to the end of the string ("Hello".Substring(1) would be "ello"). To take only one letter you need to provide a second parameter for the length ("Hello".Substring(1,1) would be "e").
if (userInput.Substring(i, 1) == S.Substring(i, 1))
{
sB.Remove(i, 1);
sB.Insert(i, userInput.Substring(i, 1));
Console.WriteLine(sB);
}
You may be interested in using String.Contains(string comparison) to simply see if a string is within another. Also, String.Replace(string target, string replacement) to replace variable-length strings rather than looping through characters.
Related
I am developing as application in asp.net mvc.
I have a string like below
string myString = "1A5#3a2#"
now I want to add a comma after every occurrence of number in my string except the first occurrence.
like
string myNewString "1A,5#,3a,2#";
I know I can use loop for this like below
myNewString
foreach(var ch in myString)
{
if (ch >= '0' && ch <= '9')
{
myNewString = myNewString ==""?"":myNewString + "," + Convert.ToString(ch);
}
else
{
myNewString = myNewString ==""? Convert.ToString(ch): myNewString + Convert.ToString(ch);
}
}
You could use this StringBuilder approach:
public static string InsertBeforeEveryDigit(string input, char insert)
{
StringBuilder sb = new(input);
for (int i = sb.Length - 2; i >= 0; i--)
{
if (!char.IsDigit(sb[i]) && char.IsDigit(sb[i+1]))
{
sb.Insert(i+1, insert);
}
}
return sb.ToString();
}
Console.Write(InsertBeforeEveryDigit("1A5#3a2#", ',')); // 1A,5#,3a,2#
Update: This answer gives a different result than the one from TWM if the string contains consecutive digits like here: "12A5#3a2#". My answer gives: 12A,5#,3a,2#,
TWM's gives: 1,2A,5#,3a,2#. Not sure what is desired.
so, as I understood the below code will work for you
StringBuilder myNewStringBuilder = new StringBuilder();
foreach(var ch in myString)
{
if (ch >= '0' && ch <= '9')
{
if (myNewStringBuilder.Length > 0)
{
myNewStringBuilder.Append(",");
}
myNewStringBuilder.Append(ch);
}
else
{
myNewStringBuilder.Append(ch);
}
}
myString = myNewStringBuilder.ToString();
NOTE
Instead of using myNewString variable, I've used StringBuilder object to build up the new string. This is more efficient than concatenating strings, as concatenating strings creates new strings and discards the old ones. The StringBuilder object avoids this by efficiently storing the string in a mutable buffer, reducing the number of object allocations and garbage collections.
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. 😊
string myString = "1A5#3a2#";
var result = Regex.Replace(myString, #"(?<=\d\D*)\d\D*", ",$&");
Regex explanation (#regex101):
\d\D* - matches every occurrence of a digit with any following non-digits (zero+)
(?<=\d\D*) - negative lookbehind so we have at least one group with digit before (i.e. ignore first)
This can be updated if you need to handle consecutive digits (i.e. "1a55b" -> "1a,55b") by changing \d to \d+:
var result = Regex.Replace(myString, #"(?<=\d+\D*)\d+\D*", ",$&");
This question already has answers here:
Split string and get first value only
(4 answers)
Closed 7 years ago.
I have declared a string and i want to get the second word from the string. For eg.
string str = "Hello world";
And I want to get the word "world" from str.
The simplest answer is to Split on space, and take the second item:
var secondWord = str.Split(' ').Skip(1).FirstOrDefault();
I use FirstOrDefault here so you get a valid null result for input of just one word.
The downside though is it will parse the entire string, so this is not a good suggestion if you want the second word of a book.
Or, you can make use of IndexOf to find the first and second occurrence of space, then Substring to take that portion:
static string GetSecondWord(string str)
{
var startIndex = str.IndexOf(' ') + 1;
if (startIndex == 0 || startIndex == str.Length)
return null;
var endIndex = str.IndexOf(" ", startIndex, StringComparison.CurrentCulture);
if (endIndex == -1)
endIndex = str.Length - 1;
return str.Substring(startIndex, endIndex - startIndex + 1);
}
This only looks through as many characters as you need, then copies out the portion you want in the end. It will perform better than the above. But it probably doesn't matter unless you're cataloging the second word of every book ever published.
Or, do it the old-fashioned way. Go through each character until you find the first space, then keep characters until the next one or the end of the string:
var sb = new StringBuilder();
bool spaceFound = false;
foreach(var c in str)
{
if(c == ' ')
{
if (spaceFound) //this is our second space so we're done
break;
spaceFound = true;
}
else
{
if (!spaceFound) //we haven't found a space yet so move along
continue;
sb.Append(c);
}
}
var secondWord = sb.ToString();
This method should be comparable in performance to the second one. You could accomplish the same thing using an enumerator instead of a foreach loop, but I'll leave that as an exercise for the reader. :)
You can do this. I suggest doing search before asking simple questions.
str.Split(' ')[1]
Demo code
Please note you have to include validations to your input, like string has more than one word, etc..
This is the perfect answer I think
//single space(or)
string line = "Hello world";
//double space(or)
string line = "Hello world";
//multiple space(or)
string line = "Hello world";
//multiple Strings
string line = "Hello world Hello world";
//all are working fine
string[] allId = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string finalstr = allId[allId.Length-1];
I want to find number of letter "a" in only first sentence. The code below finds "a" in all sentences, but I want in only first sentence.
static void Main(string[] args)
{
string text; int k = 0;
text = "bla bla bla. something second. maybe last sentence.";
foreach (char a in text)
{
char b = 'a';
if (b == a)
{
k += 1;
}
}
Console.WriteLine("number of a in first sentence is " + k);
Console.ReadKey();
}
This will split the string into an array seperated by '.', then counts the number of 'a' char's in the first element of the array (the first sentence).
var count = Text.Split(new[] { '.', '!', '?', })[0].Count(c => c == 'a');
This example assumes a sentence is separated by a ., ? or !. If you have a decimal number in your string (e.g. 123.456), that will count as a sentence break. Breaking up a string into accurate sentences is a fairly complex exercise.
This is perhaps more verbose than what you were looking for, but hopefully it'll breed understanding as you read through it.
public static void Main()
{
//Make an array of the possible sentence enders. Doing this pattern lets us easily update
// the code later if it becomes necessary, or allows us easily to move this to an input
// parameter
string[] SentenceEnders = new string[] {"$", #"\.", #"\?", #"\!" /* Add Any Others */};
string WhatToFind = "a"; //What are we looking for? Regular Expressions Will Work Too!!!
string SentenceToCheck = "This, but not to exclude any others, is a sample."; //First example
string MultipleSentencesToCheck = #"
Is this a sentence
that breaks up
among multiple lines?
Yes!
It also has
more than one
sentence.
"; //Second Example
//This will split the input on all the enders put together(by way of joining them in [] inside a regular
// expression.
string[] SplitSentences = Regex.Split(SentenceToCheck, "[" + String.Join("", SentenceEnders) + "]", RegexOptions.IgnoreCase);
//SplitSentences is an array, with sentences on each index. The first index is the first sentence
string FirstSentence = SplitSentences[0];
//Now, split that single sentence on our matching pattern for what we should be counting
string[] SubSplitSentence = Regex.Split(FirstSentence, WhatToFind, RegexOptions.IgnoreCase);
//Now that it's split, it's split a number of times that matches how many matches we found, plus one
// (The "Left over" is the +1
int HowMany = SubSplitSentence.Length - 1;
System.Console.WriteLine(string.Format("We found, in the first sentence, {0} '{1}'.", HowMany, WhatToFind));
//Do all this again for the second example. Note that ideally, this would be in a separate function
// and you wouldn't be writing code twice, but I wanted you to see it without all the comments so you can
// compare and contrast
SplitSentences = Regex.Split(MultipleSentencesToCheck, "[" + String.Join("", SentenceEnders) + "]", RegexOptions.IgnoreCase | RegexOptions.Singleline);
SubSplitSentence = Regex.Split(SplitSentences[0], WhatToFind, RegexOptions.IgnoreCase | RegexOptions.Singleline);
HowMany = SubSplitSentence.Length - 1;
System.Console.WriteLine(string.Format("We found, in the second sentence, {0} '{1}'.", HowMany, WhatToFind));
}
Here is the output:
We found, in the first sentence, 3 'a'.
We found, in the second sentence, 4 'a'.
You didn't define "sentence", but if we assume it's always terminated by a period (.), just add this inside the loop:
if (a == '.') {
break;
}
Expand from this to support other sentence delimiters.
Simply "break" the foreach(...) loop when you encounter a "." (period)
Well, assuming you define a sentence as being ended with a '.''
Use String.IndexOf() to find the position of the first '.'. After that, searchin a SubString instead of the entire string.
find the place of the '.' in the text ( you can use split )
count the 'a' in the text from the place 0 to instance of the '.'
string SentenceToCheck = "Hi, I can wonder this situation where I can do best";
//Here I am giving several way to find this
//Using Regular Experession
int HowMany = Regex.Split(SentenceToCheck, "a", RegexOptions.IgnoreCase).Length - 1;
int i = Regex.Matches(SentenceToCheck, "a").Count;
// Simple way
int Count = SentenceToCheck.Length - SentenceToCheck.Replace("a", "").Length;
//Linq
var _lamdaCount = SentenceToCheck.ToCharArray().Where(t => t.ToString() != string.Empty)
.Select(t => t.ToString().ToUpper().Equals("A")).Count();
var _linqAIEnumareable = from _char in SentenceToCheck.ToCharArray()
where !String.IsNullOrEmpty(_char.ToString())
&& _char.ToString().ToUpper().Equals("A")
select _char;
int a =linqAIEnumareable.Count;
var _linqCount = from g in SentenceToCheck.ToCharArray()
where g.ToString().Equals("a")
select g;
int a = _linqCount.Count();
I'm trying to find an efficient way to take an input string and capitalize the first letter after every punctuation mark (. : ? !) which is followed by a white space.
Input:
"I ate something. but I didn't:
instead, no. what do you think? i
think not! excuse me.moi"
Output:
"I ate something. But I didn't:
Instead, no. What do you think? I
think not! Excuse me.moi"
The obvious would be to split it and then capitalize the first char of every group, then concatenate everything. But it's uber ugly. What's the best way to do this? (I'm thinking Regex.Replace using a MatchEvaluator that capitalizes the first letter but would like to get more ideas)
Thanks!
Fast and easy:
static class Ext
{
public static string CapitalizeAfter(this string s, IEnumerable<char> chars)
{
var charsHash = new HashSet<char>(chars);
StringBuilder sb = new StringBuilder(s);
for (int i = 0; i < sb.Length - 2; i++)
{
if (charsHash.Contains(sb[i]) && sb[i + 1] == ' ')
sb[i + 2] = char.ToUpper(sb[i + 2]);
}
return sb.ToString();
}
}
Usage:
string capitalized = s.CapitalizeAfter(new[] { '.', ':', '?', '!' });
Try this:
string expression = #"[\.\?\!,]\s+([a-z])";
string input = "I ate something. but I didn't: instead, no. what do you think? i think not! excuse me.moi";
char[] charArray = input.ToCharArray();
foreach (Match match in Regex.Matches(input, expression,RegexOptions.Singleline))
{
charArray[match.Groups[1].Index] = Char.ToUpper(charArray[match.Groups[1].Index]);
}
string output = new string(charArray);
// "I ate something. But I didn't: instead, No. What do you think? I think not! Excuse me.moi"
I use an extension method.
public static string CorrectTextCasing(this string text)
{
// /[.:?!]\\s[a-z]/ matches letters following a space and punctuation,
// /^(?:\\s+)?[a-z]/ matches the first letter in a string (with optional leading spaces)
Regex regexCasing = new Regex("(?:[.:?!]\\s[a-z]|^(?:\\s+)?[a-z])", RegexOptions.Multiline);
// First ensure all characters are lower case.
// (In my case it comes all in caps; this line may be omitted depending upon your needs)
text = text.ToLower();
// Capitalize each match in the regular expression, using a lambda expression
text = regexCasing.Replace(text, s => (s.Value.ToUpper));
// Return the new string.
return text;
}
Then I can do the following:
string mangled = "i'm A little teapot, short AND stout. here IS my Handle.";
string corrected = s.CorrectTextCasing();
// returns "I'm a little teapot, short and stout. Here is my handle."
Using the Regex / MatchEvaluator route, you could match on
"[.:?!]\s[a-z]"
and capitalize the entire match.
Where the text variable contains the string
string text = "I ate something. but I didn't: instead, no. what do you think? i think not! excuse me.moi";
string[] punctuators = { "?", "!", ",", "-", ":", ";", "." };
for (int i = 0; i< 7;i++)
{
int pos = text.IndexOf(punctuators[i]);
while(pos!=-1)
{
text = text.Insert(pos+2, char.ToUpper(text[pos + 2]).ToString());
text = text.Remove(pos + 3, 1);
pos = text.IndexOf(punctuators[i],pos+1);
}
}
how to change
XXX#YYY.ZZZ into XXX_YYY_ZZZ
One way i know is to use the string.replace(char, char) method,
but i want to replace "#" & "." The above method replaces just one char.
one more case is what if i have XX.X#YYY.ZZZ...
i still want the output to look like XX.X_YYY_ZZZ
Is this possible?? any suggestions thanks
So, if I'm understanding correctly, you want to replace # with _, and . with _, but only if . comes after #? If there is a guaranteed # (assuming you're dealing with e-mail addresses?):
string e = "XX.X#YYY.ZZZ";
e = e.Substring(0, e.IndexOf('#')) + "_" + e.Substring(e.IndexOf('#')+1).Replace('.', '_');
Here's a complete regex solution that covers both your cases. The key to your second case is to match dots after the # symbol by using a positive look-behind.
string[] inputs = { "XXX#YYY.ZZZ", "XX.X#YYY.ZZZ" };
string pattern = #"#|(?<=#.*?)\.";
foreach (var input in inputs)
{
string result = Regex.Replace(input, pattern, "_");
Console.WriteLine("Original: " + input);
Console.WriteLine("Modified: " + result);
Console.WriteLine();
}
Although this is simple enough to accomplish with a couple of string Replace calls. Efficiency is something you will need to test depending on text size and number of replacements the code will make.
You can use the Regex.Replace method:
http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.replace(v=VS.90).aspx
You can use the following extension method to do your replacement without creating too many temporary strings (as occurs with Substring and Replace) or incurring regex overhead. It skips to the # symbol, and then iterates through the remaining characters to perform the replacement.
public static string CustomReplace(this string s)
{
var sb = new StringBuilder(s);
for (int i = Math.Max(0, s.IndexOf('#')); i < sb.Length; i++)
if (sb[i] == '#' || sb[i] == '.')
sb[i] = '_';
return sb.ToString();
}
you can chain replace
var newstring = "XX.X#YYY.ZZZ".Replace("#","_").Replace(".","_");
Create an array with characters you want to have replaced, loop through array and do the replace based off the index.
Assuming data format is like XX.X#YYY.ZZZ, here is another alternative with String.Split(char seperator):
string[] tmp = "XX.X#YYY.ZZZ".Split('#');
string newstr = tmp[0] + "_" + tmp[1].Replace(".", "_");