How to prevent double decimals in a C# calculator - c#

I'm developing a calculator in C# and I have a button that inserts a decimal point into the number. I ran into a problem where it allows the user to insert multiple decimal points into the interface, which threw everything off. I cooked up this little statement:
if ((number % 1) > 0)
{
richTextBox1.Text = richTextBox1.Text + "";
}
else
{
richTextBox1.Text = richTextBox1.Text + ".";
}
Except it doesn't do anything! Will someone please show me a way to only allow one decimal point by fixing this statement?

onButtonToInsertDecimalClick
if richTextBox1.Text.Contains(".")
return;
else
... rest of code
Wouldn't this (pseudocode) work?

Have you tried using Double.TryParse directly?
if(Double.TryParse(richTextBox1.Text, myDoubleValue) == false)
richTextBox1.Text = lastGoodValue;
else
lastGoodValue = richTextBox1.Text;
this will also, via TryParse, give your actual double variable the proper result. As long as this occurs every time richTextBox1.Text changes, the correction code should also cause the double value to remain good, since it'll trigger when Text is reverted to lastGoodValue.

Related

Comparing data types in "if" statements in C#?

So, I'm creating a simple calculator getting started into programming in C# and I've had two issues so far that I have not been able to solve.
The first being that for some reason, of all operators/symbols, it won't let me add the "-" operator/symbol alongside a string. It only allows me to have the "-" operator with my variables alone. (I tried using double instead of decimal but got the same error).
The second (and more important) being that I'm trying to have an if statement that gives a message (and run another method) when the user inputs the wrong data type. Any way to solve this (or at least find a work-a-round)?
Thanks!
Here's a sample of the code containing both issues:
static void Calc()
{
Console.Write("\n\nPlease enter a number here: ");
decimal num1 = Convert.ToDecimal(Console.ReadLine());
Console.Write("Please Specify an operator: ");
string op = Console.ReadLine();
Console.Write("Please enter another number: ");
decimal num2 = Convert.ToDecimal(Console.ReadLine());
if (op == "+")
{
Console.WriteLine("The answer is: " + num1 + num2);
}
else if (op == "-")
{
Console.WriteLine("The answer is: " + num1 - num2);
}
else if (op == "*")
{
Console.WriteLine("The answer is: " + num1 * num2);
}
else if (op == "/")
{
Console.WriteLine("The answer is: " + num1 / num2);
}
else
{
OpElse();
}
if (num1 || num2 != Decimal)
{
Console.WriteLine("You must input a number");
Else();
}
I'm trying to have an if statement that gives a message (and run another method) when the user inputs the wrong data type. Any way to solve this (or at least find a work-a-round)?
You can try the Decimal.TryParse method, which will attempt to parse a string to a decimal, but wont throw an exception if it fails. It would look something like this:
if (!Decimal.TryParse(Console.ReadLine(), out decimal num1))
{
Console.WriteLine("No no my friend. You have to enter a valid number.");
}
..of all operators/symbols, it won't let me add the "-" operator/symbol alongside a string. It only allows me to have the "-" operator with my variables alone. (I tried using double instead of decimal but got the same error).
That has to do with operator precedence. In fact, even though minus is the only one that complains at compile time, the addition gives you are wrong result at runtime. The problem is just that the (first) + is being evaluated before the -. That results in the first number being added to the string, before doing the calculation. To fix this, simply wrap the calculation part in parenthesis:
Console.WriteLine("The answer is: " + (num1 - num2));
or move the calculation out of the string concatenation:
var result = num1 + num2;
Console.WriteLine("The answer is: " + result);
In the line:
Console.WriteLine("The answer is: " + num1 - num2);
It will add firstly num1 to the string, and then will try to subtract number from string, which is invalid. Use parenthesis "some string" + (num1 - num2)
Same error will happen with addition as well, for example: "a" + 5 + 2 will result in: a52
To check if entered data is incorrect, TryParse can be used, or same Convert.ToDecimal but with try catch
Console.Write("\n\nPlease enter a number here: ");
decimal num2 = 0; // Assigning default value so compiler doesn't comlain
try
{
num2 = Convert.ToDecimal(Console.ReadLine());
}
catch (FormatException e)
{
//do something else
}
num1 and num2 are always going to be decimal type so checking if their type is a decimal is unnecessary. If you want to display a message when parsing fails, look into using decimal#TryParse() which will return true if it parsed correctly, false if not.
As for your - sign issue. I'm not too sure what you mean but I'm assuming you're trying to do something like -"some string" which is invalid C# code. Decimal could convert negative numbers just fine when typed out, assuming you don't put a space between the minus and the number itself.
Or if you're trying to do something like "num1 - num2" that won't work unless you use string interpolation $"{num1+num2}" for an example
You correctly pointed out two problems:
1. Operator Failure
The + - * / operators. Remember order of operations, * / are first, + - are second, then left to right in groups of equal order. So in the write statements the * / get executed before the +. Resulting string + decimal, and since there is implicit converter from decimal to string the + operator acts as a concatenation.
In the case of - the order is string + decimal - decimal, which from left to right means the first + concatenates two strings. However, - is not an operator on string and therefore fails.
Try using the $"Answer is: {num1 + num2}" syntax for each case (changing the operator as required).
2. Logic Failure
You are converting and throwing a runtime exception in the Parse method prior to the tests and out put. As suggested, use TryParse and place the error case at the top.

Error in calculation Winforms C#

I am building C# WinForms application which has 3 textboxes. First two take value and after calculation show value in third textbox. It has to be in textbox so user can change value if thinks that calculation is wrong. Everything works perfect, but when I run app on windows 7 I get huge error, it calculates that (for example ) 2 times 2.15 is 430. Why is that happening ? I tried installing latest .Net framework on that computer but still doesn't work and after research I have no further ideas.
num1 = num2 = sum = 0;
if (tbNum1.Text.Contains(","))
{
tbNum1.Text = tbNum1.Text.Replace(",", ".");
}
double.TryParse(tbNum1.Text, out num1);
if (tbNum2.Text.Contains(","))
{
tbNum2.Text = tbNum2.Text.Replace(",", ".");
}
double.TryParse(tbNum2.Text, out num2);
sum = num1 * num2;
sum = Math.Round(sum, 2);
tbSum.Text = sum.ToString();
Also, additional two problems appear with displaying WinForm.
First is that panels have different sizes and positions than I programatically set.
Secont is that ( and I suppose that is my fault because I am probably doing that wrong ) all panels show very slow. What I have is like 6 panels with particular dimensions and 6 buttons. Depending on pressed button, I set all panels visible to false and only correct panel visible to true. But it loads very slow. Do you have any suggestions ? Thanks a lot in advance !
Your parse to a double is wrong. You can do it like this:
double num1, num2, product = 0;
if (tb1.Text.IndexOf(",") != -1)
{
tb1.Text = tb1.Text.Replace(",", ".");
}
num1 = double.Parse(tb1.Text, System.Globalization.CultureInfo.InvariantCulture);
if(tb2.Text.IndexOf(",") != -1)
{
tb2.Text = tb2.Text.Replace(",", ".");
}
num2 = double.Parse(tb2.Text, System.Globalization.CultureInfo.InvariantCulture);
product = Math.Round(num1 * num2,2);
tb3.Text = product.ToString();
The character that double.Parse recognizes as the decimal separator depends on the supplied IFormatProvider; if you don't supply any, that's the one for the current culture.
If you specifically want to use the dot as the decimal separator, you can just use CultureInfo.InvariantCulture:
double.TryParse(tbNum2.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out double num);

Celsius to Fahrenheit Conversion Form

I am trying to create a form that will convert Celsius to Fahrenheit and vice versa, but I am running into an error with the Conversion buttons code. The problem I am getting is that the variable convertedTemperature is left empty, so that should validation fail the message will be displayed via the ouput label(lblConvertedTemperature). But because of this being left blank I get the use of unassigned variable error. My question is how can I reword the processing section to not cause this error.
Double inputTemperature;// the variable that will store txtTemperatureInput for calculation
Double convertedTemperature;// the variable that will store the converted temperature
/*********************************
* INPUT *
* *******************************/
// when the user inputs a value and clicks calculate, the input must first be validated
if (Double.TryParse(txtTemperatureInput.Text, out inputTemperature) == false)
{
lblConvertedTemperature.Text = "Temperature must be a numeric value.";// message displayed in
//output label telling user their input was not accepted because it was not numeric
txtTemperatureInput.Focus();// sets the focus back onto the temperature textbox for a new entry
}
else
{
/*******************************
* PROCESSING *
*******************************/
if (optConvertToCelsius.Checked == true)// if the convert to celsius radio button is selected
// this statement will run
{
convertedTemperature = (inputTemperature - 32)*5 / 9;// the formula for converting
//Fahrenheit to Celsius
}
else if (optConvertToFahrenheit.Checked == true)// convert to fahrenheit was selected,
//meaning the convert to fahrenheit radio button was selected, so this statement will run
{
convertedTemperature = (inputTemperature * 9) / 5 + 32; ;// the formula for converting Celsius to
//Fahrenheit
}//end concatonated if
}//end if
/******************************
*OUTPUT *
******************************/
lblConvertedTemperature.Text = Math.Round(convertedTemperature, 4).ToString();// sets the converted temperature
// label to the value of convertedTemperature
}
}
}
My question is how can I reword the processing section to not cause this error.
Well, there are two situations that the compiler is concerned about:
If the input is invalid, you're already changing lblConvertedTemperature.Text anyway... so just return after you've done that. (You then don't need an else clause, which means you'll have less nesting - always nice for readability.)
Neither optConvertToCelsius nor optConvertToFahrenheit is checked. That's a situation the compiler considers, because you've got two separate conditions that you're checking. You may know it's never going to happen, of course.
For the latter, I'd suggest just removing the second condition:
if (optConvertToCelsius.Checked)
{
...
}
else
{
...
}
Note that I've removed the == true from the first condition just as a matter of style.
Now the compiler will know that if you get to this point, one of those two blocks will be executed. As both blocks assign to convertedTemperature, the variable will be definitely assigned at the end of that code.
EDIT: Just to clarify, if you have:
if (someCondition)
{
...
}
else if (someOtherCondition)
{
...
}
the compiler will not assume that one of those blocks will be executed, regardless of what the conditions are. Even if you know that exactly one condition will be true, the compiler just follows its relatively-simple rules.
You're scoping looks off. Simply move
/******************************
*OUTPUT *
******************************/
lblConvertedTemperature.Text = Math.Round(convertedTemperature, 4).ToString();// sets the converted temperature
// label to the value of convertedTemperature
To the "processing" scope.

Getting data from textboxes and multiply

I have:
textbox1.text == 1.4087
textbox2.text == 521.54
It's not hardcoded, I get it from JSON. Anyway, I want to multiply these two numbers.
I use this code:
double curr = 0.0;
double price = 0.0;
double multiply = 0.0;
double.TryParse(textBox1.Text, out curr);
double.TryParse(textBox2.Text, out price);
multiply = curr * price;
textBox3.Text = multiply.ToString();
I also tried with Convert.ToDouble still no luck.
I always get 0 in textBox3. Apparently the strings are not recognized as double. But they are. Any ideas? Thanks!
EDIT: From JSON:
{"high": "567.88", "last": "543.95", "timestamp": "1394987785",
I'm using this code to get what i need:
Regex expression = new Regex(#"last"":\s""(?<Identifier>[0-9]+\.[0-9]+)");
var results = expression.Matches(Cryp);
foreach (Match match in results)
{
textBox1.Text = match.Groups["Identifier"].Value;
}
Any issues here?
Try This:
double.TryParse(textBox1,NumberStyles.AllowDecimalPoint,
CultureInfo.InvariantCulture, out curr);
double.TryParse(textBox2.Text,NumberStyles.AllowDecimalPoint,
CultureInfo.InvariantCulture, out price);
multiply = curr * price;
I would assume one of the TryParse calls fails resulting in it keeping a value of 0 so regardless of what the working one is, you're going to get 0 for a result.
I just wrote up a basic ASP.NET application with three textboxes and then just pasted your code without changing anything into the event handler for a submit button. Manually typing the two numbers you provided gave the correct answer of 734.693398 in TextBox3. Your inputs must be off.

Code to show a string of text

I'm in my first semester of college, and we're doing C#. I have to make a Winforms app that can convert between Celsius and Fahrenheit. I have all the code down (basically), but I need to have the result output to a label. I can send the answer to the label with lblOutput = Output.ToString(); but I need a message like "[input] Celsius will is [output] Fahrenheit". I tried putting in between the brackets after "ToString" but I was getting an error.
I have everything else coded except for this. I have been looking for the last couple days to figure it out, but I can't find an answer. Any help is greatly appreciated.
Edit:
The code that I have set up appears inside of a button. I have two radio buttons that saying that the value put into a text box is either Far -> Cels or Cels -> Far.
This is what I have coded in my button. If there is any way to improve upon it, please let me know.
private void btnConvert_Click(object sender, EventArgs e)
{
decimal Input = Convert.ToDecimal(txtInput.Text); //grabs the input that the user entered
if (rbtnCelsius.Checked == true) //Test to see if the Celsius radio button is checked
{
decimal Output = ((Input - 32) * 5) / 9; //If yes, it uses this formula to convert the input from Farenheit to Celsius
txtOutput.Text = Output.ToString(); //Outputs the message to the user, showing the Celsius end point
}
else //Says that the Celsius Radio Button is not checked, meaning that the Farenheit radio button is
{
decimal Output = (Input * 9) / 5 + 32; //Moves onto this formula, converts Celsius to Farenheit
txtOutput.Text = Output.ToString(); //outputs the message to the user, showing the Farenheit end point
}
//txtOutput.Text = Output.ToString();
//Commented out because it gives an error saying that "Output does not exist in current context"
}
int fahrenheit, celsius;
// your code to set the two variables
string yourLabelText = String.Format("{0} Celcius is {1} Fahrenheit", celsius.ToString(), fahrenheit.ToString());
yourLabel.Text = yourLabelText;
Here is a reference for String.Format(). (thanks to Lukazoid!)
I don't know if you care about that, but for some cases you can get something like 12.243333333 by calling Output.ToString(), to make it more user-friendly, you can make it like this
Output.ToString("F2")
Which will change it to 12.24. You can use this together with string.Format like folks suggested.
I'm not sure what your question is about but if you need to format your output into a set phrase you can do this.
private void btnConvert_Click(object sender, EventArgs e)
{
decimal Input = Convert.ToDecimal(txtInput.Text); //grabs the input that the user entered
// declare this outside the loop so you can use it later.
decimal output = 0M;
if (rbtnCelsius.Checked == true) //Test to see if the Celsius radio button is checked
{
output= ((Input - 32) * 5) / 9; //If yes, it uses this formula to convert the input from Farenheit to Celsius
}
else //Says that the Celsius Radio Button is not checked, meaning that the Farenheit radio button is
{
output= (Input * 9) / 5 + 32; //Moves onto this formula, converts Celsius to Farenheit
}
txtOutput.Text =string.Format("{0} Celsius will is {1} Fahrenheit",input,output);
}`
p.s. Do remember to use a try parse method to ensure that the txtInput is definitely convertible to decimal.
you can use string.format to replace tokens like {0} or {1} in a string, or you can directly use string concatenation. I'd like to avoid directly giving you the answer since you said this is homework, but if you look for c# examples of this you should be able to find your way.

Categories