I'm trying to build a number of strings that line up nicely, but the formatting isn't working the way I would expect.
If I have:
String.Format("{0,-25}{1,-7}{2,-18}{3,-8}{4,-15}{5,-3}{6,-10}",
i.Name, "Price: ", i.Price.toString(), "Weight: ",
i.Weight.toString() + " lbs", "Quantity:",i.Quantity.toString()));
I would expect to get Name (which is a string) starting at the beginning of the line, then "Price" starting at character 26, and so on. (None of the names are more than 10 characters). Instead, the second column is all over the place depending on the length of name.
I tried this using a StringBuilder as well, with the same result. A number of internet searches are just showing code that looks pretty much the same as what I have, so I'm not sure what's not working.
Edit: fixed typos
I suspect that the problem is the display rather than the strings themselves. These sorts of alignments only work when the font is a monospace font. A monospace font is one in which each character is the same width. There are several of these provided with Windows,Office, Visual Studio. Many people consider "Consolas" to be the best.
I recommend you change the font of whatever control is displaying your data to Consolas.
Related
I managed to make a simple C# table in a console, there are more than enough threads regarding that.
The problem is due to characters having different sizes(for example 'iiiii'(5 chars) is shorter than 'there'(5 chars)) The table will never be aligned.
Is there a way to calculate the real length of the string value in order to tell how many more spaces need to be added to align the shorter string with the rest of the table?
(I tried to visually display it here but it seems that in the font this site is using all characters have an equal size(and/or padding), However, I can send a screenshot)
Instead of trying to manually align the text into columns with arbitrary strings of spaces, you should embed actual tabs (the \t escape sequence) into each output string.
Console.WriteLine("Row1:" + "\t"
+ "iiiiiii" );
Console.WriteLine("Row2:" + "\t"
+ "7 chars" );
If you know console font name and size, you can try to use TextRenderer.MeasureText to get strings widths in pixels. Then add spaces to shorter ones until strings will be aligned.
Of course you will not get precise positioning this way, but probably it will suit your needs.
UPD. You can refer to How to measure the pixel width of a digit in a given font / size (C#) and/or other similar questions for more details.
Is there a way to perfectly align two strings in C#?
I am trying to align the string "CBI" with "Central Bureau of Investigation" and I want both strings to occupy 35 characters. I use the function
string.Format("{0,-35}", str);
to format both strings. But they do not appear to be aligned properly. Does it have something to do with the font settings?
I have to use these strings in a chart in excel and they have to occupy the same width on the screen
Yes there is PadLeft and PadRight
str.PadLeft(35);
str.PadRight(35);
str = "BBQ and Slaw";
Console.WriteLine(str.PadLeft(15)); // Displays " BBQ and Slaw".
Console.Write(str.PadRight(15)); // Displays "BBQ and Slaw ".
Side Note from documentation:
However, if totalWidth is less than the length of this instance, the method returns a reference to the existing instance
Basically if your length is less than the length of the string then an reference of the existing string is returned
If EvenMcDonnal wishes to include this in an answer I'll gladly remove it from my answer.
You can find a list of MonoSpaced fonts you can use here
I find that I am never satisfied by monospaced fonts, so I use character padding with a micro-space character (about 1 pixel wide) (char)0x200A to line things up. This is especially useful when simulating column alignment with a list of strings. The most flexible method is to use a while loop comparing string pixel widths and adding the space character until the match. I use System.Windows.Forms.TextRenderer.MeasureText() with a NoPadding flag and just to be save, an initial size of int.MaxValue, then check the Width parameter of System.Drawing.Size. If you feed in any Font in the MeasureText constructor, it works with any font.
I'm testing an SDK that extracts text from a searchable PDF. One of the SDK's dependencies was recently updated, and it's causing an existing test on Hebrew text to fail. I don't know Hebrew nor enough about how the involved technologies represent right-to-left languages.
The NUnit test asserts that the extracted text matches the C# string "מנבוצץז ".
string hebrewText = reader.ReadToEnd();
Assert.AreEqual("מנבוצץז ", hebrewText);
The rasterized PDF has what I believe are the same characters, but in the opposite order.
The unit test fails with this message:
Expected: "מנבוצץז "
But was: " זץצובנמ"
Although the actual result more closely matches what I see in the rasterized PDF, I'm not completely sure the original test is wrong.
Are Hebrew characters in a C# string supposed to be read right-to-left like printed Hebrew text?
Does any part of the .NET stack tamper with the direction of Hebrew strings?
What about NUnit?
Are Hebrew characters embedded in a searchable PDF normally supposed to go in the same direction as the rasterized text?
Anything else I should know before deciding whether to "fix" this unit test?
There are various ways to encode RTL languages. The most common way (and Window's default) is to use logical ordering, which means the first letter is encoded as the first character in a string (or file). So whether visually the first letter appears on the left or right side of the screen doesn't affect the order in which they are stored.
Now as for the text appearing in Visual Studio, it depends on the version. As far as I remember, prior to Visual Studio 2010 the code editor displayed Hebrew backwards, and it was apparent as when you tried to select Hebrew text, it reversed in an odd way (which was visually confusing). It appears this issue no longer exists is Visual Studio 2010 (at least with SP1 which I just tested).
Let's take a Hebrew word for which the direction is more clear to non-Hebrew speakers than the string specified in your text:
יון
The word happens to be the Hebrew word for an ion, and on your screen, it should appear as three letters where the tallest letter is on the left and the shortest is on the right. In a .NET string, the expression "יון".Substring(0, 1) will produce the short letter, since it's the first letter in the string. The string can also be written as "\u05D9\u05D5\u05DF" where the leftmost Unicode character \u05D9 represents the short letter displayed on the right, which clearly demonstrates the order in which the letters are stored.
Since the string in your test case is nonsensical, I can't tell you whether it was a wrong test all along or if it a correct test that should pass. If the image you uploaded has been rendered correctly then it appears the actual result of your test is correct and the expected value is incorrect, and so you should fix the test.
I believe that all strings in C# will be stored internally as LTR; RTL strings will have a non-printable character (or something) denoting that they are indeed RTL.
More than likely. RTL GUIs and rendered text for example need certain properties (specifically RightToLeft and RightToLeftLayout) to be set in order to display correctly.
NUnit shouldn't. Nor should it care. IMHO a reversed string != the original string.
I couldn't comment. I'd assume that they should be whatever the test is expecting though, assuming it was passing at first.
Don't do half measures with RTL, it really doesn't like it. Either have full RTL support, or nothing. It can be pretty nasty, I wish you the best of luck!
Is there anyway to reconcile the two ? Ie when i set the text of a richtextform from a string, a given characters index in the string does not match the position of it in the textbox.
Make sure the WordWrap property is False.
On extremely long lines you're going to run into RightMargin. It is not infinite, the maximum right margin depends on the font size.
It seems to be okay, with this my sample text:
"Provide details and share your research. Avoid statements based solely on opinion; only make statements you can back up with an appropriate reference, or personal experiences"
Using the code:
richTextBox1.Text.IndexOf("back up");
textBox1.Text.IndexOf("back up");
Both have results of: 112
It seems you are using the Rtf property of the RichTextBox that contains extra tags for its formatting?
How would I accomplish displaying a line as the one below in a console window by writing it into a variable during design time then just calling Console.WriteLine(sDescription) to display it?
Options:
-t Description of -t argument.
-b Description of -b argument.
If I understand your question right, what you need is the # sign in front of your string. This will make the compiler take in your string literally (including newlines etc)
In your case I would write the following:
String sDescription =
#"Options:
-t Description of -t argument.";
So far for your question (I hope), but I would suggest to just use several WriteLines.
The performance loss is next to nothing and it just is more adaptable.
You could work with a format string so you would go for this:
string formatString = "{0:10} {1}";
Console.WriteLine("Options:");
Console.WriteLine(formatString, "-t", "Description of -t argument.");
Console.WriteLine(formatString, "-b", "Description of -b argument.");
the formatstring makes sure your lines are formatted nicely without putting spaces manually and makes sure that if you ever want to make the format different you just need to do it in one place.
Console.Write("Options:\n\tSomething\t\tElse");
produces
Options:
Something Else
\n for next line, \t for tab, for more professional layouts try the field-width setting with format specifiers.
http://msdn.microsoft.com/en-us/library/txafckwd.aspx
If this is a /? screen, I tend to throw the text into a .txt file that I embed via a resx file. Then I just edit the txt file. This then gets exposed as a string property on the generated resx class.
If needed, I embed standard string.Format symbols into my txt for replacement.
Personally I'd normally just write three Console.WriteLine calls. I know that gives extra fluff, but it lines the text up appropriately and it guarantees that it'll use the right line terminator for whatever platform I'm running on. An alternative would be to use a verbatim string literal, but that will "fix" the line terminator at compile-time.
I know C# is mostly used on windows machines, but please, please, please try to write your code as platform neutral. Not all platforms have the same end of line character. To properly retrieve the end of line character for the currently executing platform you should use:
System.Environment.NewLine
Maybe I'm just anal because I am a former java programmer who ran apps on many platforms, but you never know what the platform of the future is.
The "best" answer depends on where the information you're displaying comes from.
If you want to hard code it, using an "#" string is very effective, though you'll find that getting it to display right plays merry hell with your code formatting.
For a more substantial piece of text (more than a couple of lines), embedding a text resources is good.
But, if you need to construct the string on the fly, say by looping over the commandline parameters supported by your application, then you should investigate both StringBuilder and Format Strings.
StringBuilder has methods like AppendFormat() that accept format strings, making it easy to build up lines of format.
Format Strings make it easy to combine multiple items together. Note that Format strings may be used to format things to a specific width.
To quote the MSDN page linked above:
Format Item Syntax
Each format item takes the following
form and consists of the following
components:
{index[,alignment][:formatString]}
The matching braces ("{" and "}") are
required.
Index Component
The mandatory index component, also
called a parameter specifier, is a
number starting from 0 that identifies
a corresponding item in the list of
objects ...
Alignment Component
The optional alignment component is a
signed integer indicating the
preferred formatted field width. If
the value of alignment is less than
the length of the formatted string,
alignment is ignored and the length of
the formatted string is used as the
field width. The formatted data in
the field is right-aligned if
alignment is positive and left-aligned
if alignment is negative. If padding
is necessary, white space is used. The
comma is required if alignment is
specified.
Format String Component
The optional formatString component is
a format string that is appropriate
for the type of object being formatted
...