11 Replies - 2118 Views - Last Post: 03 March 2013 - 08:02 AM Rate Topic: -----

#1 jess64k  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 08-November 11

Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 02 March 2013 - 06:17 PM

I'm making a calculator that performs operations sequentially (from left to right, not precedence), using ASP.NET/C#, but I'm having trouble trying to get the loops that run through the input box in my code behind to work right.

Obviously to me the logic seems to make sense, so I can't figure out why I get a runtime error if I enter just a number and no operands, and while my error checking does work when it comes to ensuring there are no two operators together, it displays that error even when I have two or more sets of numbers and operands placed correctly between them (I.E 24+5).

I am aware its a lot of code, and while I tried to put in as many comments to explain what's going on, I believe the problem lies within my loop and how I want it to build a string until it reaches an operator or the end of the input string.

 protected void btnEquals_Click(object sender, EventArgs e)
    {
        {
            lblError.Text = "";
            if (txtResult.Text.Length > 0)
            {
                double result = 0;
                Calculator myCalculator = new Calculator();
                string input = txtResult.Text;
                string Oper = "";
                int j = 0;

                while (j < input.Length)
                {
                    string temp = "";
                    double num1 = 0;
                    double num2 = 0;
                    /* get the numbers from the input string in order until the end of string or next operator */
                    while (input.Substring(j, 1) != "+" && input.Substring(j, 1) != "-" && input.Substring(j, 1) != "*" && input.Substring(j, 1) != "/")
                    {
                        temp += input.Substring(j, 1);
                        j++;
                    }
                    num1 = Convert.ToDouble(temp);  /*create number using the built substring */

                    /*check if next part of input is an operator, and if not check if end of string*/
                    if (input.Substring(j, 1) == "+" || input.Substring(j, 1) == "-" || input.Substring(j, 1) == "*" || input.Substring(j, 1) == "/")
                    {
                        Oper = input.Substring(j, 1);
                    }
                    else if (input.Substring(j, 1) == "")
                    {
                        if (result != 0)
                        {
                            switch (Oper)
                            {
                                case "+":
                                    result = myCalculator.Add(num1, num2);
                                    break;
                                case "-":
                                    result = myCalculator.Subtract(num1, num2);
                                    break;
                                case "*":
                                    result = myCalculator.Multiply(num1, num2);
                                    break;
                                case "/":
                                    result = myCalculator.Divide(num1, num2);
                                    break;
                            }
                        }
                        txtResult.Text = result.ToString();
                        break;
                    }
                    /*check if next part of input is another operator, or end of string, and display error if true*/
                    if (input.Substring(j, 1) == "+" || input.Substring(j, 1) == "-" || input.Substring(j, 1) == "*" || input.Substring(j, 1) == "/" && input.Substring(j, 1) != "")
                    {
                        lblError.Text = "You can't have two operands next to each other or an operand without a number to its right";
                        break;
                    }

                    /* get the numbers from the input string in order until the end of string or next operator (to build second number) */
                    temp = "";
                    while (input.Substring(j, 1) != "+" && input.Substring(j, 1) != "-" && input.Substring(j, 1) != "*" && input.Substring(j, 1) != "/")
                    {
                        temp += input.Substring(j, 1);
                        j++;
                    }
                    num2 = Convert.ToDouble(temp);  /*create number using the built substring*/

                    /*perform operation using calculator class*/
                    switch (Oper)
                    {
                        case "+":
                            result = myCalculator.Add(num1, num2);
                            break;
                        case "-":
                            result = myCalculator.Subtract(num1, num2);
                            break;
                        case "*":
                            result = myCalculator.Multiply(num1, num2);
                            break;
                        case "/":
                            result = myCalculator.Divide(num1, num2);
                            break;
                    }

                    /*if an operand still exists, check if there is another operand or null after that and print error, otherwise, repeat loop*/
                    if (input.Substring(j, 1) == "+" || input.Substring(j, 1) == "-" || input.Substring(j, 1) == "*" || input.Substring(j, 1) == "/")
                    {
                        Oper = input.Substring(j, 1);
                        j++;
                    }
                    else if (input.Substring(j, 1) == "")
                    {
                        break;
                    }
                    /*check if next part of input is another operator, or end of string, and display error if true*/
                    if (input.Substring(j, 1) == "+" || input.Substring(j, 1) == "-" || input.Substring(j, 1) == "*" || input.Substring(j, 1) == "/" && input.Substring(j, 1) != "")
                    {
                        lblError.Text = "You can't have two operands next to each other or an operand without a number to its right";
                        break;
                    }
                } /*repeat loop by reading next number (WIP)*/
                txtResult.Text = result.ToString();
            }
            else
            {
                txtResult.Text = string.Empty;
                lblError.Text = "There was no input entered!";
            }
        }
    }


Is This A Good Question/Topic? 0
  • +

Replies To: Problem with while loop in Sequential Calculator ASP.NET/C#

#2 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3252
  • View blog
  • Posts: 10,902
  • Joined: 12-December 12

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 02 March 2013 - 06:28 PM

You get an error but you haven't told us what this error is, and what line it refers to in your posted code. Post the error!

A quick look suggests to me that you are not increment j as often as you need to.

Actually, the reverse is also true. That is, you are only checking j < input.length once at the beginning of each loop. Your code looks for a number of characters without checking whether it has reached the end of the text.

This post has been edited by andrewsw: 02 March 2013 - 06:24 PM

Was This Post Helpful? 1
  • +
  • -

#3 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5441
  • View blog
  • Posts: 11,674
  • Joined: 02-June 10

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 02 March 2013 - 06:40 PM


tlhIn`toq's FAQ list

Learning to debug one's own code is an essential skill. Sadly, one that apparently few college courses teach. Silly if you ask me.

Placing breakpoints and walking through the code line by line allows you to actually WATCH it execute.

Visualizing what your code does will let you see why it behaves the way it does.

It would be well worth your time to do the tutorials on FAQ 2. A couple hours learning this skill will save you hundreds of hours of confusion in one project alone.


TOP most asked:
What does this error message mean?
FAQ 2: How do I debug
FAQ 3: How do I make Class1/Form1 talk to Class2/Form2


FAQ (Frequently Asked Questions - Updated Feb 2013
Spoiler



Was This Post Helpful? 0
  • +
  • -

#4 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3252
  • View blog
  • Posts: 10,902
  • Joined: 12-December 12

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 02 March 2013 - 07:02 PM

You are over-complicating this. I would consider something like:

    string sample = "34*8+5";
    string tempNum = "";
    List<string> parsed = new List<string>();

    foreach (char item in sample) {
        if (char.IsDigit(item) || item == '.') {
            tempNum += item;
        } else {
            parsed.Add(tempNum);
            tempNum = "";
            parsed.Add(item.ToString());     // operator
        }
    }
    if (tempNum != "") {
        // we should be left with one more number
        parsed.Add(tempNum);
    }
    string display = "";
    foreach (string item in parsed) {
        display += item + ", ";
    }
    display = display.TrimEnd(',', ' ');
    MessageBox.Show(display);

It needs additional checks to make sure the first item is a number, and to disallow consecutive operators, etc., but will still be much easier to manage than your currrent code.

This post has been edited by andrewsw: 02 March 2013 - 07:03 PM

Was This Post Helpful? 1
  • +
  • -

#5 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3252
  • View blog
  • Posts: 10,902
  • Joined: 12-December 12

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 02 March 2013 - 07:08 PM

Once you've collected the various bits in parsed you can loop through this again (having checked that it is valid) to perform your calculations.
Was This Post Helpful? 1
  • +
  • -

#6 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3252
  • View blog
  • Posts: 10,902
  • Joined: 12-December 12

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 02 March 2013 - 07:14 PM

I don't need the foreach, I/we can just use Join():

    string display = "";
    //foreach (string item in parsed) {
    //    display += item + ", ";
    //}
    display = String.Join(",", parsed);

    //display = display.TrimEnd(',', ' ');
    MessageBox.Show(display);

Was This Post Helpful? 1
  • +
  • -

#7 jess64k  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 08-November 11

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 02 March 2013 - 07:18 PM

View Postandrewsw, on 02 March 2013 - 07:02 PM, said:

You are over-complicating this. I would consider something like:

    string sample = "34*8+5";
    string tempNum = "";
    List<string> parsed = new List<string>();

    foreach (char item in sample) {
        if (char.IsDigit(item) || item == '.') {
            tempNum += item;
        } else {
            parsed.Add(tempNum);
            tempNum = "";
            parsed.Add(item.ToString());     // operator
        }
    }
    if (tempNum != "") {
        // we should be left with one more number
        parsed.Add(tempNum);
    }
    string display = "";
    foreach (string item in parsed) {
        display += item + ", ";
    }
    display = display.TrimEnd(',', ' ');
    MessageBox.Show(display);

It needs additional checks to make sure the first item is a number, and to disallow consecutive operators, etc., but will still be much easier to manage than your currrent code.


Sorry for not mentioning the error message, its my first time posting a code question!

The error I get when hitting the equals button when there is nothing or numbers without any operand in the string is:

System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
Parameter name: length

I had a strong feeling I was over complicating things. As tlhIn`toq mentioned, college classes do skip over the debugging feature of coding environments, and I hate to admit that mine is no exception, even moreso because our curriculum has us learning VB as a prereq then has us jump into C# without any knowledge of its functions :\

Thank you for the code example though, I will try it out and post back if I have any questions, if the help is willing :)
Was This Post Helpful? 0
  • +
  • -

#8 jess64k  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 08-November 11

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 02 March 2013 - 11:05 PM

Here is what I have so far. Its not displaying an error, and works if there are two numbers and an operand only in the input box. What's odd is that any more than that (I.E 2+4+5) and my "consecutive operators" error kicks in and despite my code to break the loop, it still does the math for the first two numbers and operator of that string (so 6 in the example).

I THINK the problem might be that certain variables are begin carried over into the next iteration of the loop, but I'm not quite sure. Any help would be much appreciated! Apologies in advance if I butchered your initial code Andrew and its intended direction.

 protected void btnEquals_Click(object sender, EventArgs e)
    {
        lblError.Text = "";
        if (txtResult.Text.Length > 0)
        {
            string input = txtResult.Text;
            string temp = "";     
            Calculator myCalculator = new Calculator();
            List<string> parsed = new List<string>();

            foreach (char item in input)
            {
                if (char.IsDigit(item) || item == '.')
                {
                    temp += item;  //number
                }
                else
                {
                    parsed.Add(temp);
                    temp = "";
                    parsed.Add(item.ToString());     // operator
                }
            }
            if (temp != "")
            {
                //we should be left with one more number, gets grabbed here
                parsed.Add(temp);
            }
           // string display = "";
            double num = 0;
            double num1 = 0;
            double num2 = 0;
            string Oper = "";

            foreach (string item in parsed) //do check/calc in here. Each 'item' is a set of numbers, or an operand
            {             
               if (double.TryParse(item, out num)) //check if item is a number
                {
                    if (num1 == 0) //if the first number isn't taken of the operation isn't taken, assign it
                    {
                        num1 = num;
                    }
                    else if (num2 == 0)//otherwise, make it the second number of the operation
                    {
                        num2 = num;
                    }
                }
                else //if its not a number, its an operand
                {
                    if (Oper != "") //check for consecutive operator, error if true
                    {
                        lblError.Text = "ERROR: You cannot have consecutive operators!";
                        break;
                    }
                   Oper = item;
                }
                //check for divide by 0, error if true
                if (Oper == "/" && num2 == 0)
                {
                    lblError.Text = "ERROR: Cannot divide by 0!";
                    break;
                }
               else if (Oper != "" && num2 != 0) //if there is a second number and an operand, perform a calculation
                {
                    double result = 0;
                    switch (Oper)
                    {
                        case "+":
                            result = myCalculator.Add(num1, num2);
                            break;
                        case "-":
                            result = myCalculator.Subtract(num1, num2);
                            break;
                        case "*":
                            result = myCalculator.Multiply(num1, num2);
                            break;
                        case "/":
                            result = myCalculator.Divide(num1, num2);
                            break;
                    }
                    txtResult.Text = result.ToString(); //output results to textbox          
                }
            } //repeat for next set of operations  
        }
        else
        {
            txtResult.Text = string.Empty;
            lblError.Text = "There is no input entered!";
        }
    }

Was This Post Helpful? 0
  • +
  • -

#9 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3252
  • View blog
  • Posts: 10,902
  • Joined: 12-December 12

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 03 March 2013 - 04:35 AM

As suggested by tlhIn`toq you need to learn how to debug your code. There is a tutorial link in my signature. But you also need to make sure that your algorithm - your solution - will work, perhaps using pen and paper :whistling:

I would probably use a for loop, looking at pairs of elements:

for (int i=0; i < parsed.Count-1; i = i+2)

I think you are concentrating too much on error checking. I would get it to work first! Convince yourself that it will work (with valid input) by testing it. Then gradually introduce error checking with a few if statements, using return; if an error is found, so that no further processing occurs.

The error checking should be fairly straight-forward:

Quote

Are there an odd number of elements?
Is every second (odd) element a valid number?
Is every middle element a valid operator? That is, is it in "+-*/"?


I would deal with division by zero a bit later, as it is a little more fiddly to determine.

This post has been edited by andrewsw: 03 March 2013 - 04:36 AM

Was This Post Helpful? 1
  • +
  • -

#10 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3252
  • View blog
  • Posts: 10,902
  • Joined: 12-December 12

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 03 March 2013 - 05:41 AM

The following seems to work, although I haven't tested it thoroughly:
    string sample = "30+2*2-5";
    string validOps = "+-*/";
    string tempNum = "";
    double tempDbl;
    List<string> parsed = new List<string>();

    foreach (char item in sample) {
        if (char.IsDigit(item) || item == '.') {
            tempNum += item;
        } else {
            parsed.Add(tempNum);
            if (Double.TryParse(parsed.Last(), out tempDbl)) {
                // do nothing..
            } else {
                MessageBox.Show("Not a number");
                return;
            }
            tempNum = "";
            parsed.Add(item.ToString());     // operator
            if ( validOps.Contains(item.ToString()) ) {
                // it's an operator, do nothing..
            } else {
                MessageBox.Show("Not a valid operator");
                return;
            }
        }
    }
    if (tempNum != "") {
        parsed.Add(tempNum);
    } else {
        MessageBox.Show("You didn't end with a number");
        return;
    }
    if (parsed.Count % 2 == 0) {
        MessageBox.Show("There should be an odd number of elements");
        return;
    }
    string display = "";
    display = String.Join(",", parsed);
    MessageBox.Show(display);

    double result = 0.0, num = 0.0;
    char oper = '\0';
    for (int i = 0; i < parsed.Count; i = i + 2) {
        if (i > 0) {
            num = Double.Parse(parsed[i]);
            switch (oper) {
                case '+':
                    result += num;
                    break;
                case '-':
                    result -= num;
                    break;
                case '*':
                    result *= num;
                    break;
                case '/':
                    if (num == 0.0) {
                        MessageBox.Show("Cannot divide by zero");
                        return;
                    }
                    result /= num;
                    break;
                default:
                    // do nothing
                    break;
            }
        } else {
            result = Double.Parse(parsed[i]);
        }
        if (i < parsed.Count - 1) {
            oper = Char.Parse(parsed[i + 1]);
        }
    }
    MessageBox.Show(String.Format("result is {0}", result));
}

but, of course, you would need to study, and adapt it, to make use of it with your myCalculator object.
Was This Post Helpful? 0
  • +
  • -

#11 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3252
  • View blog
  • Posts: 10,902
  • Joined: 12-December 12

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 03 March 2013 - 05:53 AM

I also need an extra check, checking that the last value is actually a number:

    if (tempNum != "") {
        if (Double.TryParse(tempNum, out tempDbl)) {
            // do nothing..
        } else {
            MessageBox.Show("Didn't end with a number");
            return;
        }
        parsed.Add(tempNum);
    } else {

Was This Post Helpful? 0
  • +
  • -

#12 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3486
  • View blog
  • Posts: 10,742
  • Joined: 05-May 12

Re: Problem with while loop in Sequential Calculator ASP.NET/C#

Posted 03 March 2013 - 08:02 AM

I suspect that part of the issue that our OP is having to contend with is the difficulty of debugging ASP.NET applications. The edit-compile-run cycle is much slower and there is more opportunities to lose focus between those transitions.

I highly recommend starting a small Console program that just has a hard coded string, and try working out the core of your algorithm first. The edit-compile-run cycle is much tighter and you don't have to fight with the vagaries of either IIS or the Development Web Server. Once you have your code working, transplant the core back into your ASP.NET program.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1