My KeepWindowOpen() isn't working as expected

I felt that my understanding of C++ wasn't thorough enough, so I decided to read Programming: Principles and Practice Using C++ by Bjarne Stroustrup. Anyway, my KeepWindowOpen() works when the program reaches the end of main(), but not when I have bad input. I've tried std::cin.clear() but that didn't seem to change anything. Any ideas?

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
#include <iostream>

void KeepWindowOpen( );

double ctof( const double c );

int main( )
{
	double c{};
	std::cout << "In Celcius: ";
	if( !(std::cin >> c) ) {
		std::cerr << "ERROR! Invalid input!\n";
		KeepWindowOpen( );
		return -1;
	}
	double f{ ctof( c ) };
	std::cout << c << "*C is " << f << "*F\n";

	KeepWindowOpen( );
}

void KeepWindowOpen( )
{
	std::cout << "\nPress enter to continue . . .\n";
	std::cin.rdbuf( )->sputc( 0 );
	std::cin.get( );
}

// Celcius to Farenheit
double ctof( const double c )
{
	return 1.8 * c + 32;
}


In Celcius: a


edit: Forgot to post my KeepWindowOpen().
Last edited on
If there is a problem extracting from std::cin, the input causing the problem still stays in the stream, and therefore your cin.get() will try and read it again, and fail again.

See the code below, as a quick example of how to skip the dodgy input. There is a whole thread on this at

http://www.cplusplus.com/forum/beginner/1988/

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

inline void KeepWindowOpen();

int main()
{
	//...
	//...

	KeepWindowOpen();
	return (0);
}

inline void KeepWindowOpen()
{
	std::cout << "Press ENTER to continue...";
	std::cin.clear();
	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
I've tried that before, but it always seems to close instantly after having more than one std::cin.

edit: Some code
1
2
3
4
5
6
7
8
	int a, b;
	std::cin >> a;
	//std::cin >> b;

	// window closes instantly, even after 1 std::cin
	std::cout << "Press ENTER to continue...";
	std::cin.clear( );
	std::cin.ignore( std::numeric_limits<std::streamsize>::max( ), '\n' );

1
2
3
4
5
6
7
8
	int a, b;
	std::cin >> a;
	std::cin >> b;

	// window stays open
	std::cout << "\nPress enter to continue . . .\n";
	std::cin.rdbuf( )->sputc( 0 );
	std::cin.get( );
Last edited on
@integralfx, that's interesting. Could you post a MVE?
MVE?
Sorry :-)

Minimum Verifiable Example i.e. code I can compile and run without modification, that exhibits the problem.

I'd like to try and figure out why std::istream::ignore() doesn't work for you. You should do the check after every cin extraction. It may be that there is a '\n' in the stream already from previous failed input. Attempts to extract after this (you used cin.get() for example) should then wait until the input arrives.


To illustrate, consider the 2 programs below. Try running them and use some nonsense input like a string(s), alphabetical character(s) or floating point numbers.

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
#include <iostream>
#include <limits>

using namespace std;

#if 0
int main()
{
	int a, b;
	std::cin >> a;
	cin.clear();
	cin.ignore(numeric_limits<streamsize>::max(), '\n');
	std::cin >> b;
	cin.clear();
	cin.ignore(numeric_limits<streamsize>::max(), '\n');

	std::cout << "\nPress enter to continue . . .\n";
	cin.clear();
	cin.ignore(numeric_limits<streamsize>::max(), '\n');
	std::cin.get( );
}
#endif

#if 1
int main()
{
	int a, b;
	std::cin >> a;
	std::cin.rdbuf( )->sputc( 0 );
	std::cin >> b;
	std::cin.rdbuf( )->sputc( 0 );

	std::cout << "\nPress enter to continue . . .\n";
	std::cin.rdbuf( )->sputc( 0 );
	std::cin.get( );
}
#endif

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
/*
Good/bad input: have to press enter twice at the end
*/
void foo1( )
{
	int a, b;
	std::cin >> a;
	std::cin.clear( );
	std::cin.ignore( std::numeric_limits<std::streamsize>::max( ), '\n' );
	std::cin >> b;
	std::cin.clear( );
	std::cin.ignore( std::numeric_limits<std::streamsize>::max( ), '\n' );

	std::cout << "\nPress enter to continue . . .\n";
	// only have to press enter once, regardless of good/bad input
	//std::cin.clear( );
	//std::cin.ignore( std::numeric_limits<std::streamsize>::max( ), '\n' );
	std::cin.get( );
}

/*
Bad input:		closes after first std::cin
Good input:	works fine, only have to press enter once at the end
*/
void foo2( )
{
	int a, b;
	std::cin >> a;
	//std::cin.rdbuf( )->sputc( 0 );	// doesn't change the end result
	std::cin >> b;
	//std::cin.rdbuf( )->sputc( 0 );

	std::cout << "\nPress enter to continue . . .\n";
	std::cin.rdbuf( )->sputc( 0 );
	std::cin.get( );
}

int main( )
{
	//foo1( );

	foo2( );
}


For foo1, without commenting out lines 16 and 17, I have to press enter twice. Commenting it out, I only have to press enter once.

For foo2, commenting out lines 29 and 31 doesn't change anything.
Last edited on
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
#include <iostream>
#include <limits>
void KeepWindowOpen( );

double ctof( const double c );

int main( )
{
	double c{};
	std::cout << "In Celcius: ";
	if( !(std::cin >> c) )
    {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		std::cerr << "ERROR! Invalid input!\n";
		KeepWindowOpen( );
		return -1;
	}
	double f{ ctof( c ) };
	std::cout << c << "*C is " << f << "*F\n";

	KeepWindowOpen( );
}

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

// Celcius to Farenheit
double ctof( const double c )
{
	return 1.8 * c + 32;
}



Keeping the console window open is not necessary. the console window doesn't close until the user closes it. So any output will be visible. The console window that your ide produces behaves differently than the real console window.
Last edited on
I think the best way is to call
1
2
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

after every reading for std::cin.

it will clear any evil stuff on cin.

This code works well.
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
#include <iostream>
#include <limits>
void KeepWindowOpen();

double ctof(const double c);
using namespace std;
int main()
{
    double c{};
    std::cout << "In Celcius: ";

    if (!(std::cin >> c))
    {
        std::cerr << "ERROR! Invalid input!\n";
        // clear std::cin after calling it
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        KeepWindowOpen();
        return -1;
    }

    // clear std::cin after calling it
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    double f{ ctof(c) };
    std::cout << c << "*C is " << f << "*F\n";
    KeepWindowOpen();
}

void KeepWindowOpen()
{
    std::cout << "\nPress enter to continue . . .\n";
    // make sure std::cin is empty, so no need to call std::cin.rdbuf()->sputc(0);
    //   std::cin.rdbuf()->sputc(0);
    std::cin.get();
}

// Celcius to Farenheit
double ctof(const double c)
{
    return 1.8 * c + 32;
}
Thanks for the feedback, but is there a way I can achieve the same effect as system( "pause" ) with standard C++, without having to do
1
2
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
after every std::cin?
@integralfx There are two issues here, and they are only accidentaly related :)

One problem is to do with reading from cin, and whether you want to keep your console open or not, you should verify the state of the stream, or risk getting invalid input, especially when you're reading from the stream multiple times, you can get some weird results. That's what is happening above.

The other issue is keeping the console open. I assume you're using an IDE, which launches the console, runs the program and then closes the console when the program exits. Most IDE will have an option for keeping the console open after the program exits. I though I should mention that, but I'm aware that's not the question you asked.

system() is a way to run a command from within your program, as though you were typing it in on the shell. It will actually spawn a new process to execute the command. It is highly inefficient, and platform dependent (your platform may not have "Pause" for example).

It is okay to use system() as quick and dirty way of stopping the program from exiting while you're developing it, but I advise against using it in this fashion as a final solution. Let's just say it makes you look back.

Getting to your actual question, consider the fact that system() is a function not a keyword, so someone has written this function and included it in the library. The equivalent might be a function you write yourself that does not use platform-dependent behaviour.

Consider: http://www.cplusplus.com/forum/beginner/1988/#msg7682
Topic archived. No new replies allowed.