Thread: catching non-standard input & returning error

  1. #1
    Registered User
    Join Date
    Apr 2008
    Location
    Australia
    Posts
    55

    catching non-standard input & returning error

    hi,

    Wondering if it's possible to catch non-standard input & then use that for error checking/return ?

    for example;
    Code:
    int input;
    cout<<"Enter input: ";
    cin>>input;
    
    if (input!=int)
    {
      cout<<"Not an int";
    }
    This is (a part of) something I've written, and while it does what I want, I was wondering if there's a more proper/elegant way of handling non-standard input.
    Currently I've used an initialised int using -1 as a means of doing what I want (ie catching non ints).
    Code:
    //myflush1 & 2 added/used to handle non-int/standard input.
    void myflush1 ( std::istream &in )
    {
      in.clear();
    }
    
    void myflush2 ( std::istream &in )
    {
      in.ignore ( numeric_limits<streamsize>::max(), '\n' );
      in.clear();
    }
    //other code
    
    
    
      int iNumoftimetype = 11; //number of time types in saTimetype[], counting from zero.
      int iInitialtimetype=-1, iConverttimetype=-1; //initialised to -1 in order for 0 > exit to work
      double dInitialtimevalue=-1, dConverttimevalue=-1; //used for display & conversion values
      string saTimetype[] = {"Exit Program","millisecond(s)","second(s)","minute(s)","hour(s)","day(s)","week(s)","month(s)"
                                  ,"year(s)","decade(s)","century(ies)","millennium(s)"}; //used for text display
      string saFunctimetype[] = { "INVALID", "MILLISECONDS","SECONDS","MINUTES","HOURS","DAYS","WEEKS","MONTHS"
                                  ,"YEARS","DECADES","CENTURYS","MILLENNIUMS" }; //used for function call
      string sInitialtimetype, sConverttimetype;
      string sFuncinitialtimetype, sFuncconverttimetype, sTime1_2_time2_func;
    
      while (1)
      {
        cout<<"Select base type & conversion type (enter value 1 or 2 or 3 etc)...\n";
            for (int n=0 ;n<=iNumoftimetype;n++ ) //numbers & displays the saTimetype array
            {
              cout<<n<<":"<<saTimetype[n]<<endl;
            }
        cout<<"Enter base type: ";
        myflush1 ( cin>>iInitialtimetype); 
        myflush2 ( cin );
    
          if ((iInitialtimetype>=1)&&(iInitialtimetype<=iNumoftimetype)&&(iInitialtimetype!=0))
          {
            cout<<"Convert to: ";
            myflush1 ( cin>>iConverttimetype);
            myflush2 ( cin );
            
              if (iInitialtimetype == iConverttimetype)
              {
                cout<<"Conversion will be the same\n\n";
                iInitialtimetype=-1;
                iConverttimetype=-1;
                continue;
              }
            if ((iConverttimetype>=1)&&(iConverttimetype<=iNumoftimetype)&&(iConverttimetype!=0))
              //if reach here, exit the loop & moves onto switch.
            break;
            
              if ((iConverttimetype<-1)||(iConverttimetype>iNumoftimetype))
              {
                cout<<"Invalid selection\n\n";
                iConverttimetype=-1;
                continue;
              }
    
    	  //here, if input!=int return error & return control to loop
              if (((iConverttimetype<=-1)||(iConverttimetype>=iNumoftimetype))||(iConverttimetype!=0))
              {
                cout<<"Invalid selection type. Must be a (positive) integer.\n\n";
                continue;
              }
    
              if (iConverttimetype==0)
              {
                cout<<"Program exiting\n";
                cin.get();
                return 0;
              }
          break;
          }
    
          if ((iInitialtimetype<-1)||(iInitialtimetype>iNumoftimetype))
          {
            cout<<"Invalid selection\n\n";
            iInitialtimetype=-1;
            continue;
          }
    
          if (((iInitialtimetype<=-1)||(iInitialtimetype>=iNumoftimetype))||(iInitialtimetype!=0))
          {
            cout<<"Invalid selection type. Must be a (positive) integer.\n\n";
            continue;
          }
    
          if (iInitialtimetype==0)
          {
            cout<<"Program exiting\n";
            cin.get();
            return 0;
          }
      }
    
    //other code
    I thought I had read somewhere that there is a way to do this, but I can't seem to find where that was & I'm starting to think maybe I dreamt it up

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Well, I'm not going to bother with that code beyond a cursory glance.

    You shouldn't arbitrarily clear the stream when an operation fails. (You are clearing the 'eofbit' flag.)

    You should return a reference to the stream object. (You could then use the result of the function to control branching.)

    You should store the result of stream operations--or otherwise use the result. If a stream operation leaves the stream in a good state, the relevant variable was modified--even if it has the same value. (With this implemented you don't need to employee a sentry value.)

    I've updated my example. You should normally use the result of a stream operation to control branching, but here I've cleared everything but the 'eofbit' flag anyway so controlling termination with 'bool std::istream::eof()' is fine. (You can't use the implicit conversion to "boolean convertible type" because it will not loop if the first input is invalid.)

    Soma

    Code:
    #include <iostream>
    #include <limits>
    
    std::istream & maybe_clear
    (
       std::istream & in_f,
       bool & modified_f
    )
    {
       if(!(modified_f = !((in_f.fail()) && (!in_f.eof()))))
       {
          in_f.clear();
          in_f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
       }
       return(in_f);
    }
    
    int main()
    {
       const int min(5);
       const int max(20);
       int i(0);
       for(bool updated(std::cin >> i); !std::cin.eof(); maybe_clear(std::cin >> i, updated))
       {
          if(updated && (min <= i) && (max >= i))
          {
             std::cout << i << '\n';
          }
       }
       return(0);
    }
    Last edited by phantomotap; 02-13-2009 at 10:22 PM. Reason: Clarity. Expansion.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The thing you're missing is the checking of the return value of operator >> to see if the input succeeded.

    Here's a simple method that only checks whether the input is an int or not:
    Code:
    int input;
    cout<<"Enter input: ";
    
    while (!(cin>>input))
    {
      cin.clear();
      cin.ignore(numeric_limits<streamsize>::max(), '\n');
      cout<<"Not an int";
    }
    You can also use the functions in this post to handle almost all of your basic input needs in a more streamlined fashion: http://cboard.cprogramming.com/showp...4&postcount=24

  4. #4
    Registered User
    Join Date
    Apr 2008
    Location
    Australia
    Posts
    55
    Thank you both for the replies. This has greatly helped & is exactly what I was looking for. Still trying to understand many aspects, so thanks .

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Beginner Needs help in Dev-C++
    By Korrupt Lawz in forum C++ Programming
    Replies: 20
    Last Post: 09-28-2010, 01:17 AM
  2. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  3. Why wont my function exit correctly?
    By LightsOut06 in forum C Programming
    Replies: 2
    Last Post: 10-09-2005, 09:23 PM
  4. pointer to array of objects of struct
    By undisputed007 in forum C++ Programming
    Replies: 12
    Last Post: 03-02-2004, 04:49 AM
  5. Linking error
    By DockyD in forum C++ Programming
    Replies: 10
    Last Post: 01-20-2003, 05:27 AM