String comparison fails even when visually checked - c#

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
}

Related

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".

Exception while converting String to Double C#

I take data from four different pages and different domains.
1- .com
2- .co.uk
3- .ca
4- .co.jp
For all of the above i take number from Html and Convert them to Double using line:
string lowestSellerPrice = (Convert.ToDouble(fbalPrice) +
Convert.ToDouble(fbalsPrice)).ToString();
This works perfectly fine for the first 3 domains but for .co.jp even though there is always a number in fbalPrice and fbalsPrice it is always giving exception :
Input string was not in a correct format
Any suggestion as i have been struggling with this for too long now no result i also tried the try parse solution but no luck.
UPDATE:
See this:
I solved it like this :
The string were like " 1234" and " 111" and i then did Replace(" ",""); . And only number lift this however did not work so i did this:
if (fbalPrice.Contains(" "))
{
fbalPrice = fbalPrice.Remove(0, fbalPrice.IndexOf(" ") + 1).Replace(",","").Trim();
}
if(fbalsPrice.Contains(" "))
{
fbalsPrice = fbalsPrice.Remove(0, fbalsPrice.IndexOf(" ") + 1).Replace(",", "").Trim();
}
And then added them and it worked.

How to get rid of unwanted spaces after using ToString() in C#?

This might be a problem with Session and not ToString(), I'm not sure.
I have two .aspx pages and I want to pass an IP address from a datatable from one page to the other. When I do this, spaces get added that I don't want. The simple version of the code is this:
first .aspx page
int num = DropDownList1.SelectedIndex;
DataView tempDV = SqlDataSource2.Select(DataSourceSelectArguments.Empty) as DataView;
Session["camera"] = tempDV.Table.Rows[num].ItemArray[2];
Response.Redirect("test.aspx");
test.aspx page
string ipCamAdd = Session["camera"].ToString();
TextBox1.Text = "http://" + ipCamAdd + "/jpg/image.jpg?resolution=320x240";
what I want to print is
http ://ipadd/jpg/image.jpg?resolution=320x240
but what prints out is
http//ipaddress /jpg/image.jpg?resolution=320x240
how can I fix this?
Also, I asked this question hoping someone could tell me why this is happening as well. Sorry for the mistake.
Try this:
string ipCamAdd = Session["camera"].Trim().ToString();
For the valid concern, Session["camera"] could be null, add function such as the following to your code
static string ToSafeString(string theVal)
{
string theAns;
theAns = (theVal==null ? "" : theVal);
return theAns;
}
Then use:
string ipCamAdd = Session["camera"].ToSafeString().Trim();
You can use string.Replace if you just want to get rid of the spaces:
TextBox1.Text = "http://" + (ipCamAdd ?? "").Replace(" ", "") + "/jpg/image.jpg?resolution=320x240";
Trim the result before setting to session.
Session["camera"] = tempDV.Table.Rows[num].ItemArray[2].Trim();
Seems In SQL your data type is char(*) if you convert the data type to varchar and re enter data, you wont get any additional spaces

Check empty Char in a array 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]);

if/then/else variable frustration in C#

I asked a question a few days ago and folks were very forthcoming with help.
My circumstance have changed a little, and my code has as well.
I first need to ascertain if the current article group is one of several that need to be treated differently. If it is, it defines the var "strbody" using a complete value as retrieved from the database. If it is not one of those special article groups, then I have to do some string manipulation to format the retrieved value before defining and displaying it.
My string manipulation code works just like it should, but neither of the strbody vars I define in my if/then/else block is recognized when I call it below the code block???
Here is my code:
#{
string group = Model.ArticleGroupName;
if (group.Contains("Spacial Orientation")||group.Contains("Topography")||group.Contains("Osteology")||group.Contains("Angiology")||group.Contains("Neurology")||group.Contains("Myology")||group.Contains("Radiology")||group.Contains("Misc. Drawings")||group.Contains("Clinical Testing"))
{
var strbody = item.ShortBody;
}
else
{
string s = item.ShortBody;
string sLess = s.Remove(0, 12);
int index = sLess.IndexOf("Summary");
var strbody = (sLess.Substring(index + 8));
}
}
#strbody
This is the error:
\Plugins\FoxNetSoft.Articles\Views\ArticleRead\List.cshtml(76): error CS0103: The name 'strbody' does not exist in the current context
I don't understand how the var does not exist when I JUST defined it under either possible scenario...
I am new to this, so please don't hesitate to chastise me for doing dumb stuff...I need to learn!
UPDATE:
It is working perfectly now. Thanks to all those who helped!
Below is the final working code:
#{
string strbody = item.ShortBody;
string group = Model.ArticleGroupName;
var thestrbody = " ";
if (group.Contains("Spacial Orientation")||group.Contains("Topography")||group.Contains("Osteology")||group.Contains("Angiology")||group.Contains("Neurology")||group.Contains("Myology")||group.Contains("Radiology")||group.Contains("Misc. Drawings")||group.Contains("Clinical Testing"))
{
thestrbody = strbody;
}
else
{
string s = item.ShortBody;
string sLess = s.Remove(0, 12);
int index = sLess.IndexOf("Summary");
thestrbody = (sLess.Substring(index + 8));
}
}
#thestrbody
You defined it within a specific code block, and the scope is only within that code block. As soon as you close that block, the variable falls out of scope. In order to use it outside of that code block, you need to declare it before:
string strbody;
if(...)
{
// set the value of strbody
}
#strbody

Categories