input tests

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

39 Replies - 1162 Views - Last Post: 05 May 2013 - 09:26 PM Rate Topic: -----

#31 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3169
  • View blog
  • Posts: 9,595
  • Joined: 05-May 12

Re: input tests

Posted 05 May 2013 - 05:52 PM

It's been a long day and I'm tired, but doesn't this check incorrectly count the leading '+' or '-' as digit and therefore return a false negative?
55    if( static_cast< int >( entry.size() )  >
56                     std::numeric_limits< int >::digits )



And isn't this missing an underflow check?
67    if( ins >> temp )
68    {
69        // Bigger than an int.
70        if( temp  >  std::numeric_limits< int >::max() )
71        {
72            errMsg += "Overflow Error!  ";
73            return false;
74        }
75    }


This post has been edited by Skydiver: 05 May 2013 - 05:55 PM

Was This Post Helpful? 1
  • +
  • -

#32 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 275
  • View blog
  • Posts: 1,764
  • Joined: 20-September 08

Re: input tests

Posted 05 May 2013 - 06:27 PM

View PostSkydiver, on 05 May 2013 - 08:52 PM, said:

It's been a long day and I'm tired, but doesn't this check incorrectly count the leading '+' or '-' as digit and therefore return a false negative?
55    if( static_cast< int >( entry.size() )  >
56                     std::numeric_limits< int >::digits )



And isn't this missing an underflow check?
67    if( ins >> temp )
68    {
69        // Bigger than an int.
70        if( temp  >  std::numeric_limits< int >::max() )
71        {
72            errMsg += "Overflow Error!  ";
73            return false;
74        }
75    }



Thanks ... You are correct ... needs fixing up :)

Please see (latest) edit above ...

This post has been edited by David W: 05 May 2013 - 06:50 PM

Was This Post Helpful? 1
  • +
  • -

#33 jimblumberg  Icon User is offline

  • member icon


Reputation: 3845
  • View blog
  • Posts: 11,751
  • Joined: 25-December 09

Re: input tests

Posted 05 May 2013 - 06:43 PM

Quote

It's been a long day and I'm tired, but doesn't this check incorrectly count the leading '+' or '-' as digit and therefore return a false negative?

Yes, I left out several cases that can cause the validation to fail, some purposely, some accidentally. But this check is definitely wrong, digits returns the number of bits, not the number of characters that can be held. On my system it returns 31, so this section is totally wrong.

The underflow condition was left out purposely.

Just a note about . The snippet below the cout << flush is not actually needed, unless you have altered the default behavior of cin/cout. The cout buffer is automatically flushed prior to the input.
       std::cout << count << ". Please enter a number (0 to exit) : ";
        std::cout << std::flush;

        std::string entry, err;
        getline(std::cin, entry);


Again David is correct about missing multiple sign bits, but I believe the following code is not necessarily correct:
if( idx != std::string::npos )
{
...
} 
else
        if( entry.size() < 2 )
        {
            errMsg += "A joker ...eh!  NO digits follow the sign.  ";
            return false; // not at front
        }

The sign bits are not mandatory, they may not be present at all.

If you have a C++11 compiler it gets a little easier to test the range.
   try
   {
      number = stoi(entry);
   }
   catch (const std::out_of_range& oor) {
      std::cerr << "Out of Range error: " << oor.what() << '\n';
      return(false);
   }



You'll still need to check for duplicate and misplaced signs if they are present.

Are we having fun yet?


Jim

This post has been edited by jimblumberg: 05 May 2013 - 06:45 PM

Was This Post Helpful? 2
  • +
  • -

#34 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 275
  • View blog
  • Posts: 1,764
  • Joined: 20-September 08

Re: input tests

Posted 05 May 2013 - 06:49 PM

Great fun, isn't it ... eh :)

Please see 'underflow check fix' (thank you Skydiver)

and

'number of digits check fix' (thank you Jim)

added to edited code above

This post has been edited by David W: 05 May 2013 - 07:05 PM

Was This Post Helpful? 0
  • +
  • -

#35 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3169
  • View blog
  • Posts: 9,595
  • Joined: 05-May 12

Re: input tests

Posted 05 May 2013 - 07:32 PM

And above you see the results of people who are the masters at their craft while I'm just a dilettante.
Was This Post Helpful? 0
  • +
  • -

#36 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 275
  • View blog
  • Posts: 1,764
  • Joined: 20-September 08

Re: input tests

Posted 05 May 2013 - 07:42 PM

View PostSkydiver, on 05 May 2013 - 10:32 PM, said:

And above you see the results of people who are the masters at their craft while I'm just a dilettante.


No way Hose ... u's ... (you and Jim) ... u the pro ... I'm just a (sometime too zealous) beginner :)

This post has been edited by David W: 05 May 2013 - 07:42 PM

Was This Post Helpful? 0
  • +
  • -

#37 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3169
  • View blog
  • Posts: 9,595
  • Joined: 05-May 12

Re: input tests

Posted 05 May 2013 - 08:34 PM

LOL! This is going to drive David W to drink:
#include <iostream>
#include <sstream>
#include <limits>

using namespace std;

int main()
{
    // create string with 130 characters
    string s(128, '0');
    s += "12";
    cout << s << endl;

    // parse the input
    stringstream inputStream(s);
    int n;
    inputStream >> n;

    // show what was parsed.
    // output: 12
    cout << n << endl;

    return 0;
}



Notice that the string with the 128 leading zeros followed by the characters '1' and '2' was correctly parsed by the stringstream's extractor operator, but the validate() function would have complained that it was too long to be a valid integer.
Was This Post Helpful? 2
  • +
  • -

#38 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 275
  • View blog
  • Posts: 1,764
  • Joined: 20-September 08

Re: input tests

Posted 05 May 2013 - 09:19 PM

Yes ...

I'm thinking that cin skips over all leading ws char's ...

and then leaves any non int valid char's and all trailing ws char's for a next read ...

but here ...

we only accept exact strings, (i.e. no leading or trailing ws)

This post has been edited by David W: 05 May 2013 - 09:21 PM

Was This Post Helpful? 0
  • +
  • -

#39 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3169
  • View blog
  • Posts: 9,595
  • Joined: 05-May 12

Re: input tests

Posted 05 May 2013 - 09:23 PM

Run the program, the '0' are not whitespace.
Was This Post Helpful? 1
  • +
  • -

#40 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 275
  • View blog
  • Posts: 1,764
  • Joined: 20-September 08

Re: input tests

Posted 05 May 2013 - 09:26 PM

View PostSkydiver, on 06 May 2013 - 12:23 AM, said:

Run the program, the '0' are not whitespace.


Yes ... sorry ... answered too quickly ...

However, still here, we only accept a certain pre-fixed entry field width

It may be better to reject also, any entry that has leading zeros :)


Back to C ... as the OP was using C ...

take a look:

#define BIG_BUF_LEN 1024

/* presumming ? negative numbers are stored in memory using 2's complement ? */
#define MIN_INT  ( 1 << ( sizeof( int ) * 8 - 1 ) )
#define MAX_INT -( MIN_INT + 1 )

#define NUM_DIG_INT ( (int) log10( MAX_INT ) + 1 )


char* fixFgets( char* str )
{
    char* p = strchr( str, '\n' );
    if( p )
        *p = 0; /* strip off '\n' char if present */
    else
        while( getchar() != '\n' ); /* flush stdin to end of line */
    return str;
}

/* since using 'static' buf inside, memory persists ... so can return address */
char* getString( const char* msg, unsigned max_len )
{
    static char buf[BIG_BUF_LEN];
    for( ; ; )
    {
        fputs( msg, stdout ); fflush( stdout );
        fgets( buf, BIG_BUF_LEN, stdin );

        fixFgets( buf );

        if( buf[0] && strlen( buf ) <= max_len ) break;
        else if( !buf[0] ) printf( "\nBlank line NOT valid here ... \n" );
        else printf( "\nMax len of %u char's was exceeded ... \n", max_len );
    }
    return buf;
}


/* simple ... but accepts and returns input like 3.3 ... as (int) 3 ... */
int getValidInt( const char* prompt )
{
    for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
    {
        int numGood, testInt;
        fputs( prompt, stdout ); fflush( stdout );
        numGood = fscanf( stdin, "%d", &testInt );
        while( getchar() != '\n' ); /* 'flush' stdin ... as we go ... */
        if( numGood == 1 ) return testInt;
        /*else ...*/
        puts( "Invalid input! Integers only please ..." );
    }
}

/* accepts only positive (i.e. >= 0) valid int range of values ... */
int getValidPosInt( const char* prompt, int high )
{
    for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
    {
        char* tmp = getString( prompt, NUM_DIG_INT );
        int i = strlen( tmp );
        int good = 1;
        while( --i >= 0 && good )
        {
            if( !isdigit( tmp[i] ) ) good = 0;
        }

        if( good )
        {
            int t = atoi( tmp );
            if( t >= 0 && t <= high ) /* will 'under flow' i.e. be negative
                                         if t too big */
                return t;
        }
        /*else ...*/
        printf( "\nInvalid input! Integers please, only in range %d..%d\n",
                0, high );
    }
}

/*  returns a valid int in range (MIN_INT+1)..MAX_INT  */
int getValidInt2( const char* prompt, int low, int high )
{
    for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
    {
        int good = 1, i, sign = 1;
        char* tmp = getString( prompt, NUM_DIG_INT+1 ); /* leave room for + - */

        if( tmp[0] == '+' ) ++tmp;
        else if( tmp[0] == '-') { ++tmp; sign = -1; }


        i = strlen( tmp );
        while( --i >= 0 && good )
        {
            if( !isdigit( tmp[i] ) ) good = 0;
        }

        if( good )
        {
            int t = atoi( tmp );
            if( t >= 0 && t <= high )
                if( low <= sign*t )
                    return sign*t;
        }
        /*else ...*/
        printf( "\nInvalid input! Integers please, only in range %d..%d\n",
                low, high );
    }
}



This post has been edited by David W: 05 May 2013 - 09:39 PM

Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3