reading some string from a text file and the writing them to a text file there only a small problem and that's with the alignment of the text. The {4} parameter is what needs to be formatted to the right so that they are all vertically aligned.
while (recordIn != null)
{
fields = recordIn.Split(DELIM);
emp.accNumber = Convert.ToInt32(fields[0]);
emp.lastName = fields[1];
emp.firstName = fields[2];
emp.funds = Convert.ToDouble(fields[3]);
double money = Convert.ToDouble(fields[3].ToString());
if (money < 0)
{
Console.WriteLine("{0},{1},{2}, {3, 2}, {4}", emp.accNumber, emp.lastName, emp.firstName, emp.funds.ToString("F2"), creditOutput);
}
else
{
Console.WriteLine("{0},{1},{2}, {3, 2} {4}", emp.accNumber, emp.lastName, emp.firstName, emp.funds.ToString("F2"), debitOutput);
}
recordIn = reader.ReadLine();
}
You can try string.PadLeft or string.PadRight
Also you can do it like this:
To align string to the left (spaces on the right) use formatting
patern with comma (,) followed by a negative number of characters:
String.Format("{0,–10}", text). To right alignment use a positive
number: {0,10}.
You could separate all values with a tab:
Console.WriteLine("{0} \t {1} \t etc... ", emp.accNumber, emp.last name...
Or you could just add a tab before the {4} just to align these. Two tabs may be necessary.
I just did the following in Visual Studio 2012
Console.WriteLine("{0,200}", "SomeText");
It right aligned the "SomeText" in a 200 character field. You can left align with "{0,-200}";
Console.WriteLine("{0,-200}", "SomeText");
From: http://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx
The format item
A format item has this syntax:
{ index[,alignment][ :formatString] }
Brackets denote optional elements. The opening and closing braces are required. (To include a literal opening or closing brace in the format string, see the "Escaping Braces" section in the Composite Formatting article.)
For example, a format item to format a currency value might appears like this:
C#C++VB
String.Format("{0,-10:C}", 126347.89m);
A format item has the following elements:
index
The zero-based index of the argument whose string representation is to be included at this position in the string. If this argument is null, an empty string will be included at this position in the string.
alignment
Optional. A signed integer that indicates the total length of the field into which the argument is inserted and whether it is right-aligned (a positive integer) or left-aligned (a negative integer). If you omit alignment, the string representation of the corresponding argument is inserted in a field with no leading or trailing spaces.
formatString
Optional. A string that specifies the format of the corresponding argument's result string. If you omit formatString, the corresponding argument's parameterless ToString method is called to produce its string representation. If you specify formatString, the argument referenced by the format item must implement the IFormattable interface. Types that support format strings include:
Use the alignment in the format item, as in {4,10}. This makes your {4} column 10 characters wide and aligns the content to the right. Full syntax: { index[,alignment][ :formatString] }
Related
I'm Printing order in a receipt-like format to a RichtextBox, everything works just fine when my item name is in English, once my item name is a non-English language like Hebrew or Arabic where these two languages are written from right-to-left, the overall format becomes messy.
Example when all text is in English
1...5...10...15...20...25...30...35...40...45.48
ITM Price QTY Value
------------------------------------------------
Test 6,000 x1 6,000
test02 0 x1 0
test03 0 x1 0
As you Can see, everything is tidy and well-formatted, but when I have an Item which its name is in Hebrew or Arabic, This is what happens
1...5...10...15...20...25...30...35...40...45.48
ITM Price QTY Value
------------------------------------------------
Test 6,000 x1 6,000
1,500 تيست x1 1,500
As you can see, the Non-English text shifts under Price Column. As I mentioned, this happens only with languages written from Right-To-Left.
My code which does the formatting
int Item_Length = -29;
int Price_Length = -8;
int Qty_Length = -3;
int Value_Length = 8;
string Seperator = "------------------------------------------------"+"\n";
string ruler = "1...5...10...15...20...25...30...35...40...45.48"+"\n";
rTxtReceipt.Text = ruler;
string Headers = string.Format("{0,"+Item_Length+"}{1,"+Price_Length+"}{2,"+Qty_Length+"}{3,"+Value_Length+"}", "ITM", "Price", "QTY", "Value")+"\n";
rTxtReceipt.AppendText(Headers);
rTxtReceipt.AppendText(Seperator);
string Rows = null;
foreach (var item in Items_List)
{
Rows += string.Format("{0,"+Item_Length+"}{1," + Price_Length + ":N0}{2," + Qty_Length + "}{3," + Value_Length + ":N0}", item.ItemName, item.ItemSellPrice, ("x" + item.SellsQty), item.SellsValue) + "\n";
}
rTxtReceipt.AppendText(Rows);
Where rTxtReceipt is a RichTextBox Control.
Can anyone advise how to make all the texts regardless of the language to be aligned from left to right?
I do have a function where it can detects if text is in English or not, but I don't know where to change if the text was not in Egnlish.
public bool IsEnglish(string inputstring)
{
Regex regex = new Regex(#"[A-Za-z0-9 .,-=+(){}\[\]\\]");
MatchCollection matches = regex.Matches(inputstring);
if (matches.Count.Equals(inputstring.Length))
return true;
else
return false;
}
}
The problem has to do with how RTL characters behave when surrounded by numbers in bidirectional text. For more information, you may read this article:
Right-to-left language support and bidirectional text
You wouldn't have faced this problem if, say, instead of the price immediately following the item name, you had a Latin letter: تيست x1,500.
Well obviously, that's not what you want. So, to force the direction of text to remain LTR and prevent the numbers from messing it up, you simply add a "hidden character" immediately after the item name. Fortunately, there's a specific character that is used for this purpose. It's called a Left-to-Right Mark.
First, add the following constant somewhere appropriate:
const string LtrMark = "\u200E";
And then you can simply do something like this: *
Rows += string.Format(format, item.ItemName + LtrMark, item.ItemSellPrice, ...
// ^^^^^^^
Now, you don't have to worry about checking whether the item name is in English or not. Simply inserting that character will work for both LTR and RTL languages. Do note, however, that you need to use a fixed-width font that works for both English and Arabic (Courier New, for example). And this is how the final result would look like:
* Because the LTR mark is a zero-width character, it will make the following values appear one character behind. To avoid this, you may use Item_Length - 1 for the items or Item_Length + 1 for the headers to make sure they're aligned.
So I have a Label being initialized by a WebService. I want to see if that label contains any commas. The problem is, even if the label has commas, Contains() returns false and if I do a Split(), the array is only 1 element long, containing the entire string.
// text is "255,255,0,0"
string wat = myLabel.Text;
string[] wats = wat.Split(',');
// This IF never happens, for some reason
if (wat.Contains(","))
{
anotherLabel.Text = wats[0] + " VS " + wats[1];
}
Why don't Split() and Contains() work? Can it be some kind of diferent encode in the string that comes from the label? If I do wat = wat + ",", then Contains()returns True.
Unicode symbols are often weird. Unicode has a lot of commas, e.g.
string wat = "255,255,0,0"; // Full range commas
bool hasComma = wat.Contains(','); // false
If wat.Contains(',') returns false then delimiters are not commas ,. You can check it with string decoded:
string wat = myLabel.Text;
// Let's have a close look at wat: which characters (codes included) does it contain
MessageBox.Show(
$"wat: [{wat}] encoded as {string.Join(" ", wat.Select(c => ((int)c).ToString("x4")))}");
You should get
wat: [255,255,0,0] encoded as 0032 0035 0035 002c 0032 0035 0035 002c
0030 002c 0030
if not check what character code(s) do you have instead of expected 002c.
The following line is always going to evaluate to false:
if (wats.Contains(","))
string.Split(',') will only return the values in between commas as you are specifying a comma as your delimiter. None of the items in the array will ever contain a comma.
If you want to check whether your label text contains commas simply do:
if (lblteste.Text.Contains(','))
I'm trying to figure out how to write code to let the user input three values (string, int, int) in one line with space to separate the values.
I thought of doing it with String.Split Method but that only works if all the values have the same datatype.
How can I do it with different datatypes?
For example:
The user might want to input
Hello 23 54
I'm using console application C#
Well the first problem is that you need to decide whether the text the user enters itself can contain spaces. For example, is the following allowed?
Hello World, it's me 08 15
In that case, String.Split will not really be helpful.
What I'd try is using a regular expression. The following may serve as a starting point:
Match m = Regex.Match(input, #"^(?<text>.+) (?<num1>(\+|\-)?\d+) (?<num2>(\+|\-)?\d+)$");
if (m.Success)
{
string stringValue = m.Groups["text"].Value;
int num1 = Convert.ToInt32(m.Groups["num1"].Value);
int num2 = Convert.ToInt32(m.Groups["num2"].Value);
}
BTW: The following part of your question makes me frown:
I thought of doing it with String.Split Method but that only works if all the values have the same datatype.
A string is always just a string. Whether it contains a text, your email-address or your bank account balance. It is always just a series of characters. The notion that the string contains a number is just your interpretation!
So from a program's point of view, the string you gave is a series of characters. And for splitting that it doesn't matter at all what the real semantics of the content are.
That's why the splitting part is separate from the conversion part. You need to tell your application that that the first part is a string, the second and third parts however are supposed to be numbers. That's what you need type conversions for.
You are confusing things. A string is either null, empty or contains a sequence of characters. It never contains other data types. However, it might contain parts that could be interpreted as numbers, dates, colors etc... (but they are still strings). "123" is not an int! It is a string containing a number.
In order to extract these pieces you need to do two things:
Split the string into several string parts.
Convert string parts that are supposed to represent whole numbers into a the int type (=System.Int32).
string input = "Abc 123 456"
string[] parts = input.Split(); //Whitespaces are assumed as separators by default.
if (parts.Count == 3) {
Console.WriteLine("The text is \"{0}\"", parts[0]);
int n1;
if (Int32.TryParse(parts[1], out n1)) {
Console.WriteLine("The 1st number is {0}", n1);
} else {
Console.WriteLine("The second part is supposed to be a whole number.");
}
int n2;
if (Int32.TryParse(parts[2], out n2)) {
Console.WriteLine("The 2nd number is {0}", n2);
} else {
Console.WriteLine("The third part is supposed to be a whole number.");
}
} else {
Console.WriteLine("You must enter three parts separated by a space.");
}
What you have to do is get "Hello 23 54" in a string variable. Split by " " and treat them.
string value = "Hello 23 54";
var listValues = value.Split(' ').ToList();
After that you have to parse each item from listValues to your related types.
Hope it helps. ;)
I apologize up front for the title, I'm not sure how to word the question.
I am trying to find the index for a similar character or set of characters in two different, but similar strings.
String A: I <color=red><b>really</b></color> don't like spiders!
String B: I really don't like spiders!
The relevant text is the same, however A has some formatting while B does not. I got B by taking A and running a regex to find and replace all <contents> with an empty string.
Now lets say I have selected a character at an index of 9 in B, this would be the letter d in the word don't. How can I then determine in string A that the letter d in don't needs to also be selected which is at an index of 35 (if I counted correctly)?
Edit: Possibly important information, these tags are for the rich text within Unity. Very similar to HTML in almost all regards.
As I already suggested in the comments, you should write your own parser for this format that keeps the formatting as metadata next to the text. For example, you could keep a simple list of string parts where each part represents consecutive text with the same formatting.
You could start with something simplistic as this:
import re
def parse (string):
it = iter([None] + re.split('(<[^>]+>)', string))
parsed = []
curFormat = {}
for fmt, text in zip(it, it):
if fmt is None:
curFormat = {}
elif fmt.startswith('</'):
fmt = fmt[2:-1]
del curFormat[fmt]
else:
fmt = fmt[1:-1]
if '=' in fmt:
name, value = fmt.split('=', 1)
curFormat[name] = value
else:
curFormat[fmt] = True
if text != '':
parsed.append((text, list(curFormat.items())))
return parsed
For your text, this will give you the following result:
>>> text = "I <color=red><b>really</b></color> don't like spiders!"
>>> parsed = parse(text)
>>> parsed
[('I ', []), ('really', [('color', 'red'), ('b', True)]), (" don't like spiders!", [])]
As you can see, you get pairs of text, with a list of formatting information for that particular part of text. If you then want to get the underlying text, you can just iterate the first list elements:
>>> ''.join(t for t, fmt in parsed)
"I really don't like spiders!"
And on top of that, you can also create your own indexing method (note that this one is really crude):
def index (parsed, start, length):
output = ''
for t, fmt in parsed:
if start < 0:
output += t
elif start > len(t):
start -= len(t)
else:
output += t[start:]
start = -1
if len(output) > length:
return output[:length]
return output
>>> index(parsed, 4, 5)
'ally '
>>> index(parsed, 7, 6)
"y don'"
Finally, you can put this all inside a custom type, which implements the iterator protocol and the senquence protocol, so you can use it like a normal string.
What is the meaning of {0}\{1} in c#, it returns some string, but in which format and what kind of string?
It means that it is expecting parameters to be replaced in string. something like.
string.Format("{0}{1}","parameter1","parameter2");
You may see: Composite Formatting
A composite format string and object list are used as arguments of
methods that support the composite formatting feature. A composite
format string consists of zero or more runs of fixed text intermixed
with one or more format items. The fixed text is any string that you
choose, and each format item corresponds to an object or boxed
structure in the list. The composite formatting feature returns a new
result string where each format item is replaced by the string
representation of the corresponding object in the list.
These are the arguments/params usually used in the string format function:
DateTime dat = new DateTime(2012, 1, 17, 9, 30, 0);
string city = "Chicago";
int temp = -16;
string output = String.Format("At {0} in {1}, the temperature was {2} degrees.",
dat, city, temp);
Console.WriteLine(output);
// The example displays the following output:
// At 1/17/2012 9:30:00 AM in Chicago, the temperature was -16 degrees.
See the documentation
They are format specifier, used with string.Format or StringBuilder.AppendFormat and similar functions.
See the manual for string.Format for a detailed explanation.