I'm having a weird problem, trying to take a string from a string array
and convert it to an integer.
Take a look at this code snippet:
string date = "21/07/2010 13:50";
var date1 = date.Split(' ')[0];
string[] dateArray = date1.Split('/');
string s = "21";
string t1 = dateArray[0];
bool e = string.Compare(s, t1) == 0; //TRUE
int good = Convert.ToInt32(s); //WORKING!
int bad = Convert.ToInt32(t1); //Format exception - Input string was not in a correct format.
Can someone please explain why the conversion with s works, while with t1 fails?
Your string is full of hidden characters, causing it to break. There's four U+200E and one U+200F
Here's a clean string to try on:
string date = "21/07/2010 13:50";
Why do you use string.Compare(s, t1) == 0 to test if the strings are equal? This overload of Compare does a culture sensitive comparison. But it doesn't mean that the strings are identical. To check if the strings consist of identical "sequences" of char values, use ordinal comparison. Ordinal comparison can be done, for example, with
bool e = s == t1;
In your case, the strings have different Lengths, and they also differ on the first index, s[0] != t1[0].
Your string date contains right-to-left marks and left-to-right marks. This may happen because you copy-paste from an Arabic text (or another language written in the "wrong" direction).
To remove these characters in the ends of your string (not in the middle), you can use something like
t1 = t1.Trim('\u200E', '\u200F');
Related
I have as input the string format CST-000000 and an integer with value 1
Upon using
string result = string.Format("CST-000000", 1);
the expected result should be CST-000001 instead of CST-000000
How could i create this string format dynamically?
For example
- CST-000 should produce CST-001
- HELLO000 should produce HELLO001
- CUSTOMER0000 should produce CUSTOMER0001
Assuming that:
You receive your format string from somewhere and you can't control what it looks like
Your format string ends with 1 or more zeros
If the format string is e.g. CST-00000 and your value is 123, you want the result to be CST-00123
You can do something like this:
Inspect your format string, and separate out the stuff at the beginning from the zeros at the end. It's easy to do this with Regex, e.g.:
string format = "CST-000000";
// "Zero or more of anything, followed by one or more zeros at the end of the string"
var match = Regex.Match(format, "(.*?)(0+)$");
if (!match.Success)
{
throw new ArgumentException("Format must end with one or more zeros");
}
string prefix = match.Groups[1].Value; // E.g. CST-
string zeros = match.Groups[2].Value; // E.g. 000000
Once you have these, note the "Zero placeholder" in this list of custom numeric format strings -- you can write e.g. 123.ToString("0000") and the output will be 0123. This lets you finish off with:
int value = 123;
string result = prefix + value.ToString(zeros);
See it on dotnetfiddle
String.Format requires a placeholder {n} with a zero-based argument number. You can also add it a format {n:format}.
string result = String.Format("CST-{0:000000}", 1);
You can also use String interpolation
string result = $"CST-{1:000000}"
The difference is that instead of a placeholder you specify the value directly (or as an expression). Instead of the Custom numeric format string, you can also use the Standard numeric format string d6: $"CST-{1:d6}"
If you want to change the format template dynamically, String.Format will work better, as you can specify the format and the value as separate arguments.
(Example assumes an enum FormatKind and C# >= 8.0)
int value = 1;
string format = formatKind switch {
FormatKind.CstSmall => "CST-{0:d3}",
FormatKind.CstLarge => "CST-{0:d6}",
FormatKind.Hello => "HELLO{0:d3}",
FormatEnum.Customer => "CUSTOMER{0:d4}"
};
string result = String.Format(format, value);
Also note that the value to be formatted must be of a numeric type. Strings cannot be formatted.
See also: Composite formatting
It seems .toString("CST-000"), .toString("HELLO000") and so on, does the trick.
ToString and String.Format can do much more than use predefined formats.
For example :
string result = string.Format("CST-{0:000000}", 1);
string result = 1.ToString("CST-000000");
Should both do what you want.
(Of course you could replace "1" by any variable, even a decimal one).
I have a six digit unicode character, for example U+100000 which I wish to make a comparison with a another char in my C# code.
My reading of the MSDN documentation is that this character cannot be represented by a char, and must instead be represented by a string.
a Unicode character in the range U+10000 to U+10FFFF is not permitted in a character literal and is represented using a Unicode surrogate pair in a string literal
I feel that I'm missing something obvious, but how can you get the follow comparison to work correctly:
public bool IsCharLessThan(char myChar, string upperBound)
{
return myChar < upperBound; // will not compile as a char is not comparable to a string
}
Assert.IsTrue(AnExample('\u0066', "\u100000"));
Assert.IsFalse(AnExample("\u100000", "\u100000")); // again won't compile as this is a string and not a char
edit
k, I think I need two methods, one to accept chars and another to accept 'big chars' i.e. strings. So:
public bool IsCharLessThan(char myChar, string upperBound)
{
return true; // every char is less than a BigChar
}
public bool IsCharLessThan(string myBigChar, string upperBound)
{
return string.Compare(myBigChar, upperBound) < 0;
}
Assert.IsTrue(AnExample('\u0066', "\u100000));
Assert.IsFalse(AnExample("\u100022", "\u100000"));
To construct a string with the Unicode code point U+10FFFF using a string literal, you need to work out the surrogate pair involved.
In this case, you need:
string bigCharacter = "\uDBFF\uDFFF";
Or you can use char.ConvertFromUtf32:
string bigCharacter = char.ConvertFromUtf32(0x10FFFF);
It's not clear what you want your method to achieve, but if you need it to work with characters not in the BMP, you'll need to make it accept int instead of char, or a string.
As per the documentation for string, if you want to iterate over characters in a string as full Unicode values, use TextElementEnumerator or StringInfo.
Note that you do need to do this explicitly. If you just use ordinal values, it will check UTF-16 code units, not the UTF-32 code points. For example:
string text = "\uF000";
string upperBound = "\uDBFF\uDFFF";
Console.WriteLine(string.Compare(text, upperBound, StringComparison.Ordinal));
This prints out a value greater than zero, suggesting that text is greater than upperBound here. Instead, you should use char.ConvertToUtf32:
string text = "\uF000";
string upperBound = "\uDBFF\uDFFF";
int textUtf32 = char.ConvertToUtf32(text, 0);
int upperBoundUtf32 = char.ConvertToUtf32(upperBound, 0);
Console.WriteLine(textUtf32 < upperBoundUtf32); // True
So that's probably what you need to do in your method. You might want to use StringInfo.LengthInTextElements to check that the strings really are single UTF-32 code points first.
From https://msdn.microsoft.com/library/aa664669.aspx, you have to use \U with full 8 hex digits. So for example:
string str1 = "\U0001F300";
string str2 = "\uD83C\uDF00";
bool eq = str1 == str2;
using the :cyclone: emoji.
I'm setting up an orchestration class that handles multiple actions as one big transaction. For each of these transactions I give them the same time-stamp instantiated at the beginning of the orchestration.
I user the following line:
var transactionTimestamp = DateTime.UtcNow.ToString("o");
I have a constraint in the system that dictates that the time stamp cannot have any trailing zeros.
For example:
2013-06-26T19:51:38.0083980Z //bad
2013-06-26T19:51:38.008398Z //good
2013-06-26T19:51:38.0083988Z //good
The built-in DateTime format "o" is comparable to the custom format of: "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffK". If you just use that format, but replace the lower-case f's with upper case ones, there will be no trailing zeros.
ie
DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFK");
Custom date and time format strings
You can achieve this fairly easily using Regex. Here's one way.
string result = Regex.Replace("2013-06-26T19:51:38.0083980Z", "0+Z$", "Z");
// result == "2013-06-26T19:51:38.008398Z"
string result2 = Regex.Replace("2013-06-26T19:51:38.0083988Z", "0+Z$", "Z")
// result2 == "2013-06-26T19:51:38.0083988Z"
I would write my own help method like;
public string GetDtString(DateTime dt)
{
RegEx rgx = new RegEx("[1-9]0+Z\b");
return rgx.Replace(dt.ToString("o"), System.String.Empty);
}
It basically just returns the dt string with all 0's which occur after a digit 1-9 and before Z\b (Z followed by a word boundary) with an empty string.
I have a numeric string like this 2223,00. I would like to transform it to 2223. This is: without the information after the ",". Assume that there will be only two decimals after the ",".
I did:
str = str.Remove(str.Length - 3, 3);
Is there a more elegant solution? Maybe using another function? -I don´t like putting explicit numbers-
You can actually just use the Remove overload that takes one parameter:
str = str.Remove(str.Length - 3);
However, if you're trying to avoid hard coding the length, you can use:
str = str.Remove(str.IndexOf(','));
Perhaps this:
str = str.Split(",").First();
This will return to you a string excluding everything after the comma
str = str.Substring(0, str.IndexOf(','));
Of course, this assumes your string actually has a comma with decimals. The above code will fail if it doesn't. You'd want to do more checks:
commaPos = str.IndexOf(',');
if(commaPos != -1)
str = str.Substring(0, commaPos)
I'm assuming you're working with a string to begin with. Ideally, if you're working with a number to begin with, like a float or double, you could just cast it to an int, then do myInt.ToString() like:
myInt = (int)double.Parse(myString)
This parses the double using the current culture (here in the US, we use . for decimal points). However, this again assumes that your input string is can be parsed.
String.Format("{0:0}", 123.4567); // "123"
If your initial value is a decimal into a string, you will need to convert
String.Format("{0:0}", double.Parse("3.5", CultureInfo.InvariantCulture)) //3.5
In this example, I choose Invariant culture but you could use the one you want.
I prefer using the Formatting function because you never know if the decimal may contain 2 or 3 leading number in the future.
Edit: You can also use Truncate to remove all after the , or .
Console.WriteLine(Decimal.Truncate(Convert.ToDecimal("3,5")));
Use:
public static class StringExtensions
{
/// <summary>
/// Cut End. "12".SubstringFromEnd(1) -> "1"
/// </summary>
public static string SubstringFromEnd(this string value, int startindex)
{
if (string.IsNullOrEmpty(value)) return value;
return value.Substring(0, value.Length - startindex);
}
}
I prefer an extension method here for two reasons:
I can chain it with Substring.
Example: f1.Substring(directorypathLength).SubstringFromEnd(1)
Speed.
You could use LastIndexOf and Substring combined to get all characters to the left of the last index of the comma within the sting.
string var = var.Substring(0, var.LastIndexOf(','));
You can use TrimEnd. It's efficient as well and looks clean.
"Name,".TrimEnd(',');
Try the following. It worked for me:
str = str.Split(',').Last();
Since C# 8.0 it has been possible to do this with a range operator.
string textValue = "2223,00";
textValue = textValue[0..^3];
Console.WriteLine(textValue);
This would output the string 2223.
The 0 says that it should start from the zeroth position in the string
The .. says that it should take the range between the operands on either side
The ^ says that it should take the operand relative to the end of the sequence
The 3 says that it should end from the third position in the string
Use lastIndexOf. Like:
string var = var.lastIndexOf(',');
I have strings like this:
var a = "abcdefg";
var b = "xxxxxxxx";
The strings are always longer than five characters.
Now I need to trim off the last 3 characters. Is there some simple way that I can do this with C#?
In the trivial case you can just use
result = s.Substring(0, s.Length-3);
to remove the last three characters from the string.
Or as Jason suggested Remove is an alternative:
result = s.Remove(s.Length-3)
Unfortunately for unicode strings there can be a few problems:
A unicode codepoint can consist of multiple chars since the encoding of string is UTF-16 (See Surrogate pairs). This happens only for characters outside the basic plane, i.e. which have a code-point >2^16. This is relevant if you want to support Chinese.
A glyph (graphical symbol) can consist of multiple codepoints. For example ä can be written as a followed by a combining ¨.
Behavior with right-to-left writing might not be what you want either
You want String.Remove(Int32)
Deletes all the characters from this string beginning at a specified
position and continuing through the last position.
If you want to perform validation, along the lines of druttka's answer, I would suggest creating an extension method
public static class MyStringExtensions
{
public static string SafeRemove(this string s, int numCharactersToRemove)
{
if (numCharactersToRemove > s.Length)
{
throw new ArgumentException("numCharactersToRemove");
}
// other validation here
return s.Remove(s.Length - numCharactersToRemove);
}
}
var s = "123456";
var r = s.SafeRemove(3); //r = "123"
var t = s.SafeRemove(7); //throws ArgumentException
string a = "abcdefg";
a = a.Remove(a.Length - 3);
string newString = oldString.Substring(0, oldString.Length - 4);
If you really only need to trim off the last 3 characters, you can do this
string a = "abcdefg";
if (a.Length > 3)
{
a = a.Substring(0, a.Length-3);
}
else
{
a = String.Empty;
}