Another way to write (numeric_limits<streamsize>::max(), '\n');?

Hello. I'm writing a program currently and when the user is going to input an integer i need to make sure the user enters an integer. I ran acroess a few numeric limits. Is there another way to write this without using the limits?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <cstdlib>
#include <limits>

using namespace std;

int main()
{
    bool fail;
    int num1;
    do
    {
        cout << "Enter and integer: ";
        cin >> num1;
        fail = cin.fail();
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');

    }while(fail == true);
    return 0;
}
Last edited on
You can use any number. It should work the same as long as it's not less than the length of the inputted line.
Last edited on
What do you mean any number? I'm really confused about the numeric_limits thing
Perhaps don't think about the limits for the time being. Instead focus on what happens here:
 
    cin >> num1;

The user is supposed to enter an integer. Let's say for example they type "y" and then press the enter key.

The input buffer will contain the two characters "y\n".
In that case, the buffer could be cleared by
1
2
    cin.clear();
    cin.ignore(2, '\n');

But what if the user typed
"     y     \n"

that is, five spaces, a 'y', another five spaces and enter.
The leading spaces will be removed, input will stop at the 'y' because it is not an integer, so the buffer now contains seven characters from the 'y', to the '\n'.
In that case the buffer could be cleared by
1
2
    cin.clear();
    cin.ignore(7, '\n');

But we actually don't know what the user typed, so instead use some reasonably large number such as
cin.ignore(100, '\n'); or cin.ignore(1000, '\n');.
In practice those should be adequate.

The version with the value numeric_limits<streamsize>::max() is simply meant to cover all possibilities, it will ignore an unlimited amount of characters - or until the newline character is found.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template <typename T>
bool input_number(std::istream &in, T &dst){
    std::string line;
    std::getline(in, line);
    if (!in)
        return false;
    std::stringstream stream(line);
    return !!(stream >> dst))
}

int main(){
    int num1;
    do{
        std::cout << "Enter and integer: ";
    }while (!input_number(std::cin, num1));
    return 0;
}
Last edited on
Thank you very much chevril for the information it's very helpful. And thank you too helios for showing me another way to write it.
I was making a few modifications and now for some reason it's letting stuff like 1e1e1 go through. I'm thinking is there a way to put something like if there are more inputs after 1 that are not numbers it's rejected?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <limits>
using namespace std;

int main()
{
    int array_numbers[10];
    int current_used_numbers=5;
    int active_number=1;
    bool bfail;
    int num1;

    for(int i = 0; i < current_used_numbers; i++)
    {
        array_numbers[i] = i+1;
        if(i == active_number)
            cout << '[' << array_numbers[i] << ']' << ' ';
        else
        cout << array_numbers[i] << ' ';
    }

    do
    {
        cout << "\nEnter and integer: ";
        cin >> num1;
        bfail = cin.fail();
        cin.clear();

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

    }while(bfail == true);

    current_used_numbers++;
    for(int i = current_used_numbers; i != 0 ; i--)
    {
        if(i == active_number)
            array_numbers[i] = num1;
        else
        array_numbers[i] = array_numbers[i-1];
    }
    for(int i = 0; i < current_used_numbers; i++)
    {
        if(i == active_number)
            cout << '[' << array_numbers[i] << ']' << ' ';
        else
        cout << array_numbers[i] << ' ';
    }
    return 0;
}
Last edited on
That does work but the thing is I'm trying to keep this program into things i know and i don't know <sstream>. Plus when i enter it still goes through o.o
 
"1          1"
Last edited on
"1 1"
It occurred to me that the (old) example code which I posted, could perhaps use getline() instead of cin >> input;.

I'm trying to keep this program into things i know

Sometimes there is a need to do things which will satisfy whoever is teaching or checking your work. But still, stringstream is a very useful thing to learn about, even if you are not permitted to use it 'officially'. It just allows a string to be used as a stream the same as cin, cout or like a file.



Ah alright and thank you very much for the information. And that's true i could always tell me professor what the i know about the lirbrary and how it will affect my program.
> stuff like 1e1e1 go through.
> when i enter it still goes through o.o "1 1"
trim the whitespace of the string, then check that you've reached the end
I don't like your second case, would prefer that to be valid input. It's a lot more convenient to input several numbers in a line.
Sigh I don't understand this anymore. I think i will just try to convert it into a string and get everything in by char. And then i check everything the user enter if it ends up putting something that is not an int then i'll just deny it and start the loop over again.
here you are http://www.cplusplus.com/forum/beginner/170685/#msg851160
to trim the whitespace at the end you may use ss >> n >> ws;
> I think i will just try to convert it into a string and get everything in by char.
> And then i check everything the user enter if it ends up putting something that is not an int
> then i'll just deny it and start the loop over again.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
#include <iomanip>
#include <sstream>

int get_int_from_stdin( std::string prompt = {}, bool repeat = false ) // noisy, non-throwing version
{
    std::cout << prompt ;

    std::string line ;
    if( std::getline( std::cin, line ) )
    {
        try
        {
            std::size_t pos ;
            const int number = std::stoi( line, std::addressof(pos) ) ;

            const auto trailing_spaces = [&] { return std::all_of( line.begin()+pos, line.end(),
                                                                   [] ( char c ) { return std::isspace(c) ; } ) ; };
            if( pos == line.size() || trailing_spaces() ) return number ;

            std::cout << std::quoted(line) << " *** error: invalid trailing character(s) "
                      << std::quoted( line.substr(pos) ) << '\n' ;
        }
        catch( const std::invalid_argument& ) { std::cout << std::quoted(line) << " *** error:  not an integer\n" ; }
        catch( const std::out_of_range& ) { std::cout << std::quoted(line) << " *** error: not within the range of int\n" ; }
    }

    else if(repeat)
    {
        std::cout << "*** error: unable to recover from eof on stdin. returning zero.\n\n" ;
        return 0 ;
    }

    else
    {
        std::cout << "unexpected eof on stdin. trying to recover\n" ;
        std::cin.clear() ;
        return get_int_from_stdin( prompt, true ) ;
    }

    return get_int_from_stdin(prompt) ;
}

http://coliru.stacked-crooked.com/a/bac12216ad4b8d95
http://rextester.com/XEDB66063
OP: as you mentioned previously, if you can indeed swing stringstream by ur prof, the following is a small program that checks whitespace, trailing and leading non-int

characters and blank input. Similar to JLBorges' it also accepts the initial input as a string which is perhaps the most all-encompassing C++ datatype:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <string>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    bool fQuit = false;
    while(!fQuit)
    {
        cout << "Enter number: ";
        string input;
        getline(cin, input);
        stringstream convert(input);
        int n;
        if(!(convert >> n) || !convert.eof() || input.find(string(" ")) != string::npos)
        {
            cout << "Incorrect input, try again \n";
        }
        else
        {
            fQuit = true;
            break;
        }
    }
}

Topic archived. No new replies allowed.