6 Replies - 1159 Views - Last Post: 04 June 2018 - 01:24 PM

#1 moskitos80   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 4
  • Joined: 04-June 18

istream input loop

Posted 04 June 2018 - 10:55 AM

Hi all. If you enter the wrong data in the code, for example, two words through a space, then the input is looped. The loop works and is not blocked where the "cin >> id >> name" instruction. This bug occurs on Linux but on Windows everything is correct. Tell me please what's the matter?

#include<iostream>
#include<string>

using namespace std;

int main()
{
	int id;
	string name;

	cout << "Please fill data: (int)id (string)name \n"
	        "(press Ctrl+D to complete):";

	while (true) {
		if (cin >> id >> name) {
			cout << "Entered: " << id << ":" << name << "\n";
			continue;
		}

        // Ctrl+D
		if (cin.eof()) { break; } 

        // incorrect data format
		if (cin.fail()) {
			cerr << "Wrong data try again.\n";
			cin.clear();
			cin.ignore(cin.rdbuf()->in_avail());
		}

        // trace the stream state
		cerr << "in_avail" << cin.rdbuf()->in_avail() << "\n"; // 0
		cerr << "eof" << bool(cin.eof()) << "\n";   // 0
		cerr << "fail" << bool(cin.fail()) << "\n"; // 0
		cerr << "bad" << bool(cin.bad()) << "\n";   // 0
		cerr << "good" << bool(cin.good()) << "\n";   // 1
	}

	return 0;
}



Is This A Good Question/Topic? 0
  • +

Replies To: istream input loop

#2 modi123_1   User is online

  • Suitor #2
  • member icon



Reputation: 15356
  • View blog
  • Posts: 61,556
  • Joined: 12-June 08

Re: istream input loop

Posted 04 June 2018 - 10:57 AM

15        if (cin >> id >> name) {

What do you think this evaluates to?
Was This Post Helpful? 0
  • +
  • -

#3 moskitos80   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 4
  • Joined: 04-June 18

Re: istream input loop

Posted 04 June 2018 - 11:17 AM

View Postmodi123_1, on 04 June 2018 - 10:57 AM, said:

15        if (cin >> id >> name) {

What do you think this evaluates to?

In this line i retrieve user input: two value separated by space. The first value must be an integer and second one must be a string. If I enter two strings purposely this cause the stream error and the loop work infinitly. But this behavior appears only in gcc, in VC compiler all ok.

View Postmodi123_1, on 04 June 2018 - 10:57 AM, said:

15        if (cin >> id >> name) {

What do you think this evaluates to?

I think this evaluate the input stream state after user input.
Was This Post Helpful? 1
  • +
  • -

#4 modi123_1   User is online

  • Suitor #2
  • member icon



Reputation: 15356
  • View blog
  • Posts: 61,556
  • Joined: 12-June 08

Re: istream input loop

Posted 04 June 2018 - 11:32 AM

Hmm. Perhaps if you are getting an infinite loop due to that line you may want to reconsider _NOT_ using the CIN inside an IF condition.
Was This Post Helpful? 0
  • +
  • -

#5 moskitos80   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 4
  • Joined: 04-June 18

Re: istream input loop

Posted 04 June 2018 - 12:12 PM

View Postmodi123_1, on 04 June 2018 - 11:32 AM, said:

Hmm. Perhaps if you are getting an infinite loop due to that line you may want to reconsider _NOT_ using the CIN inside an IF condition.


Solution:

#include<iostream>
#include<string>
#include<limits>

using namespace std;

int main()
{
	int id;
	string name;

	cout << "Please fill data: (int)id (string)name \n"
		"(press Ctrl+D to complete):";

	while (true) {
		if (cin >> id >> name) {
			cout << "Entered: " << id << ":" << name << "\n";
			continue;
		}

		// Ctrl+D
		if (cin.eof()) { break; } 

		// incorrect data format
		if (cin.fail()) {
			cerr << "Wrong data try again.\n";
			cin.clear();
			cin.ignore(numeric_limits<streamsize>::max(), '\n'); // IT WORK!!
		}

		// trace the stream state
		cerr << "in_avail" << cin.rdbuf()->in_avail() << "\n"; // 0
		cerr << "eof" << bool(cin.eof()) << "\n";   // 0
		cerr << "fail" << bool(cin.fail()) << "\n"; // 0
		cerr << "bad" << bool(cin.bad()) << "\n";   // 0
		cerr << "good" << bool(cin.good()) << "\n";   // 1
	}

	return 0;
}



Apparently cin.rdbuf()->in_avail() returns not the full number of characters in the buffer, at least not in all implementations. Therefore, it is better to use such a construction:

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


Was This Post Helpful? 1
  • +
  • -

#6 sepp2k   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2754
  • View blog
  • Posts: 4,414
  • Joined: 21-June 11

Re: istream input loop

Posted 04 June 2018 - 01:13 PM

View Postmodi123_1, on 04 June 2018 - 07:57 PM, said:

15        if (cin >> id >> name) {

What do you think this evaluates to?


I know you didn't ask me, but cin >> id >> name evaluates to cin and then the fact that it's used inside an if causes an implicit conversion that returns 0 if cin is in a fail-state and non-zero otherwise. So in other words the if checks that the input operation finished successfully.

View Postmodi123_1, on 04 June 2018 - 08:32 PM, said:

Perhaps if you are getting an infinite loop due to that line you may want to reconsider _NOT_ using the CIN inside an IF condition.


Why not? And why would you assume that the infinite loop was due to that line?
Was This Post Helpful? 0
  • +
  • -

#7 modi123_1   User is online

  • Suitor #2
  • member icon



Reputation: 15356
  • View blog
  • Posts: 61,556
  • Joined: 12-June 08

Re: istream input loop

Posted 04 June 2018 - 01:24 PM

I was getting tripped up on the flow. Whoopsadaisy.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1