Cannot calculate decimals in my calculator - c#

So, I have made a calculator in C# but it cannot calculate decimal numbers.
It works perfectly fine when clicking on for example the buttons: 6 then . (this is a dot) then 5. But as soon as I click on the "+"-button (or any other operator) afterwards in the form, the program stops and I get a message saying that
"An unhandled exception of type 'System.FormatException' occured in
mscorlib.dll. The input string was not in a correct format".
I don't know exactly how to solve this. Is there anyone that knows how to solve this problem?
Here is my code:
namespace Kalkylator{
public partial class Form1 : Form{
String operation = ""; //the operation we will use
Double resultat = 0; //the result we will get
bool finished = false; //if false, we have not pressed the "=" button yet
public Form1(){
InitializeComponent();
}
//
private void button_click(object sender, EventArgs e){
if (finished == true){ //if we press any operator, clear the textbox-window so new numbers can be entered
textBoxFonster.Clear();
}
finished = false; //we are not done with the calculation
Button b = (Button)sender;
if (b.Text == "."){
if (!textBoxFonster.Text.Contains(".")){
textBoxFonster.Text = textBoxFonster.Text + b.Text;
}
}
else{
textBoxFonster.Text = textBoxFonster.Text + b.Text; //writes the number in the textBox
}
}
private void operator_click(object sender, EventArgs e)
{
Button b = (Button)sender;
operation = b.Text; //the operation we will perform is the operatorButton we will press
resultat = Double.Parse(textBoxFonster.Text); //HERE IS WHERE THE PROGRAM GIVES ME THE ERROR.
finished = true; //we are done with the calculation
}
private void clear_click(object sender, EventArgs e)
{
textBoxFonster.Text = ""; //clear the window from all text
resultat = 0; //clear the value of resultat and set it to 0
}
private void LikaMed_click(object sender, EventArgs e)
{
switch(operation){
case "+": //add the result with the text in the textBox
textBoxFonster.Text = (resultat + Double.Parse(textBoxFonster.Text)).ToString();
break;
case "-":
textBoxFonster.Text = (resultat - Double.Parse(textBoxFonster.Text)).ToString();
break;
case "*":
textBoxFonster.Text = (resultat * Double.Parse(textBoxFonster.Text)).ToString();
break;
case "%":
textBoxFonster.Text = (resultat / Double.Parse(textBoxFonster.Text) * (resultat/100)).ToString();
break;
case "^":
textBoxFonster.Text = (Math.Pow(resultat, Double.Parse(textBoxFonster.Text))).ToString();
break;
case "Log": //takes the 10th log of resultat
textBoxFonster.Text = (Math.Log10(resultat)).ToString();
break;
case "Sqrt":
textBoxFonster.Text = (Math.Sqrt(resultat)).ToString();
break;
case "/": //divide the result with the text in the textBox if that text is not 0. If so, show an error message
if ((Double.Parse(textBoxFonster.Text)) != 0){
textBoxFonster.Text = (resultat / Double.Parse(textBoxFonster.Text)).ToString();
}
else{ //show error in MessageBox
MessageBox.Show("Cannot divide by 0!");
}
break;
default:
break;
}
finished = true; //this will clear the result textbox when clicking another number after the equal sign has been clicked
}
}
}

Don't use Double.Parse without specifying the Culture.
Change:
switch(operation){
case "+": //add the result with the text in the textBox
textBoxFonster.Text = (resultat + Double.Parse(textBoxFonster.Text)).ToString();
break;
case "-":
textBoxFonster.Text = (resultat - Double.Parse(textBoxFonster.Text)).ToString();
break;
to:
Double operand1=resultat;
Double operand2=0;
Double.TryParse(textBoxFonster.Text,NumberStyles.Float,CultureInfo.InvariantCulture,out operand2);
switch(operation){
case "+": //add the result with the text in the textBox
textBoxFonster.Text = (operand1 + operand2).ToString();
break;
case "-":
textBoxFonster.Text = (operand1 - operand2).ToString();
break;
Alternatively, you could actually support multiple cultures, and change this code:
if (b.Text == "."){
if (!textBoxFonster.Text.Contains(".")){
textBoxFonster.Text = textBoxFonster.Text + b.Text;
}
}
to this:
if (b.Text == System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator){
if (!textBoxFonster.Text.Contains(System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator)){
textBoxFonster.Text = textBoxFonster.Text + b.Text;
}
}

Related

C# WinAppCalculator to WebAppCalculator

Hi I am pretty new to coding especially in c# and have a problem with my project. I am looking to make a calculator online using c# and upload it to a database and host in azure. Here is my question:
I am having a problem with my c# code in Visual Studio using web forms. It is simply not working, It can input numbers and operations however does not get the correct result e.g. 3 + 3 = 33. This is a conversion from WinApp, so it may be from there? But I re-created the UI and repurposed the code to fit a online app. After I get this to work I plan on uploading it to azure. Is there any reason why this is not working? My WinApp in .NET has a very similar code and works so is it a .NET/ASP.net issue? Any help is appreciated!
Here is the .aspx.cs file:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication2
{
public partial class WebForm1 : Page
{
protected void Page_Load(object sender, EventArgs e)
{
ViewState["operationPerf"] = "false";
ViewState["operation"] = string.Empty;
ViewState["answer"] = "0";
}
protected void NumbEvent(object sender, EventArgs e)
{
if (textbox.Text == "0" || bool.Parse(ViewState["operationPerf"].ToString()) == true)
textbox.Text = string.Empty;
Button butt = (Button)sender;
textbox.Text += butt.Text;
ViewState["operationPerf"] = false;
label.Text = label.Text + " " + textbox.Text;
}
protected void OperandEvent(object sender, EventArgs e)
{
ViewState["operationPerf"] = true;
Button butt = (Button)sender;
string newOperand = butt.Text;
label.Text = label.Text + " " + newOperand;
switch (ViewState["operation"])
{
case "+":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) + Double.Parse(textbox.Text)).ToString();
break;
case "-":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) - Double.Parse(textbox.Text)).ToString();
break;
case "*":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) * Double.Parse(textbox.Text)).ToString();
break;
case "/":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) / Double.Parse(textbox.Text)).ToString();
break;
case "^":
textbox.Text = (Math.Pow(Double.Parse(Convert.ToString(ViewState["answer"])), Double.Parse(textbox.Text))).ToString();
break;
case "√":
textbox.Text = (Math.Sqrt(Double.Parse(textbox.Text))).ToString();
break;
default:
break;
}
ViewState["answer"] = textbox.Text;
ViewState["operation"] = newOperand;
}
protected void Bequal_Click(object sender, EventArgs e)
{
ViewState["operationPerf"] = true;
switch (ViewState["operation"])
{
case "+":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) + Double.Parse(textbox.Text)).ToString();
break;
case "-":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) - Double.Parse(textbox.Text)).ToString();
break;
case "*":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) * Double.Parse(textbox.Text)).ToString();
break;
case "/":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) / Double.Parse(textbox.Text)).ToString();
break;
case "^":
textbox.Text = (Math.Pow(Double.Parse(Convert.ToString(ViewState["answer"])), Double.Parse(textbox.Text))).ToString();
break;
case "√":
textbox.Text = (Math.Sqrt(Double.Parse(textbox.Text))).ToString();
break;
default:
break;
}
label.Text = label.Text + " = " + textbox.Text;
label.Text = "";
ViewState["answer"] = textbox.Text;
textbox.Text = ViewState["answer"].ToString();
ViewState["answer"] = 0;
ViewState["operation"] = "";
}
protected void BC_Click(object sender, EventArgs e)
{
textbox.Text = "0";
label.Text = "";
ViewState["answer"] = 0;
ViewState["operation"] = "";
}
}
This is my original code before attempting to fix the issue:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication2
{
public partial class WebForm1 : Page
{
bool operationPerf = false;
string operation = "";
double answer = 0;
protected void NumbEvent(object sender, EventArgs e)
{
if (textbox.Text == "0" || operationPerf)
textbox.Text = string.Empty;
Button butt = (Button)sender;
textbox.Text += butt.Text;
operationPerf = false;
label.Text = label.Text + " " + textbox.Text;
}
protected void OperandEvent(object sender, EventArgs e)
{
operationPerf = true;
Button butt = (Button)sender;
string newOperand = butt.Text;
label.Text = label.Text + " " + newOperand;
switch (operation)
{
case "+":
textbox.Text = (answer + Double.Parse(textbox.Text)).ToString();
break;
case "-":
textbox.Text = (answer - Double.Parse(textbox.Text)).ToString();
break;
case "*":
textbox.Text = (answer * Double.Parse(textbox.Text)).ToString();
break;
case "/":
textbox.Text = (answer / Double.Parse(textbox.Text)).ToString();
break;
case "^":
textbox.Text = (Math.Pow(answer, Double.Parse(textbox.Text))).ToString();
break;
case "√":
textbox.Text = (Math.Sqrt(Double.Parse(textbox.Text))).ToString();
break;
default:
break;
}
answer = Double.Parse(textbox.Text);
operation = newOperand;
}
protected void Bequal_Click(object sender, EventArgs e)
{
operationPerf = true;
switch (operation)
{
case "+":
textbox.Text = (answer + Double.Parse(textbox.Text)).ToString();
break;
case "-":
textbox.Text = (answer - Double.Parse(textbox.Text)).ToString();
break;
case "*":
textbox.Text = (answer * Double.Parse(textbox.Text)).ToString();
break;
case "/":
textbox.Text = (answer / Double.Parse(textbox.Text)).ToString();
break;
case "^":
textbox.Text = (Math.Pow(answer, Double.Parse(textbox.Text))).ToString();
break;
case "√":
textbox.Text = (Math.Sqrt(Double.Parse(textbox.Text))).ToString();
break;
default:
break;
}
label.Text = label.Text + " = " + textbox.Text;
label.Text = "";
answer = Double.Parse(textbox.Text);
textbox.Text = answer.ToString();
answer = 0;
operation = "";
}
protected void BC_Click(object sender, EventArgs e)
{
textbox.Text = "0";
label.Text = "";
answer = 0;
operation = "";
}
}
}
If you're getting 33 as the result of 3 + 3 then that suggests to me that you're using the + operator on two strings (or maybe a string and a number) rather than two numbers, i.e. the + operator is doing string concatenation rather than addition.
If you use the + operator on two numbers (types such as int, float, double, decimal) then it adds the two numbers together as you'd expect.
However, if you use the + operator on
two strings, or
a string and an instance of something which has an implementation of the ToString method (which means pretty much anything which isn't a struct, because all classes in .net are derived from object, which has a ToString method)
then it concatenates the two strings, or the string and the return value of the other object's ToString method. (* see footnote)
I can't see in the code where this is happening, but I'd suggest a bit of refactoring which would make it easier to track down.
This switch block has quite a lot of repetition:
switch (ViewState["operation"])
{
case "+":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) + Double.Parse(textbox.Text)).ToString();
break;
case "-":
textbox.Text = (Double.Parse(Convert.ToString(ViewState["answer"])) - Double.Parse(textbox.Text)).ToString();
break;
All those calls to Double.Parse are going to return the same two values, regardless of which one is executed, so only make the calls once and cache the result, e.g.
var answer = Double.Parse(Convert.ToString(ViewState["answer"]));
var textboxValue = Double.Parse(textbox.Text);
switch (ViewState["operation"])
{
case "+":
textbox.Text = (answer + textboxValue).ToString();
break;
case "-":
textbox.Text = (answer - textboxValue).ToString();
break;
This gives you shorter lines, easier to read, easier to spot any mistakes, and importantly there are fewer nested brackets. Transposing a bracket and a comma in a long and complex line of code, in the best case scenario causes a compiler error, but if it doesn't then it can cost hours of investigating why the application is misbehaving.
I also notice that this entire switch block appears to be repeated in both the OperandEvent and Bequal_Click methods. Do you need it in both? I can't tell from looking at the posted code, but it's something I'd suggest you think about. If you do need it in both, and it needs to behave identically in both, then move it into its own private method, and call that method from the OperandEvent and Bequal_Click methods.
May I draw your attention to the Don't Repeat Yourself principle of software development?
OF ALL THE PRINCIPLES OF PROGRAMMING, Don’t Repeat Yourself (DRY) is perhaps one of the most fundamental. The principle was formulated by Andy Hunt and Dave Thomas in The Pragmatic Programmer, and underlies many other well-known software development best practices and design patterns. The developer who learns to recognize duplication, and understands how to eliminate it through appropriate practice and proper abstraction, can produce much cleaner code than one who continuously infects the application with unnecessary repetition.
Duplication Is Waste
Every line of code that goes into an application must be maintained, and is a potential source of future bugs. Duplication needlessly bloats the codebase, resulting in more opportunities for bugs and adding accidental complexity to the system. The bloat that duplication adds to the system also makes it more difficult for developers working with the system to fully understand the entire system, or to be certain that changes made in one location do not also need to be made in other places that duplicate the logic they are working on. DRY requires that “every piece of knowledge must have a single, unambiguous, authoritative representation within a system.”
Any time you find yourself writing more or less the same block of code more than once, you should ask yourself, "can I refactor this code into a new, shorter line, a new reusable method, or maybe even a new class?"
I hope you find this answer helpful, and wish you the best of luck in your studies.
Footnote
What I said about the behaviour of the + operator isn't the whole truth, because a class can explicitly define how the + and other operators behave when applied to an instance of that class (this is known as operator overloading). But you say you're new to programming, and this detail isn't really relevant to this question, so don't worry about it for now.

C# Calculator, Equal button won't perform operation on second click

I'm building calculator (similar to win10 standard calculator), and problem is when you click equal button twice or more. I'm getting second argument from textBox and every time you click equal button it changes it's text value.
e.g when you type 10 + 5 = 15 and then you press button again it shows 25 instead of 20 and so on.
private void buttonEqual(object sender, EventArgs e)
{
secondArg = Convert.ToDouble(textBox1.Text);
switch (oper) {
case "+":
result = firstArg + Convert.ToDouble(label7.Text);
textBox1.Text = result.ToString();
label3.Text = firstArg.ToString();
break;
case "-":
result = firstArg - secondArg;
textBox1.Text = result.ToString();
label3.Text = result.ToString();
break;
case "*":
result = firstArg * secondArg;
textBox1.Text = result.ToString();
label3.Text = result.ToString();
break;
case "/":
result = firstArg / secondArg;
textBox1.Text = result.ToString();
label3.Text = result.ToString();
break;
case "^":
result = Math.Pow(firstArg, secondArg);
textBox1.Text = result.ToString();
break;
In your + case, you set label3.Text = firstArg.ToString();. In all the other cases shown you set it equal to result. Set label3.Text = result.ToString(); to fix.
You also don't use secondArg in the + case, this might be contributing to your issue as well.

Thrown system.exception.stackoverflowexception C#

In my C# windows form application, there is a combo box that has 3 options in it, when selecting second one a switch command that checks options of another combo box throws and exception of type stack overflow, with this details:
System.StackOverflowException occurred
HResult=0x800703E9
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>
Update:
this is the event of index change in combo box:
private void cmbxDoorType_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbxDoorType.SelectedIndex == 0)
{
chkTopBlock.Enabled = true;
if(chkTopBlock.Checked)
cmbxTopBlockConfig.Enabled = true;
cmbxTopSideConfig.Enabled = true;
txtDoorHeight.ReadOnly = false;
txtTotalWidth.Visible = false;
lblTotalWidth.Visible = false;
lblDoorBaleWidth.Enabled = false;
}
else if (cmbxDoorType.SelectedIndex == 1)
{
txtTotalWidth.Visible = false;
lblTotalWidth.Visible = false;
lblDoorBaleWidth.Enabled = false;
cmbxTopBlockConfig.Enabled = false;
chkTopBlock.Enabled = false;
txtDoorHeight.ReadOnly = true;
cmbxTopSideConfig.Enabled = false;
}
else
{
chkTopBlock.Enabled = true;
if (chkTopBlock.Checked)
cmbxTopBlockConfig.Enabled = true;
cmbxTopSideConfig.Enabled = true;
txtDoorHeight.ReadOnly = false;
txtTotalWidth.Visible = true;
lblTotalWidth.Visible = true;
lblDoorBaleWidth.Enabled = true;
}
Prediction();
}
this is the prediction methode than exception ocours in:
internal void Prediction ()
{
if (Globals.ProjectType=="Gama")
{
int TotalHeight_=0;
double DesignHeight_=0;
int TotalWidth_=0;
double LeftDis = 0;
double RightDis = 0;
double RowsTotalHeight_=0;
double TopBlockHeight_=0;
double thisDoorHeight_ = 0;
int DoorHeight_=0;
int DoorWidth_=0;
double DoorBaleWidth_=0;
try
{
switch (cmbxLeftSideConfig.SelectedIndex) //exception thrown here
{
case 0:
LeftDis = GamaGlobals.Constants.BeamThickness - GamaGlobals.Constants.InsertOffset;
break;
case 2:
LeftDis = GamaGlobals.Constants.GP115Body + GamaGlobals.Constants.BeamThickness - GamaGlobals.Constants.InsertOffset;
break;
case 3:
LeftDis = GamaGlobals.Constants.GP114Body + GamaGlobals.Constants.BeamThickness - GamaGlobals.Constants.InsertOffset;
break;
case 4:
LeftDis = GamaGlobals.Constants.GP117Height - GamaGlobals.Constants.InsertOffset;
break;
case 1:
LeftDis = 0;
break;
}
switch (cmbxRightSideConfig.SelectedIndex)
{
case 0:
RightDis = GamaGlobals.Constants.BeamThickness - GamaGlobals.Constants.InsertOffset;
break;
case 2:
RightDis = GamaGlobals.Constants.GP115Body + GamaGlobals.Constants.BeamThickness - GamaGlobals.Constants.InsertOffset;
break;
case 3:
RightDis = GamaGlobals.Constants.GP114Body + GamaGlobals.Constants.BeamThickness - GamaGlobals.Constants.InsertOffset;
break;
case 4:
RightDis = GamaGlobals.Constants.GP117Height - GamaGlobals.Constants.InsertOffset;
break;
case 1:
RightDis = 0;
break;
}
}
Something in your cmbxDoorType_SelectedIndexChanged, or another SelectedIndexChanged event will retrigger your event again, which makes it a StackOverFlowException after a couple of seconds
in "prediction" method there was a line that changes a textbox value, and that text box itself has a value changed event that triggers "prediction" again.
so it's solved.
just as another question, is there a way to change textbox/numericupdown controls value programmatically without triggering its change event?
for example, if the user changes it, it triggers event but when its programmatically changed, the event does not trigger.
hm??

How can I find the last character of a textbox text?

I am a beginner in C#. I am making a web calculator like Microsoft Desktop calculator with the help of asp.net. But I'm stuck at one place. My code for Plus, minus, multiply or div is like:
protected void btnPlus_Click(object sender, EventArgs e)
{
if (txtBox1.Text.EndsWith("+"))
{
txtBox1.Text = txtBox1.Text;
}
else
{
txtBox1.Text = txtBox1.Text + "+";
ViewState["Operation"] = "+";
}
}
But I want to check this condition for all operations like minus, multiply and divide. I don't want Plus, Minus, Multiply or Div signs appear in the textbox.
You can store all your operators in a string constant and check if the last character is contained in that string:
private const string OPERATORS = "+-/*";
protected void btnPlus_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtBox1.Text) || // check if string is empty
OPERATORS.Contains(txtBox1.Text.Last())) // or if last character is a operator
{
txtBox1.Text = txtBox1.Text;
}
else
{
txtBox1.Text = txtBox1.Text + "+";
ViewState["Operation"] = "+";
}
}
You can do something like the following:
Extract last character
Based on the character assign operator to the view state
If it is any operator then remove them from the textbox
Finally do the operation
if (txtBox1.Text != "")
{
char last_char = txtBox1.Text[txtBox1.Text.Length - 1];
switch (last_char)
{
case '+':
ViewState["Operation"] = "+";
txtBox1.Text.Remove(txtBox1.Text.Length - 1);
break;
case '-':
ViewState["Operation"] = "-";
txtBox1.Text.Remove(txtBox1.Text.Length - 1);
break;
// do the same for all operators
default:
break;
}
}

Textbox validation 2 char and 2 integer

i need to validate textbox1 as 2 alphabets and 2integer only i.e) ab11
how i can set it my text box only accept 2 chars and 2 integers.
Please help me...
if:
string myString = textbox1.Text;
Then to validate:
If (Regex.IsMatch(myString, "^[A-Za-z]{2}[0-9]{2}$")))
{
return true;
}
else
{
return false;
}
private void textBox2_Validating(object sender, CancelEventArgs e)
{
var cn = textBox2.Text.Where(c => char.IsLetter(c)).Count();
var cd = textBox2.Text.Where(c => char.IsNumber(c)).Count();
if (cn >= 2 && cd >= 2)
{
//Success, Do Stuff
}
else
{
e.Cancel = true;
}
}
This should work.
private void textBox1_TextChanged(object sender, EventArgs e)
{
TextBox tb=sender as TextBox;
string text=tb.Text;
switch (text.Length)
{
case 1:
if (!char.IsLetter(text[0]))
tb.Text = "";
break;
case 2:
if (!char.IsLetter(text[1]))
tb.Text = text.Remove(1);
break;
case 3:
if (!char.IsNumber(text[2]))
tb.Text = text.Remove(2);
break;
case 4:
if (!char.IsNumber(text[3]))
tb.Text = text.Remove(3);
break;
default:
if(text.Length>4)
tb.Text = text.Substring(0, 4);
break;
}
textBox1.Select(tb.Text.Length, 0);
}
string str = textBox1.Text;
if (Regex.IsMatch(str, #"^(([A-Z]|[a-z])([A-Z]|[a-z])\d\d)$"))
{
MessageBox.Show("Valid");
}
Reference: Regex Class

Categories