How do YOU deal with a failed input stream?

Hey guys, Just a quick question. How do you, personally, deal with a failed input stream and type checking input?

I use:

1
2
3
4
5
6
7
8
9
cout << "\n\nEnter a menu option: ";

while(!(cin >> menuGameMode))
{
   cin.clear();
   while (cin.get() != '\n')
      continue;
   cout << "Enter a menu option: ";
}


Is this the "Best" way to do it?

EDIT: We're assuming input is expecting an int.
Last edited on
Instead of doing this:
1
2
   while (cin.get() != '\n')
      continue;


You can do this:

 
cin.ignore( numeric_limits<streamsize>::max() );


Though to answer your actual question... personally... I hardly ever use iostream for i/o so I don't have a technique that I'd call familiar.
type checking is easy. here is a quick one:
1
2
3
4
5
6
7
8
9
10
#include <sstream>

template<typename T>
void Sanitize(std::string Buffer, T &Holder) {
    std::istringstream Stream(Buffer);

    if(Stream >> Holder) {
        return;
    }
}
http://www.cplusplus.com/forum/beginner/108849/#msg592118

Disch wrote:
You can do this:

cin.ignore( numeric_limits<streamsize>::max() );


Note that this will ignore all characters until eof is encountered. The canonical way to clear the rest of the current line is:

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


eXception handling. Easy to read and cleaner
Gkneeus wrote:
eXception handling. Easy to read and cleaner


It may be cleaner and easier to read if you want to abort the operation on any failure, otherwise not really.

Take the following, for example:

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// http://ideone.com/DVZDeD
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <limits>

void do_without_exceptions()
{
    std::istringstream in("3 4\n5 6\nbad line\n10 39\n100 1001\nbad line");

    while (in.good())
    {
        int a, b;
        while (in >> a >> b)
            std::cout << a << " + " << b << " = " << a + b << '\n';

        if (!in)
        {
            in.clear();
            in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
    }
}

void do_with_exceptions()
{
    auto exception_bits = std::istringstream::badbit |
        std::istringstream::failbit |
        std::istringstream::eofbit;

    std::istringstream in("3 4\n5 6\nbad line\n10 39\n100 1001\nbad line");
    in.exceptions(exception_bits);

    while (in.good())
    {
        try {
            int a, b;
            in >> a >> b;
            std::cout << a << " + " << b << " = " << a + b << '\n';
        }

        catch (std::istream::failure& ex)
        {
            if (in.fail())
            {
                try {
                    in.clear();
                    in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
                }

                catch (std::istream::failure&)
                {
                }
            }
        }
    }
}


int main(int argc, char* argv[])
{
    do_without_exceptions();
    do_with_exceptions();
}


How does using exceptions add to the readability or cleanliness of the code here?
To me this looks much easier to read without the nested while loops. Also, Not only do I think it is easier to read but it is great practice when you are working with other programmers. Suppose another programmer is using your code and something goes wrong, throwing an error can put him in a position to recover and better handle it because he might not know the implementation of your code and it will give him some information as to what is going on.

I am not a professional yet and I have little experience so you might be correct but that is just my two cents.


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

int main()
{

	int a, b;
	int more  = true;

	while(more)
	{
		try
		{
			withException();

			more = false;
		}
		catch(std::logic_error& e)
		{
			std::cout << e.what() << std::endl;
			std::cin.clear();
			std::cin.ignore();
		}
		
	}


	

	system("Pause");
	return 0;
}

void withException() throw(std::logic_error)
{
	int a, b;

	std::cin >> a >> b;


	if(std::cin.fail())
	throw std::logic_error("Input error blah blah");

	std::cout << a << " + " << b << " = " << a + b << '\n';


To me this looks much easier to read without the nested while loops.

My code reads a series of number pairs from a stream, skipping lines with an unexpected format. Yours attempts to read two numbers from the console. They aren't really comparable.


But, here's the equivalent of yours without exceptions:

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

void do_without_exception();

int main()
{
    do_without_exception();
}

void do_without_exception()
{
    int a, b;
    while (!(std::cin >> a >> b))
    {
        std::cout << "Invalid input.\n";
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }

    std::cout << a << " + " << b << " = " << a + b << '\n';
}


Which do you find more readable?

Last edited on
@Cire

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
while (in.good())
    {
        try {
            int a, b;
            in >> a >> b;
            std::cout << a << " + " << b << " = " << a + b << '\n';
        }

        catch (std::istream::failure& ex)
        {
            if (in.fail())
            {
                try {
                    in.clear();
                    in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
                }

                catch (std::istream::failure&)
                {
                }
            }
        }
    }
}


Why did you do two try...catch statements there? You catch potential istream failure, then try to clear the input stream and then catch another potential istream failure.

Just wondering if that is a standard method of catching bad input through exceptions or if it was a typo or something else entirely.

:)
Why did you do two try...catch statements there?

Because ignore may throw when eof is encountered with the exceptions I enabled, and I didn't want that exception to propagate.
Registered users can post here. Sign in or register to post.