i have a string like this:
some_string = "A simple demo of SMS text messaging.\r\n+CMGW: 3216\r\n\r\nOK\r\n\"
im coming from vb.net and i need to know in c#, if i know the position of CMGW, how do i get "3216" out of there?
i know that my start should be the position of CMGW + 6, but how do i make it stop as soon as it finds "\r" ??
again, my end result should be 3216
thank you!
Find the index of \r from the start of where you're interested in, and use the Substring overload which takes a length:
// Production code: add validation here.
// (Check for each index being -1, meaning "not found")
int cmgwIndex = text.IndexOf("CMGW: ");
// Just a helper variable; makes the code below slightly prettier
int startIndex = cmgwIndex + 6;
int crIndex = text.IndexOf("\r", startIndex);
string middlePart = text.Substring(startIndex, crIndex - startIndex);
If you know the position of 3216 then you can just do the following
string inner = some_string.SubString(positionOfCmgw+6,4);
This code will take the substring of some_string starting at the given position and only taking 4 characters.
If you want to be more general you could do the following
int start = positionOfCmgw+6;
int endIndex = some_string.IndexOf('\r', start);
int length = endIndex - start;
string inner = some_string.SubString(start, length);
One option would be to start from your known index and read characters until you hit a non-numeric value. Not the most robust solution, but it will work if you know your input's always going to look like this (i.e., no decimal points or other non-numeric characters within the numeric part of the string).
Something like this:
public static int GetNumberAtIndex(this string text, int index)
{
if (index < 0 || index >= text.Length)
throw new ArgumentOutOfRangeException("index");
var sb = new StringBuilder();
for (int i = index; i < text.Length; ++i)
{
char c = text[i];
if (!char.IsDigit(c))
break;
sb.Append(c);
}
if (sb.Length > 0)
return int.Parse(sb.ToString());
else
throw new ArgumentException("Unable to read number at the specified index.");
}
Usage in your case would look like:
string some_string = #"A simple demo of SMS text messaging.\r\n+CMGW: 3216\r\n...";
int index = some_string.IndexOf("CMGW") + 6;
int value = some_string.GetNumberAtIndex(index);
Console.WriteLine(value);
Output:
3216
If you're looking to extract the number portion of 'CMGW: 3216' then a more reliable method would be to use regular expressions. That way you can look for the entire pattern, and not just the header.
var some_string = "A simple demo of SMS text messaging.\r\n+CMGW: 3216\r\n\r\nOK\r\n";
var match = Regex.Match(some_string, #"CMGW\: (?<number>[0-9]+)", RegexOptions.Multiline);
var number = match.Groups["number"].Value;
More general, if you don't know the start position of CMGW but the structure remains as before.
String s;
char[] separators = {'\r'};
var parts = s.Split(separators);
parts.Where(part => part.Contains("CMGW")).Single().Reverse().TakeWhile(c => c != ' ').Reverse();
Related
I need to count the number of points at the END of string.
The number of points in the middle of the string are not relevant and should not be countet.
How can this be done?
string sample = "This.is.a.sample.string.....";
for the example above the correct answer would be 5 because there are 5 points at the end of the string.
because of performace reasons I would prefer a fast solution. Don't know if Regular Expressions
\.*$
should be used in such a case.
Start from the end of the string and go back char by char until its not a dot:
string sample = "This.is.a.sample.string....."
int count = 0;
for (int i = sample.Length - 1; i >= 0; i--)
{
if (sample[i] != '.') break;
count++;
}
Using Linq:
var test = "this.is.a.test........";
var count = test.ToCharArray().Reverse().TakeWhile(q => q == '.').Count();
Convert string to array, reverse, then take while character = '.'. Count result.
A simple solution using an extension method.
var test = "this.is.a.test........";
Console.WriteLine(test.CountTrailingDots());
public static int CountTrailingDots(this string value)
{
return value.Length - value.TrimEnd('.').Length;
}
Using Regex:
int points = Regex.Match("This.is.a.sample.string....", #"^[\w\W]*?([.]*+)$").Groups[1].Value.Length;
Description:
*+ = Matches as many characters as possible
*? = Matches as few characters as possible.
It can be something like..
string sample = "This.is.a.sample.string.....";
int count = 0;
if(sample.EndsWith("."))
count = sample.Substring(sample.TrimEnd('.').Length).Length;
I have strings that look like this:
1.23.4.34
12.4.67
127.3.2.21.3
1.1.1.9
This is supposed to be a collection of numbers, separated by '.' symbols, similar to an ip address. I need to increment only the last digit/digits.
Expected Output:
1.23.4.35
12.4.68
127.3.2.21.4
1.1.1.10
Basically, increment whatever the number that is after the last '.' symbol.
I tried this:
char last = numberString[numberString.Length - 1];
int number = Convert.ToInt32(last);
number = number + 1;
If I go with the above code, I just need to replace the characters after the last '.' symbol with the new number. How do I get this done, good folks? :)
It seems to me that one method would be to:
split the string on . to get an array of components.
turn the final component into an integer.
increment that integer.
turn it back into a string.
recombine the components with . characters.
See, for example, the following program:
using System;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
String original = "1.23.4.34";
String[] components = original.Split('.');
int value = Int32.Parse(components[components.Length - 1]) + 1;
components[components.Length - 1] = value.ToString();
String newstring = String.Join(".",components);
Console.WriteLine(newstring);
}
}
}
which outputs the "next highest" value of:
1.23.4.35
You can use string.LastIndexOf().
string input = "127.3.2.21.4";
int lastIndex = input.LastIndexOf('.');
string lastNumber = input.Substring(lastIndex + 1);
string increment = (int.Parse(lastNumber) + 1).ToString();
string result = string.Concat(input.Substring(0, lastIndex + 1), increment);
You need to extract more than just the last character. What if the last character is a 9 and then you add 1 to it? Then you need to correctly add one to the preceding character as well. For example, the string 5.29 should be processed to become 5.30 and not simply 5.210 or 5.20.
So I suggest you split the string into its number sections. Parse the last section into an integer. Increment it and then create the string again. I leave it as an exercise for the poster to actually write the few lines of code. Good practice!
Something like this:
var ip = "1.23.4.34";
var last = int.Parse(ip.Split(".".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries).Last());
last = last + 1;
ip = string.Format("{0}.{1}",ip.Remove(ip.LastIndexOf(".")) , last);
If you are dealing with IP, there will be some extra code in case of .034, which should be 035 instead of 35. But that logic is not that complicated.
It's simple as this, use Split() and Join() String methods
String test = "1.23.4.34"; // test string
String[] splits = test.Split('.'); // split by .
splits[splits.Length - 1] = (int.Parse(splits[splits.Length - 1])+1).ToString(); // Increment last integer (Note : Assume all are integers)
String answ = String.Join(".",splits); // Use string join to make the string from string array. uses . separator
Console.WriteLine(answ); // Answer : 1.23.4.35
Using a bit of Linq
int[] int_arr = numberString.Split('.').Select(num => Convert.ToInt32(num)).ToArray();
int_arr[int_arr.Length - 1]++;
numberString = "";
for(int i = 0; i < int_arr.Length; i++) {
if( i == int_arr.Length - 1) {
numberString += int_arr[i].ToString();
}
else {
numberString += (int_arr[i].ToString() + ".");
}
}
Note: on phone so can't test.
My Solution is:
private static string calcNextCode(string value, int index)
{
if (value is null) return "1";
if (value.Length == index + 1) return value + "1";
int lastNum;
int myIndex = value.Length - ++index;
char myValue = value[myIndex];
if (int.TryParse(myValue.ToString(), NumberStyles.Integer, null, out lastNum))
{
var aStringBuilder = new StringBuilder(value);
if (lastNum == 9)
{
lastNum = 0;
aStringBuilder.Remove(myIndex, 1);
aStringBuilder.Insert(myIndex, lastNum);
return calcNextCode(aStringBuilder.ToString(), index++);
}
else
{
lastNum++;
}
aStringBuilder.Remove(myIndex, 1);
aStringBuilder.Insert(myIndex, lastNum);
return aStringBuilder.ToString();
}
return calcNextCode(value, index++);
}
I need to capitalize everything before the second - from the beginning of the string in .NET. What is the best way to do this? The string before the second dash can be anything. I need a new single string once this is complete.
Before
Tt-Fga - Louisville - Kentucky
After
TT-FGA - Louisville - Kentucky
This should get the job done for your specific case:
public static string ToUpperUntilSecondHyphen(string text)
{
int index = text.IndexOf('-', text.IndexOf('-') + 1);
return text.Substring(0, index).ToUpper() + text.Substring(index);
}
A more generalized method could look something like this:
public static string ToUpperUntilNthOccurrenceOfChar(string text, char c, int occurrences)
{
if (occurrences > text.Count(x => x == c))
{
return text.ToUpper();
}
int index = 0;
for (int i = 0; i < occurrences; i++, index++)
{
index = text.IndexOf(c, index);
}
return text.Substring(0, index).ToUpper() + text.Substring(index);
}
Identify the location of the hyphen with IndexOf. You'll have to use this function twice so that you can find the first hyphen, and then the second one.
Construct the substring that only contains the characters up to that with Substring. Construct the substring that contains all the remaining characters as well.
Upper case the first string with ToUpper.
Concatenate with the + operator.
(.*?-.*)(?=-)
You can use replace here.Replace with $1.upper() or something which is available in c#.
See
http://regex101.com/r/yR3mM3/50
I went ahead and did this. If there is a better answer let me know.
var parts = #event.EventParent.Name.Split(new[] {'-'}, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < parts.Length; i++)
{
if (i >= 2)
break;
parts[i] = parts[i].ToUpper();
}
#event.EventParent.Name = string.Join("-", parts);
Hello I'm try to remove special characters from user inputs.
public void fd()
{
string output = "";
string input = Console.ReadLine();
char[] charArray = input.ToCharArray();
foreach (var item in charArray)
{
if (!Char.IsLetterOrDigit(item))
{
\\\CODE HERE }
}
output = new string(trimmedChars);
Console.WriteLine(output);
}
At the end I'm turning it back to a string. My code only removes one special character in the string. Does anyone have any suggestions on a easier way instead
You have a nice implementation, just consider using next code, which is only a bit shorter, but has a little bit higher abstractions
var input = " th#ere's! ";
Func<char, bool> isSpecialChar = ch => !char.IsLetter(ch) && !char.IsDigit(ch);
for (int i = 1; i < input.Length - 1; i++)
{
//if current character is a special symbol
if(isSpecialChar(input[i]))
{
//if previous or next character are special symbols
if(isSpecialChar(input[i-1]) || isSpecialChar(input[i+1]))
{
//remove that character
input = input.Remove(i, 1);
//decrease counter, since we removed one char
i--;
}
}
}
Console.WriteLine(input); //prints " th#ere's "
A new string would be created each time you would call Remove. Use a StringBuilder for a more memory-performant solution.
The problem with your code is that you are taking the data from charArray and putting the result in trimmedChars for each change that you make, so each change will ignore all previous changes and work with the original. At the end you only have the last change.
Another problem with the code is that you are using IndexOf to get the index of a character, but that will get the index of the first occurance of that character, not the index where you got that character. For example when you are at the second ! in the string "foo!bar!" you will get the index of the first one.
You don't need to turn the string into an array to work with the characters in the string. You can just loop through the index of the characters in the string.
Note that you should also check the value of the index when you are looking at the characters before and after, so that you don't try to look at characters that are outside the string.
public void fd() {
string input = Console.ReadLine();
int index = 0;
while (index < input.Length) {
if (!Char.IsLetterOrDigit(input, index) && ((index == 0 || !Char.IsLetterOrDigit(input, index - 1)) || (index == input.Length - 1 || !Char.IsLetterOrDigit(input, index + 1)))) {
input = input.Remove(index, 1);
} else {
index++;
}
}
Console.WriteLine(input);
}
Been awhile since I've hit on C#, but a reg ex might be helpful
string input = string.Format("{0}! ", Console.ReadLine());
Regex rgx = new Regex("(?i:[^a-z]?)[.](?i:[^a-z]?)");
string output = rgx.Replace(input, "$1$2");
The regex looks for a character with a non-alpha character on left or right and replaces it with nothing.
I have a compressed string value I'm extracting from an import file. I need to format this into a parcel number, which is formatted as follows: ##-##-##-###-###. So therefore, the string "410151000640" should become "41-01-51-000-640". I can do this with the following code:
String.Format("{0:##-##-##-###-###}", Convert.ToInt64("410151000640"));
However, The string may not be all numbers; it could have a letter or two in there, and thus the conversion to the int will fail. Is there a way to do this on a string so every character, regardless of if it is a number or letter, will fit into the format correctly?
Regex.Replace("410151000640", #"^(.{2})(.{2})(.{2})(.{3})(.{3})$", "$1-$2-$3-$4-$5");
Or the slightly shorter version
Regex.Replace("410151000640", #"^(..)(..)(..)(...)(...)$", "$1-$2-$3-$4-$5");
I would approach this by having your own formatting method, as long as you know that the "Parcel Number" always conforms to a specific rule.
public static string FormatParcelNumber(string input)
{
if(input.length != 12)
throw new FormatException("Invalid parcel number. Must be 12 characters");
return String.Format("{0}-{1}-{2}-{3}-{4}",
input.Substring(0,2),
input.Substring(2,2),
input.Substring(4,2),
input.Substring(6,3),
input.Substring(9,3));
}
This should work in your case:
string value = "410151000640";
for( int i = 2; i < value.Length; i+=3){
value = value.Insert( i, "-");
}
Now value contains the string with dashes inserted.
EDIT
I just now saw that you didn't have dashes between every second number all the way, to this will require a small tweak (and makes it a bit more clumsy also I'm afraid)
string value = "410151000640";
for( int i = 2; i < value.Length-1; i+=3){
if( value.Count( c => c == '-') >= 3) i++;
value = value.Insert( i, "-");
}
If its part of UI you can use MaskedTextProvider in System.ComponentModel
MaskedTextProvider prov = new MaskedTextProvider("aa-aa-aa-aaa-aaa");
prov.Set("41x151000a40");
string result = prov.ToDisplayString();
Here is a simple extension method with some utility:
public static string WithMask(this string s, string mask)
{
var slen = Math.Min(s.Length, mask.Length);
var charArray = new char[mask.Length];
var sPos = s.Length - 1;
for (var i = mask.Length - 1; i >= 0 && sPos >= 0;)
if (mask[i] == '#') charArray[i--] = s[sPos--];
else
charArray[i] = mask[i--];
return new string(charArray);
}
Use it as follows:
var s = "276000017812008";
var mask = "###-##-##-##-###-###";
var dashedS = s.WithMask(mask);
You can use it with any string and any character other than # in the mask will be inserted. The mask will work from right to left. You can tweak it to go the other way if you want.
Have fun.
If i understodd you correctly youre looking for a function that removes all letters from a string, aren't you?
I have created this on the fly, maybe you can convert it into c# if it's what you're looking for:
Dim str As String = "410151000vb640"
str = String.Format("{0:##-##-##-###-###}", Convert.ToInt64(MakeNumber(str)))
Public Function MakeNumber(ByVal stringInt As String) As String
Dim sb As New System.Text.StringBuilder
For i As Int32 = 0 To stringInt.Length - 1
If Char.IsDigit(stringInt(i)) Then
sb.Append(stringInt(i))
End If
Next
Return sb.ToString
End Function