Switch statement = infinite loop

This is a discussion on Switch statement = infinite loop within the C++ Programming forums, part of the General Programming Boards category; alright... I'm writing a program and my switch statement seems to be causing an infinite loop in certain circumstances. When ...

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    9

    Switch statement = infinite loop

    alright... I'm writing a program and my switch statement seems to be causing an infinite loop in certain circumstances.

    When putting in the case numbers, the program works just fine... but when putting in any non-number character (letters, for instance), it enters an infinite loop. My default seems to do nothing.
    Also, if I input certain numbers ( 9 and 10, for instance), it doesn't trigger the default... but other numbers do (6 through 8)...

    I've tried everything I could think of. I've searched google and this forum. I'm using Microsoft Visual Studio .NET 2003

    Here's the entire program.
    Code:
    #include "stdafx.h"
    using std::cout;
    using std::cin;
    using std::endl;
    using std::fixed;
    
    #include <iomanip>
    using std::setprecision;
    
    int main()
    {
    	int product;
    	int quantity;
    	double product1 = 2.98;
    	double product2 = 4.5;
    	double product3 = 9.98;
    	double product4 = 4.49;
    	double product5 = 6.87;
    	double total = 0;
    	
    	cout << "We offer the following products: \n\nProduct 1 = $"<< product1
    		<< "\nProduct 2 = $" << fixed << setprecision( 2) << product2 << "\nProduct 3 = $"
    		<< product3 << "\nProduct 4 = $" << product4 << "\nProduct 5 = $" <<product5 
    		<< endl << endl;
    
    	cout << "Enter the product number you would like to purchase (-1 when finished): ";
    	cin >> product; 
    	 
    	while ( product != -1 )
    	{
    		switch ( product )
    		{
    		case 1:
    			cout << "Please enter the quantity you would like to purchase: ";
    			cin >> quantity;
    			total = total + ( product1 * quantity );
    			break;
    		
    		case 2:
    			cout << "Please enter the quantity you would like to purchase: ";
    			cin >> quantity;
    			total = total + ( product2 * quantity );
    			break;
    			
    		case 3:
    			cout << "Please enter the quantity you would like to purchase: ";
    			cin >> quantity;
    			total = total + ( product3 * quantity );
    			break;
    
    		case 4:
    			cout << "Please enter the quantity you would like to purchase: ";
    			cin >> quantity;
    			total = total + ( product4 * quantity );
    			break;
    
    		case 5:
    			cout << "Please enter the quantity you would like to purchase: ";
    			cin >> quantity;
    			total = total + ( product5 * quantity );
    			break;
    		
    		case '\n':
    		case '\t':
    		case ' ':
    			break;
    					
    		default: //catch all other characters
    			cout << "Incorrect character entered." << endl;
    			break;
    		}
    
    	cout << "Enter the product number you would like to purchase (-1 when finished): ";
        cin >> product;
    
    	}
    
    	cout << "\nThe total of all purchases is $" << fixed << setprecision( 2 )
    		<< total << endl;
    
    	return 0;
    }
    Last edited by Lucid003; 10-09-2005 at 10:50 PM.

  2. #2
    C++ Developer XSquared's Avatar
    Join Date
    Jun 2002
    Location
    Ontario, Canada
    Posts
    2,718
    Try adding 'product = -1;' in after the cout statement in your default. The break statement will just break out of the switch, not out of the while.
    Naturally I didn't feel inspired enough to read all the links for you, since I already slaved away for long hours under a blistering sun pressing the search button after typing four whole words! - Quzah

    You. Fetch me my copy of the Wall Street Journal. You two, fight to the death - Stewie

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    9
    Quote Originally Posted by XSquared
    Try adding 'product = -1;' in after the cout statement in your default. The break statement will just break out of the switch, not out of the while.
    Well, the thing is that I don't want the while statement to end on a default. I want it to cout that an incorrect character was entered and then prompt them to enter a character, and store it in product... but it just loops the "enter product number" line, without allowing any input.

    Anyway, I tried it and it resulted in telling me "Incorrect character entered." (just like it's supposed to), prompting me to enter another number, and then exiting the while statement (due to the product being equal to -1).

    So there is no infinite loop, but it does end the program before I would like it to.

    I've also tried setting the product to 0 (in the default), which appears to do nothing.
    Last edited by Lucid003; 10-09-2005 at 11:03 PM.

  4. #4
    C++ Developer XSquared's Avatar
    Join Date
    Jun 2002
    Location
    Ontario, Canada
    Posts
    2,718
    In that case, you need to put the cin<< part inside the while loop, and don't bother to set product to -1 in the default statement.
    Naturally I didn't feel inspired enough to read all the links for you, since I already slaved away for long hours under a blistering sun pressing the search button after typing four whole words! - Quzah

    You. Fetch me my copy of the Wall Street Journal. You two, fight to the death - Stewie

  5. #5
    Registered User
    Join Date
    Oct 2005
    Posts
    9
    Quote Originally Posted by XSquared
    In that case, you need to put the cin<< part inside the while loop, and don't bother to set product to -1 in the default statement.
    Hmm.. notice at the end of my while loop, I have this:
    Code:
    default: //catch all other characters
    			cout << "Incorrect character entered." << endl;
    			break;
    		}
    
    	cout << "Enter the product number you would like to purchase (-1 when finished): ";
        cin >> product;
    
    	}
    I do have a cin >> product just before my while loop ends.

    I also have a cin >> product before the while loop begins, in case they enter -1 as their first number. If I have it inside the beginning of the while loop, the while loop will always execute, and I don't want it to if they enter -1 for their first product.

    Anyway, even if I do put a cin >> product at the beginning of the loop, it still causes the infinite loop.


    I noticed that the book example I have uses
    "while ( ( grade = cin.get() ) != EOF )"
    but when I try to apply this to my program
    "while ( ( product = cin.get() ) != -1 )"
    It uses the default case even when I input correct numbers (1 through 5). Is there anything I'm doing wrong?
    Last edited by Lucid003; 10-09-2005 at 11:31 PM.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,344
    The problem with the original code is that product is an int variable. If you type a character when cin is attempting to read into an int, it goes into a fail state and causes the infinite loop.

    To solve this, in both places change
    Code:
    cin >> product;
    to
    Code:
    while (!(cin >> product))
    {
       cout << "Incorrect character entered." << endl;
       cin.clear();
       cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
       cout << "Enter the product number you would like to purchase (-1 when finished): ";
    }
    That clears the fail bit and ignores the bad characters typed by the user. You must also #include <limits> to use numeric_limits.
    Last edited by Daved; 10-10-2005 at 12:12 AM. Reason: Forgot the ! in the loop control.

  7. #7
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    The reason 9 and 10 didn't trigger the default is that 9 == '\t', 10 == '\n'. Characters are just integers, and typing the tab character isn't going to cause a tab character to be input -- cin is looking for digits.

  8. #8
    Registered User
    Join Date
    Oct 2005
    Posts
    9
    Daved, thanks for the help... unfortunetely I cannot use what you have provided me

    This is homework (if you couldn't guess :P ), and we aren't allowed to use anything that hasn't been covered in class up until this point.

    There's another thing that's bothering me. There is an example in the book (a gradebook) that uses an integer type, and allows for entering characters without going into a fail state... here's the code:

    Code:
    void GradeBook::inputGrades()
    {
       int grade; // grade entered by user
       cout << "Enter the letter grades." << endl
          << "Enter the EOF character to end input." << endl;
       // loop until user types end-of-file key sequence
       while ( ( grade = cin.get() ) != EOF )
       {
          // determine which grade was entered
          switch ( grade ) // switch statement nested in while
           {
              case 'A': // grade was uppercase A
              case 'a': // or lowercase a
                aCount++; // increment aCount
                break; // necessary to exit switch
     
    		  case 'B': // grade was uppercase B
              case 'b': // or lowercase b
                 bCount++; // increment bCount
                 break; // exit switch
    
              case 'C': // grade was uppercase C
              case 'c': // or lowercase c
                 cCount++; // increment cCount
                 break; // exit switch
    
              case 'D': // grade was uppercase D
              case 'd': // or lowercase d
                 dCount++; // increment dCount
                 break; // exit switch
    
              case 'F': // grade was uppercase F
              case 'f': // or lowercase f
                 fCount++; // increment fCount
                 break; // exit switch
    
              case '\n': // ignore newlines,
              case '\t': // tabs,
              case ' ': // and spaces in input
                 break; // exit switch
    
              default: // catch all other characters
                 cout << "Incorrect letter grade entered."
                    << " Enter a new grade." << endl;
                 break; // optional; will exit switch anyway
           } // end switch
        } // end while
    } // end function inputGrades
    ... I just don't get it. I ran this program and input characters that weren't allowed for in the case section (such as g and t) and it successfully defaulted...
    Last edited by Lucid003; 10-10-2005 at 12:56 AM.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,344
    Ok, the cin.get() function is a little weird. It gets a single character from the stream, but returns it as an int. So you should use cin.get() like the book shows.

    The key is that the int that is returned by cin.get() is the integer value of a character in the character set (ASCII most likely). So as Rashakil Fol said, if the user hits tab, cin.get() will return 9 (because '\t' is 9 in ASCII). So to get the example from the book to work on numbers, you just have to check for the 10 digit characters - '0', '1', '2', ... '9'. Make sure you check for a character like '1' instead of the actual integer 1 without the single quotes.

    Once you do that, there is one more change you'll need to make. Because you ask for input inside your loop (for the quantity), you will have to ignore the newline from when the user hits enter after inputting that quantity. An extra cin.get() after getting the quantity will get rid of that newilne so it doesn't screw up your next time through the loop.

  10. #10
    Registered User
    Join Date
    Oct 2005
    Posts
    9
    Quote Originally Posted by Daved
    Ok, the cin.get() function is a little weird. It gets a single character from the stream, but returns it as an int. So you should use cin.get() like the book shows.

    The key is that the int that is returned by cin.get() is the integer value of a character in the character set (ASCII most likely). So as Rashakil Fol said, if the user hits tab, cin.get() will return 9 (because '\t' is 9 in ASCII). So to get the example from the book to work on numbers, you just have to check for the 10 digit characters - '0', '1', '2', ... '9'. Make sure you check for a character like '1' instead of the actual integer 1 without the single quotes.

    Once you do that, there is one more change you'll need to make. Because you ask for input inside your loop (for the quantity), you will have to ignore the newline from when the user hits enter after inputting that quantity. An extra cin.get() after getting the quantity will get rid of that newilne so it doesn't screw up your next time through the loop.
    Well, either I'm not understanding the cin.get() part in your last paragraph, or I'm just implementing it incorrectly. Either way it's a lot of trouble.

    Thanks for the help, everyone. I've got a workaround (that I'm not happy with, but it works) where I declare product as a char instead. I really wish I could've gotten this to work with it as an int, but it seems that having a quantity thrown in there complicates things, as opposed to having just the product.

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,344
    Actually, switching it to a char is a good solution. Probably better than my suggestion. That way you always use cin >> to read in each piece of input and you don't have to worry about my last paragraph (which only applies to mixing cin.get() and cin >> in the same program).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. syntax question
    By cyph1e in forum C Programming
    Replies: 19
    Last Post: 03-31-2006, 12:59 AM
  2. I need help as soon as possible.
    By hyrule in forum C++ Programming
    Replies: 7
    Last Post: 11-09-2005, 05:49 PM
  3. Replies: 1
    Last Post: 08-31-2004, 05:07 AM
  4. Switch statement
    By big146 in forum C++ Programming
    Replies: 7
    Last Post: 06-25-2004, 08:16 AM
  5. can (switch) be apart of a loop?
    By matheo917 in forum C++ Programming
    Replies: 2
    Last Post: 09-20-2001, 07:29 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21