String from label.text weird behaviour - c#

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(','))

Related

Replace text in file regardless of the end of the line

I've been working on a tool to modify a text file to change graphics settings for a game. A few examples of the settings are as follows:
sg.ShadowQuality=0
ResolutionSizeX=1440
ResolutionSizeY=1080
bUseVSync=False
I want to be able to find sg.ShadowQuality=(rest of line, regardless of what is after this text), and replace it. This is so that a user can set this to say, 10 then 1 without having to check for 10 and 1 etc.
Basically, I'm try to find out what I need to use to find/replace a string in a text file without knowing the end of the string.
My current code looks like:
FileInfo GameUserSettings = new FileInfo(#SD + GUSDirectory);
GameUserSettings.IsReadOnly = false;
string text = File.ReadAllText(SD + GUSDirectory);
text = text.Replace("sg.ShadowQuality=0", "sg.ShadowQuality=" + Shadows.Value.ToString());
File.WriteAllText(SD + GUSDirectory, text);
text = text.Replace("sg.ShadowQuality=1", "sg.ShadowQuality=" + Shadows.Value.ToString());
File.WriteAllText(SD + GUSDirectory, text);
SD + GUSDirectory is the location of the text file.
The file must have readonly Off to be edited, otherwise the game can revert the settings back, hence the need for this.(It is turned back to readonly On after any change, its just not included in this code provided)
You can do it like you do, if you use a regular expression to match all the line
FileInfo gameUserSettings = new FileInfo(Path.Combine(#SD, GUSDirectory)); //name local varaible in camelCase, use Path.Combine to combine paths
gameUserSettings.IsReadOnly = false;
string text = File.ReadAllText(gameUserSettings.FullName); //use the fileinfo you just made rather than make the path again
text = Regex.Replace(text, "^sg[.]ShadowQuality=.*$", $"sg.ShadowQuality={Shadows.Value}", RegexOptions.Multiline); //note switch to interpolated strings
File.WriteAllText(gameUserSettings.FullName, text);
That regex is a Multiline one (so ^ and $ have altered meanings):
^sg[.]ShadowQuality=.*$
start of line ^ (not start of input)
followed by sg
followed by period . (in a character class it loses its "any character" meaning)
followed by ShadowQuality=
followed by any number of any character(.*)
followed by end of line $ (not end of input)
The vital bit is "any number of any character" that can cope with the vlaue in the file being 1, 2, 7, hello and so on..
The replacement is:
$"sg.ShadowQuality={Shadows.Value}"
This is an interpolated string; a neater way of representing strings that mix constant content (hardcoded chars) and variable content. When a $tring contains a { that "breaks out" of the string and back into normal c# code so you can write code that resolves to values that will be included in the string -> if Shadows.Value is for example a decimal? of 1.23 it will become 1.23
You can format data too; calling for $"to one dp is {Shadows.Value:F1}" would produce "to one dp is 1.2" - the 1.23 is formatted to 1 decimal place by the F1, just like calling Shadows.Value.ToString("F1") would

empty string has a length of 1

I have an array of names concatenated with an _ ex: string[] samples = ["Test_test","Test2_blah", "Test3_"].
At some point in my code I want to try and validate the value after the _ to check if it's empty or null, and if it is, remove it from the array like so :
string[] splitSample= samples[2].Split(new char[] { '_' }, 2);
if(!string.IsNullOrWhiteSpace(splitSample[1]))
The problem i'm running into is that splitSample[1] is "", when i check the length of the string it's 1, not 0 but in Visual Studio 2017 it shows empty quotes. Is there a way to actually see the value that's invisible or what's actually going on?
EDIT:
Here's a pic of the immediate window when i check the array value
Depending on how they get rendered, some Unicode characters can be invisible (i.e., "") when represented (e.g., "\u200C", "\u2063", and check this answer for more).
Now, your string has a length (>0), and you'd like to know what it actually represents. There are many ways to achieve this, one of them is to convert your string to hex. Here's an example using the Unicode character mentioned above:
static void Main(string[] args)
{
string invisibleChar = "\u200C";
string[] samples = { "Test_test", "Test2_blah", "Test3_" + invisibleChar };
string[] splitSample = samples[2].Split(new char[] { '_' }, 2);
// Prints "Test3_" (or "Test3_?" if you use Console.Write).
Debug.Print(samples[2]);
Debug.Print(splitSample.Length.ToString()); // 2
if (!string.IsNullOrWhiteSpace(splitSample[1]))
{
Debug.Print(splitSample[1].Length.ToString()); // 1
// Prints "" (or "?" in Console).
Debug.Print(splitSample[1]);
var hex = string.Join("", splitSample[1].Select(c => ((int)c).ToString("X2")));
// Prints "200C"
Debug.Print(hex);
}
Console.ReadLine();
}
Note that because you're using !string.IsNullOrWhiteSpace, you could be missing other Unicode characters (e.g., "\u00A0") because they're considered a white space. So, you should ask yourself whether you want to also check for these or not.
Hope that helps.

Input string was not in correct format error when parsing to int

I get error "Input string was not in correct format" when parsing to int.
But string is in correct format. I'm adding screenshot below.
The problem is that there must be some hidden characters in your a string variable (Carriage Return maybe?). Try int.Parse(a.Substring 0,4) as usually they are at the end of the string.
You could also clean the input where you are getting that value from.
I noticed you are doing multiple conversions. Are you sure it's a ("2016") that is causing the error?
if yes, then there must be hidden characters as other have suggested. The a.substring(0,4) would indeed remove any trailing characters. But if the first character is a hidden char, it would not.
string output = new string(input.Where(c => char.IsLetter(c) || char.IsDigit(c)).ToArray());
should clear out any possible hidden characters.
Maybe you can try something like this:
int x = Convert.ToInt32(a);
Furthermore you can try to use the .ToString() Methode of a to make it run more stable.
You can additionaly try to clear the string from all "non number" chars using Rexex:
/// <summary>
/// RegEx to extract all non numeric values.
/// </summary>
private static readonly Regex rxNonDigits = new Regex(#"[^\d.,-]+");
Use it as follows to clear:
String a2 = rxNonDigits.Replace(a, "");
I think you are using REST API with JSON or passing whole string in query string i.e JSON formatted string, then you should use
a = new JavaScriptSerializer().Deserialize(a, null).ToString();
x = int.Parse(a);

How can I determine the index of the same set of characters between two strings that are of different lengths?

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.

C# text alignment

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] }

Categories

Resources