Check empty Char in a array C# - c#

I'm reading a field On a table it only has 3 values ("",ESD,R&S)
I don't know exactly why, but when I read the R&S value, the print out label is R ("empty space") S
this is the code I'm using:
char[] area = read1[8].ToString().ToCharArray();
// if array is less than one do nothing
if (area.Length > 1)
{
//trying to use this to check if the second item of array is the "&" symbol (print this format data)
if (area[1].ToString() == "&")
{
Arealbl.Text = area[0].ToString() + "\n" + "&" + "\n" + area[2].ToString();
}
//else print out this format data
else
{
Arealbl.Text = area[0].ToString() + "\n" + area[1].ToString() + "\n" + area[2].ToString();
}
}
I using this code because I haven't found an easy way to put a label on vertical.

The & is a special char in MenuItems, Labels and Buttons, used to indicate that the next char should be underscored. When you manage to focus Arealbl and hit Alt you might see that.
Set
Arealbl.UseMnemonic = false;
somewhere. Like with the designer.

In addition to #Henk Holterman's answer, here are a few code review suggestions. You can access a string as an array, so there is no need to .ToString().ToCharArray(), just to .ToString() everything further down the method. Simplifying the concatenation to a string.Format can help improve readability and assuming you don't have to do this a large number of times (tens of thousands) it shouldn't impact performance.
string area = read1[8].ToString()
if(area.Length < 3) { return; } //exit early on error conditions.
// if array is less than one do nothing
Arealbl.UseMnemonic = false; //only add this if you cannot guarantee it will be set.
Arealbl.Text = string.Format("{0}\n{1}\n{2}", area[0], area[1], area[2]);

Related

Inserting a certain character in between every character in a textbox

So in this example I attempted to make a program that inserts a "*" in between every character that is in a certain textbox (textBox1). Though I'm having trouble figuring it out. Yes I have looked around on stack-overflow already, nothing seems to relate/work with what I'm trying to do.
Here's the code I have currently:
for (int i = 1; i <= textBox1.Text.Length; i += 1)
{
textBox2.Text = textBox1.Text.Insert(i, "*");
i++;
}
Here is a picture of what this current code does:
pretty easy to do like...
textBox2.Text = string.Join('*', textBox1.Text.ToCharArray())
You're doing a whole lot of unnecessary things. I'm using two strings instead of text boxes as I'm on Console, but the idea is the same.
var tb1Text = "hello";
var tb2Text = string.Empty;
foreach (var ch in tb1Text)
{
tb2Text += ch + "*";
}
tb2Text = tb2Text.TrimEnd(new char[] { '*' });
We iterate through the string (because a string is essentially an array of char), and add it to the tb2Text along with a trailing *. If you don't want a trailing * at the very end, use the last line of code, otherwise get rid of it.
Result
tb1Text = hello
And
tb2Text = h*e*l*l*o

How do I tell the difference between +'s in and out of strings?

I am making a simple compiler, and am working on string parsing. At the moment, my code is:
while (stringToParse.Contains(" + ") || stringToParse.Contains("+ ") || stringToParse.Contains(" +")) {
stringToParse = stringToParse.Replace(" +", "+").Replace("+ ", "+").Replace(" + ", "+");
}
string[] splitString = stringToParse.Split("+");
But something like:
"\"hello \" + \"world \" + \" + \" + \"hello\""
Would return:
["\"hello "\", "\"world \"", "\"", "\"", ]
(without backslashes)
But something like:
""hello " + "world " + " + " + "hello""
Would return:
[""hello "", ""world "", """, """, ]
So how can I specify if a " + " is in a string or as a separator? is there maybe a way to detect for something like the following?
...(any number of non " or + characters)...+...(any number of " or + characters)
My expected output would be:
[""hello "", ""world "", ""+""]
Explicit State Machine
To do this, Without using any dedicated library, I suggest to build a state machine.
You will iterate over the characters of the string, and depending on which character you encounter you update the state of the machine. Optimizations are possible, however, let us begin with conventional clarity.
var characters = input.ToCharArray();
var results = new List<string>();
var current = string.Empty;
// 0 = not inside quotes, we expect +
// 1 = not inside quotes, we expect "
// 2 = inside quotes
var state = 1;
foreach (var character in characters)
{
switch (state)
{
case 0:
// We are not inside quotes, we expect +
if (character == '+')
{
state = 1;
continue;
}
if (char.IsWhiteSpace(character))
{
continue;
}
// error?
break;
case 1:
// We are not inside quotes, we expect "
if (character == '\"')
{
state = 2;
continue;
}
if (char.IsWhiteSpace(character))
{
continue;
}
// error?
break;
case 2:
// We are inside quotes, we expect "
if (character == '\"')
{
state = 0;
results.Add(current);
current = string.Empty;
continue;
}
current += character;
break;
default:
// error?
break;
}
}
if (state != 0)
{
// error
}
// You can use results.ToArray();
Possible optimizations:
We can use a StringBuilder instead of concatenations.
Also, we can use IndexOf to find the next relevant character.
We can check if a string (a chunk of characters) is empty or white space (perhaps using IsNullOrWhiteSpace).
We can use AsSpan so we can work with ReadOnlySpan instead.
You can also see how you can add support for your own escape sequences, or any other stuff.
Implicit State Machine (with helper class)
I want to point out that this is not the only way to organize this code. I would, if I were you, create a pseudo iterator class that had a method two methods:
A method that returns the next character... or better yet, that returns true if the next character matches a parameter (and advances), or false (and does not advance).
A method that returns all the characters until the next instance of a particular character (and advances to there).
The main advantage of such approach is that I would no longer have to step character by character, thus, I would not need to have a state variable. Instead I could allow the code structure to resemble the shape of my gramar.
Wait, I have wrote such class: StringProcessor. It is part of the Theraot.Core nuget, it is used to parse strings to BigInteger.
var processor = new Theraot.Core.StringProcessor(input);
var results = new List<string>();
while (!processor.EndOfString)
{
// SkipWhile skips all the characters that match
processor.SkipWhile(char.IsWhiteSpace);
// Read returns true (and advances after) if what is next matches the paramter
if (processor.Read('"'))
{
// ReadUntil advances after and returns everything found before the parameter
// Note: it does not advance after the parameter.
results.Add(processor.ReadUntil('"'));
processor.Read('"');
}
processor.SkipWhile(char.IsWhiteSpace);
if (!processor.Read('+'))
{
// error?
}
}
Please notice that a class such as the StringProcessor used above cuts a lot of fluff, which makes it viable for simple languages.
Custom Tokenizer
Of course, for something more complex you might want to look for a tokenizer.
To give you an example, consider that this is the "grammar" we have:
Document: Many
{
Whitespace
String:
{
QuoteSymbol
NonQuoteSymbol
QuoteSymbol
}
Whitespace
PlusSymbol
}
No, this not any of the usual metalanguages. However, written this way it is easier to see how the code we had above resembles the language.
Would it not be nice to write as follows?
var QuoteSymbol = Pattern.Literal("QuoteSymbol", '"');
var NonQuoteSymbol = Pattern.Custom("NonQuoteSymbol", s => s.ReadUntil('"'));
var String = Pattern.Conjunction("String", QuoteSymbol, NonQuoteSymbol, QuoteSymbol);
var WhiteSpace = Pattern.Custom("WhiteSpace", s => s.ReadWhile(char.IsWhiteSpace));
var PlusSymbol = Pattern.Literal("PlusSymbol", '+');
var Document = Pattern.Repetition(
Pattern.Conjunction(WhiteSpace, String, WhiteSpace, PlusSymbol)
);
var results = from TerminalSymbol symbol
in Document.Parse(input)
where symbol.Pattern == String
select symbol.ToString();
Writing code like that would make it easier to modify the language. Well, we are still writing code, however you could imagine parsing a file that has the grammar of the language you want to parse... Fancy!
As you might expect, it requires extra work to build the necesary code to make it work. Or, you know, get some code that already works (the linked code is built around on StringProcessor).
Language Toolkits
The code presented earlier is not suitable to be used for a prettyprinter and is not capable of recovering from a syntax error. It can be modified to do such things. Neither will it integrate with code editors at any level.
If you want a fully fledged solution. I have two suggestions:
Irony
Nitra
These are the kind of things you would use if you wanted to create a programming language ontop.
And of course, I should link you to "Compilers: Principles, Techniques, and Tools" usually just known as "The Dragon Book".

How can I print all the positions in my array on a TextMesh on Unity?

I have a 3D text linked to a public TextMesh. I want all the elements on my public string array to be displayed on that 3D text. When I try to run it on a for loop it runs through all the strings in my array and prints the last position. What I need it to do is to display in that TextMesh all of the strings in my array. I tried to do it with a foreach loop as well, but same result.
This is what I tried:
for (int i = 0; i < myShoppingList.Length; i++){
listText.text = (myShoppingList[i] + "\n");
}
When I hit play, I can only see the last position in my array in the 3DText (although I know it has run through all of them). This is the foreach loop I tried and got the same result with:
foreach (string item in myShoppingList) {
listText.text = (item + "\n");
}
Basically what I need is a way for it to say
listText.text = (myShoppingList[0] + "\n" + myShoppingList[1] + "\n" + myShoppingList[2] + etc.)
I could do it like that, but then if I want to add an item to my list (my string array) I would have to get into this code and add another position at then end. So maybe there is a smart way to do this that I am not seeing!
Any thoughts? Thank you for your time!!!
= will assign the variable to a new value. It's replacing the old text with the current element's.
Instead, you want to append it. That's the + operator.
You can append the new text to the existing contents of listText.text and assign the result of that to listText.text itself (listText.text = listText.text + moreString), or, more conveniently, use the += operator, with is the shorthand for appending followed by assigning to self (listText.text += moreString).
Alternatively, instead of using a loop, you could use the string.Join() method, which will take an IEnumerable or an array, and join all the items with any string (like a newline character, in your case).
For example:
listText.Text = string.Join("\n", myShoppingList);

String comparison fails even when visually checked

I added a function to my application recently that reads a date from a downloaded file and finds the difference in days between current date and the date from the file. When done, it is displayed in a label in one of my forums.
There is an exception: if the string in the file equals "Lifetime", it should not process it as a date and follow alternate logic. But when I try to check if the string is "Lifetime", it does not return true, even if the string = "Lifetime".
EDIT: I fixed the FormatException with help from Nisarg. Now, my labels aren't changing to the values. This is the problem.
EDIT2: I feel stupid. I found out that I was initiating Main twice in one function, then using main1 to switch between forms and main to set the labels.
This is why the labels weren't working right. Thanks Nisarg and all other contributors.
Code example:
string subScript = File.ReadAllText(Path.GetTempPath() + txtUsername.Text + ".txt");
Main main = new Main();
double dSubLeft;
main.dateLabel.Text = subScript;
if (subScript == "Lifetime") // it bypasses this, apparently blank
{
main.daysLeftLabel.Text = "Expires: Never";
}
if (subScript != "Lifetime") //Goes here and throws error saying subScript is not valid DateTime
{
dSubLeft = Math.Round(Convert.ToDouble(Convert.ToString(((Convert.ToDateTime(subScript)) - DateTime.Now).TotalDays)));
string sSubLeft = Convert.ToString(dSubLeft);
main.daysLeftLabel.Text = "Expires: " + sSubLeft + " Days";
}
While using files you often get trailing blank spaces or newline characters. Try trimming the string before comparing it to Lifetime:
subScript = subScript.Trim().Trim(Environment.NewLine.ToCharArray());
Another (less likely) problem could be with the comparison itself. In C# the comparison in case-sensitive. So if you're comparing lifetime with Lifetime they are considered unequal. You should rather use case-insensitive comparison:
if(string.Equals(subScript, "Lifetime", StringComparer.OrdinalIgnoreCase))
OR
if(subScript.ToLower() == "lifetime")
You could also check if the subScript you are getting from the file is a valid date or not using DateTime.TryParse.
string subScript = File.ReadAllText(Path.GetTempPath() + txtUsername.Text + ".txt");
Main main = new Main();
double dSubLeft;
main.dateLabel.Text = subScript;
DateTime subScriptDate;
if(!DateTime.TryParse(subScript, out subScriptDate))
{
main.daysLeftLabel.Text = "Expires: Never";
}
else //Goes here and throws error saying subScript is not valid DateTime
{
dSubLeft = Math.Round(Convert.ToDouble(Convert.ToString((subScriptDate - DateTime.Now).TotalDays)));
string sSubLeft = Convert.ToString(dSubLeft);
main.daysLeftLabel.Text = "Expires: " + sSubLeft + " Days";
}
I think it is because main is the starting point of a program in C#, make another methodname if you donĀ“t want it to reset things from where the program is supposed to start from
That is my guess only, make a breakpoint in the beginning of your code and check through what info you get from each row in the code
Almost certainly, the actual content of the string is not actually the string "Lifetime". Probably because of white-space on either side. Try trimming.
Relevant edit:
if (subscript.Trim() == "Lifetime")
{
main.daysLeftLabel.Text = "Expires: Never";
}
else // don't retest for the opposite condition
{
...
As you can see, this thing is awfully fragile, because the string could still be many things that aren't a valid DateTime. Smells like homework, but there you go...
i think you should use
if(string.Equals(subScript, "Lifetime", StringComparer.OrdinalIgnoreCase))
{
//statement
}
else
{
//statement
}

C# : Printing variables and text in a textbox

I need to know the command that I can print a sentence like "the item Peter at row 233 and column 1222 is not a number " .
I far as now I have made this:
string[] lineItems = (string[])List[]
if (!Regex.IsMatch(lineItems[0], (#"^\d*$")))
textBox2.Text += " The number ,lineItems[0], is bigger than
10 " + Environment.NewLine;
I want to print the array fields that have error. So if it finds something it will print it.
I made a code that correctly prints that there is an error on this line of the array, but I cant print the item of the array.
I need to have an Environment.NewLine because I will print many lines.
Thanks ,
George.
foreach (int lineNumber in lineItems)
{
if (lineNumber > 10)
textBox2.Text += "The number " + lineNumber + " is bigger than 10\n";
}
Something like this should work, (I have not checked the c# code, I am working on a mac at the moment)
TextBox2.Text="This is FirstLine\nThis is Second Line";
The code is not compilable absolutely, but I may be understand what you're asking about.
If you are asking about how to compose the string of text box, by adding new strings to it, based on some desicional condition (regex), you can do folowing, pseudocode:
StringBuilder sb = new StringBuidler();
if (!Regex.IsMatch(lineItems[i], (#"^\d*$")))
sb.Append(string.Format(The number ,{0}, is bigger than 10, lineItems[i]) + Environment.NewLine);
textBox2.Text = sb.ToString();
If this is not what you want, just leave the comment, cause it's not very clear from post.
Regards.

Categories