String.Format: Hexadecimal ("X") Format Specifier and Zero (0) [duplicate] - c#

This question already has answers here:
How to use string.Format() to format a hex number surrounded by curly brackets?
(4 answers)
Closed 5 years ago.
Now, here is a strange problem I have with String.Format while formatting zero as a hex string. Please take a look at the following example:
public override string ToString()
{
return $"{{{LowPart:X}-{HighPart.ToString("X")}}}";
}
Above code works alright with HighPart being zero, but the following two give me a wrong result:
public override string ToString()
{
return $"{{{LowPart:X}-{HighPart:X}}}";
}
public override string ToString()
{
return string.Format("{{{0:X}-{1:X}}}", LowPart, HighPart);
}
With LowPart being 50 for example and HighPart being 0, both of these will return "{32-X}" instead of "{32-0}".
I don't know the "Why" that this happens. I also tried googling it and found no answer. So here I am to see if anyone have a clue about this.
BTW, I am using VS2015 and .Net4.5
Edit: Turns out that the problem is with the ending }} in the string. Still strange to me though.
Seems like a bug in formatting engine as if I add a space there in the middle, it will work. Like: $"{{{LowPart:X}-{HighPart:X} }}"

Console.WriteLine(string.Format("{0:X}", 50));
returns 32. 50 in decimal is 32 in hexadecimal, because 2*16^0+3*16^1 = 2 + 48 = 50
Edit after understanding what the question is about:
I believe this page holds the answer (https://msdn.microsoft.com/en-us/library/txafckwd(v=vs.110).aspx)
The way escaped braces are interpreted can lead to unexpected results.
For example, consider the format item "{{{0:D}}}", which is intended
to display an opening brace, a numeric value formatted as a decimal
number, and a closing brace. However, the format item is actually
interpreted in the following manner:
The first two opening braces ("{{") are escaped and yield one opening
brace.
The next three characters ("{0:") are interpreted as the start of a
format item.
The next character ("D") would be interpreted as the Decimal standard
numeric format specifier, but the next two escaped braces ("}}") yield
a single brace. Because the resulting string ("D}") is not a standard
numeric format specifier, the resulting string is interpreted as a
custom format string that means display the literal string "D}".
The last brace ("}") is interpreted as the end of the format item.
The final result that is displayed is the literal string, "{D}". The
numeric value that was to be formatted is not displayed.
So the "{1:X}}}" is interpreted as "X}", because it tries to apply "X}" which is not recognized. The same happens in String.Format("{0:HELLO}",50)
The credit for explaining the issue goes to Hans Kesting's answer in How to use string.Format() to format a hex number surrounded by curly brackets? I flagged the question as possible duplicate because of this.

Related

How do I escape a brace in an interpolated string, after a brace with a format string?

The following crashes:
$"{{{DayOfWeek.Friday:d}}}"
If I put a space after the first closing brace, it works, but I don't want a space there.
So 2 questions:
Why does it crash, instead of treating the last 2 braces as a literal brace?
How can I do what I am trying to do?
Please have a look at Escaping Braces documentation
For example, consider the format item "{{{0:D}}}", which is intended
to display an opening brace, a numeric value formatted as a decimal
number, and a closing brace. However, the format item is actually
interpreted in the following manner: The first two opening braces
("{{") are escaped and yield one opening brace. The next three
characters ("{0:") are interpreted as the start of a format item. The
next character ("D") would be interpreted as the Decimal standard
numeric format specifier, but the next two escaped braces ("}}") yield
a single brace. Because the resulting string ("D}") is not a standard
numeric format specifier, the resulting string is interpreted as a
custom format string that means display the literal string "D}".
This is exactly your case, you are getting incorrect format specifier as a result.
For you code you can try to use the old string.Format
string.Format("{0}{1:d}{2}", "{", DayOfWeek.Friday, "}");

C# String formatter

i want to format a string. Assume there is:
string unformatedString="004897582515"
string stringFormater="{0:00#-###-###-####}"
After formatting:
string result = String.Format(stringFormater, Int64.Parse(unformatedString));
the result is: 000-044-788-9556
I'd like to know why? Because after parsing unformatedString into Int64 I am getting 4897582515 value as integer, but after formatting it there are always additional zeros(it's based on count of zeros in the beginning of unformatedString).
The simple reason 004897582515 is turning into 000-0xx-xxx-xxx with the format specifier "{0:00#-###-###-####}" is because of the 0's at the beginning
Custom numeric format strings
Format specifiers
0 : Zero placeholder
Replaces the zero with the corresponding digit if one is present; otherwise, zero appears in the result string.
Maybe you want "{0:###-###-###-####}"
Format specifiers
# : Digit placeholder
Replaces the # symbol with the corresponding digit if one is present; otherwise, no digit appears in the result string.
Which in worst case will result in "-xxx-xxx-xxxx"
However, you could hack in a TrimStart('-')
Console.WriteLine(string.Format("{0:###-###-###-####}", 004897582515).TrimStart('-'));
Which will remove any leading dash
Output
489-758-2515
Full Demo Here

Interpolated string formatting issue

I have stumbled upon one issue with interpolated strings for a several times now.
Consider the following case:
double number = 123.4567;
var str = $"{{{number:F2}}}"; //I want to get "{123.45}"
Console.WriteLine(str); // Will print "{F2}"
A little surprising at first but once you realize how the curly brackets are paired it makes sense. Two following curly brackets are an escape sequence for a single curly in the interpolated string. So the opening bracket of the interpolated expression is paired with the last curly in the string.
___pair____
| |
$"{{{number:F2}}}";
Now you could do the following to break the escape sequence:
var str = $"{{{number:F2} }}"; // This will be "{123.45 }"
Notice the space character this approach adds to the output. (Not ideal)
My question:
Lets say I want to use a single interpolated string to get exactly the output "{123.45}"
Is this at all possible without doing something hackish like the following?
var s = $"{{{number:F2}{'}'}";
This is an expected behavior of string interpolation. It is mentioned at this Microsoft document. The below content is from Microsoft link only.
Opening and closing braces are interpreted as starting and ending a format item. Consequently, you must use an escape sequence to display a literal opening brace or closing brace. Specify two opening braces ("{{") in the fixed text to display one opening brace ("{"), or two closing braces ("}}") to display one closing brace ("}"). Braces in a format item are interpreted sequentially in the order they are encountered. Interpreting nested braces is not supported.
The way escaped braces are interpreted can lead to unexpected results. For example, consider the format item "{{{0:D}}}", which is intended to display an opening brace, a numeric value formatted as a decimal number, and a closing brace. However, the format item is actually interpreted in the following manner:
The first two opening braces ("{{") are escaped and yield one
opening brace.
The next three characters ("{0:") are interpreted as the start of a
format item.
The next character ("D") would be interpreted as the Decimal standard
numeric format specifier, but the next two escaped braces ("}}")
yield a single brace. Because the resulting string ("D}") is not a
standard numeric format specifier, the resulting string is
interpreted as a custom format string that means display the literal
string "D}".
The last brace ("}") is interpreted as the end of the format item.
The final result that is displayed is the literal string, "{D}". The
numeric value that was to be formatted is not displayed.
One way to write your code to avoid misinterpreting escaped braces and format items is to format the braces and format item separately. That is, in the first format operation display a literal opening brace, in the next operation display the result of the format item, then in the final operation display a literal closing brace. The following example illustrates this approach.
int value = 6324;
string output = string.Format("{0}{1:D}{2}",
"{", value, "}");
Console.WriteLine(output);
// The example displays the following output:
// {6324}
Assuming that it is not required to use a named format string, you can use:
var s = $"{{{number:#.#0}}}";

How do I format a number as a string, so that zero is replaced by the empty string

I need for this to work in a single format statement and to work for both ints and decimals:
For example:
int myInt=0;
decimal myDecimal=0.0m;
// ... Some other code
string formattedResult1=String.Format("{0}",myInt);
string formattedResult2=String.Format("{0}",myDecimal);
The expected results are:
"" (i.e., string.Empty) if the item to be formatted is zero
and a numeric value (e.g., "123.456" for the decimal version) if it isn't.
I need for this to occur exclusively as a result of the format specification in the format string.
This should do:
string formattedResult1 = string.Format("{0:0.######;-0.######;\"\"}", myInt);
The colon introduces a numeric format string. The numeric format string is divided into 3 parts with semicolons: part 1 is for positive numbers, part 2 for negative numbers, and part 3 for zeros. To define a blank string you need to delimit it with double quotes otherwise it doesn't like it.
See MSDN for the full syntax.
based from the accepted answer above i have done the same thing in microsoft "report builder"
this worked for me (shows 2 decimal places, blank for zero) :
,##0.00;-#,##0.00;""

What does this C# string format mean?

From my previous question, Converting chinese character to Unicode, I had a good answer but with some code I didn't understand:
Console.WriteLine("U+{0:x4}", (int)myChar);
Could anyone explain this?
Console.WriteLine("U+{0:x4}", (int)myChar);
is the equivalent to the call:
Console.WriteLine("U+{0}", ((int)myChar).ToString("x4"));
In a format string, the : indicates that the item should be displayed using the provided format. The x4 part indicates that the integer should be printed in its hexadecimal form using 4 characters. Refer to standard numeric format strings for more information.
The 0 indicates which positional argument to substitute. The x displays a hexadecimal number, the 4 has it display four digits.
For example, the character ΘΏ (LATIN SMALL LETTER S WITH SWASH TAIL, codepoint 575) is printed as U+023F since 57510 = 23F16.
That will simply create the literal string "U+1234"... now if you are wanting to convert a unicode code point into a char, you want Convert.ToChar(myChar)
http://msdn.microsoft.com/en-us/library/3hkfdkcx.aspx

Categories