Menu

help with my first loop test program

Will P
2008-06-18
2012-09-26
  • Will P

    Will P - 2008-06-18

    hey, i've been trying to learn how to code on my own and i was making decent progress until i got to loops. the program runs and loops like it should, the only problem is if the person enters a letter instead of a number like they're suppose to in the beginning, then the program goes into an infinite loop. can anyone tell me what i'm doing wrong or edit my code? here it is:

    include <iostream>

    using namespace std;

    int main ()
    {
    int x;
    char answer = 'y';

        while (answer == 'y') {
    cout&lt;&lt;&quot;Enter a number: &quot;;
    cin&gt;&gt; x;
    
    cout&lt;&lt;&quot;You entered: &quot;&lt;&lt; x &lt;&lt; endl;
    cout&lt;&lt;&quot;Would you like to try again?(y/n): &quot;;
    cin&gt;&gt; answer;
        }
    
    if (answer == 'n')
        cout&lt;&lt;&quot;Ok, goodbye!&quot;&lt;&lt; endl;
    
    
        else
        cout&lt;&lt;&quot;Invalid Operation&quot;&lt;&lt; endl;
    
    system(&quot;PAUSE&quot;);
    return 0;
    

    }

    i appreciate any help =P

     
    • cpns

      cpns - 2008-06-20

      If you enter something that does not match the expected format for the type (i.e an integer in this case), then the variable is not assigned. When you display x it will show whatever happened to be in there before the call, and it was uninitialised in any case.

      If a formatted input fails to match the expected type, the stream's failbit is set, the after all calls to the stream are ignored (including the istream::ignore()!). You can test for the failbit with istream::fail(), but since there are other possible stream error states, it is best to test them all with istream::good().

      You know that your testing of "answer" at the end of your loop is entirely redundant?

      To fix your while loop, consider this:

      while (answer == 'y'){
          cout&lt;&lt;&quot;Enter a number: &quot;;
          cin&gt;&gt; x;
          if( !cin.good() )
          {
              cout &lt;&lt; &quot;Try again.&quot; &lt;&lt; endl ;
              cin.clear() ;
              cin.ignore( numeric_limits&lt;streamsize&gt;::max(), '\n' );
          }
          else
          {
              cin.ignore( numeric_limits&lt;streamsize&gt;::max(), '\n' );
      
              cout&lt;&lt;&quot;You entered: &quot;&lt;&lt; x &lt;&lt; endl;
              cout&lt;&lt;&quot;Would you like to try again?(y/n): &quot;;
              cin&gt;&gt; answer;
              cin.ignore( numeric_limits&lt;streamsize&gt;::max(), '\n' );
          }
      }
      

      Note the ignore() for both when the input succeeds and fails!

      And do read some documentation: http://www.cplusplus.com/reference/iostream/

      Clifford

       
    • Will P

      Will P - 2008-06-23

      heh and of course i wouldn't have even noticed till i was able to try it. thanks for the fix, i'm gonna go hit the books and read everything over and over till i understand more.

       
    • cpns

      cpns - 2008-06-18

      Console input is line oriented; so console input functions do not return until an entire line is bufferred. When you use formatted input and ask for a number, (as in "cin >> x" ), the istream::opperator>> will leave the input in teh buffer since it does not match what it was looking for. The next time you ask for a number, there is a line still in the buffer, so it returns immediatly, but the input still does not match, so it remains in the buffer and so on forever.

      After any formatted input, flush the line with:

      cin.ignore( numeric_limits<streamsize>::max(), '\n' );

      i.e.

      cin>> x;
      cin.ignore( numeric_limits<streamsize>::max(), '\n' );

      ...

      cin>> answer;
      cin.ignore( numeric_limits<streamsize>::max(), '\n' );

      To save me explaining that, it was last discussed at length just a few days ago here: https://sourceforge.net/forum/forum.php?thread_id=2066529&forum_id=48211

      Clifford

       
    • Will P

      Will P - 2008-06-18

      thanks for the help, i didn't realize the answer was in that other topic sorry.

       
      • cpns

        cpns - 2008-06-18

        Not at all; there was no way for you to know what to look for unless you knew what the problem was, and then you probably wouldn't have had a problem!

        However a whole bunch of frequently asked C++ questions are available at: http://www.parashift.com/c++-faq-lite/

         
    • Will P

      Will P - 2008-06-18

      oh boy...i was finally able to try it out and i still get the same problem =/. this is my updated code with no errors returned:

      include <iostream>

      using namespace std;

      int main ()
      {
      int x;
      char answer = 'y';

      while (answer == 'y'){
      cout&lt;&lt;&quot;Enter a number: &quot;;
      cin&gt;&gt; x;
      cin.ignore( numeric_limits&lt;streamsize&gt;::max(), '\n' );
      
      cout&lt;&lt;&quot;You entered: &quot;&lt;&lt; x &lt;&lt; endl;
      cout&lt;&lt;&quot;Would you like to try again?(y/n): &quot;;
      cin&gt;&gt; answer;
      cin.ignore( numeric_limits&lt;streamsize&gt;::max(), '\n' );
      
      if (answer != 'y'){
      break;
      }
      
      if (answer == 'y')
      continue;
      }
      
      cout&lt;&lt;&quot;Ok, goodbye!&quot;&lt;&lt; endl;
      
      system(&quot;PAUSE&quot;);
      return 0;
      

      }

      looks like i'm really stuck now heh..

       
    • Will P

      Will P - 2008-06-20

      oh and i'd also like to add this to my last post. when i enter a letter for x in the program it prints out as the number 2. is there anyway i can make it so the program only lets the user input an integer otherwise they get some custom error message?

       
    • Will P

      Will P - 2008-06-20

      thanks a lot AGAIN lol, it works perfectly now. the books i read went past loops without explaining anything like what you told me. i could do their examples easily but i couldn't make my own working program the way i wanted it. i'll definitely read the documentation you linked me to. =P

       
      • cpns

        cpns - 2008-06-21

        Note that the site I linked has other useful content, including a tutorial.

        Expecting a user to accurately enter the required data type is unrealistic, but all that error checking and stream error clearing can get rather tedious, repetitive and hard to maintain. The design can be cleaned up by creating input functions for the necessary types that contain their own error checking and then call the function. When you have a program with a lot of input, you will see the benefits of this approach.

        void getInput( const char* prompt, int& num )
        {
        bool valid = false ;
        while( !valid )
        {
        cout << prompt ;
        cin >> num ;
        if( !cin.good() )
        {
        cout << "Try again." << endl ;
        cin.clear() ;
        }
        else
        {
        valid = true ;
        }
        }
        }

        void getInput( const char* prompt, char& ch )
        {
        cin >> answer;
        cin.ignore( numeric_limits<streamsize>::max(), '\n' );
        }

        The your while loop simply becomes:

        while (answer == 'y')
        {
        getInput( "Enter a number: ", x ) ;

        cout<<"You entered: "<< x << endl;

        getInput( "Would you like to try again?(y/n): ", answer ) ;

        }

         
    • Will P

      Will P - 2008-06-21

      ah thanks man, very helpful

       
      • cpns

        cpns - 2008-06-22

        Oops, actually less than helpful... I reintroduced teh error we originally fixed!

        void getInput( const char* prompt, int& num )
        {
        bool valid = false ;
        while( !valid )
        {
        cout << prompt ;
        cin >> num ;
        if( !cin.good() )
        {
        cout << "Try again." << endl ;
        cin.clear() ;
        cin.ignore( numeric_limits<streamsize>::max(), '\n' );
        }
        else
        {
        valid = true ;
        cin.ignore( numeric_limits<streamsize>::max(), '\n' );
        }
        }
        }

        void getInput( const char* prompt, char& ch )
        {
        cin >> answer;
        cin.ignore( numeric_limits<streamsize>::max(), '\n' );
        }

         
    • Will P

      Will P - 2008-06-21

      oh and btw, i know it's definitely unrealistic for you to expect people to input what you want them to, i just wanted a way to prevent them from doing it with some kind of error message instead of that nasty infinite loop lol.

       

Log in to post a comment.