0

So I have a project for school that requires me to wait for the user to input Ctrl + Z to end a loop. The teacher said the best way to do this is to check for cin >> x and if this is true than they haven't entered in Ctrl + Z yet. Well after a bit of testing and going back and forth I couldn't figure out what the problem was, so I made a super simple version of the code to see if I could fix it. Nothing really changed at all. Anyway here is the simple code:

#include "Proj_02.h";

vector<int> dog;
string entry = "";
int value = 0;

void main()
{
    Menu();
}

void Menu()
{
    do
    {
        //Ask the user to enter a number
        cout << "Enter a number: ";
        //Save the number to a vector
        do
        {
            cout << "k";
            getline(cin, entry);
            value = atoi(entry.c_str());
        }while(value == 0);

        while (cin >> value)
        {
            cout << "L";
            dog.push_back(value);
        }

    //when the user presses Ctrl + Z stop asking
    }while(cin >> entry);

    //Display all of the numbers
    for(int i = 0;i < dog.size();i++)
    {
        cout << dog.at(i) << endl;
    }

    system("PAUSE");
}

So what happens when this is run is the code waits for me to enter 2 more values before even doing anything after any entry is made at all. My guess is it has something to do with the while cin >> entry causing some sort of buffer interference, but I don't really have any solid ideas on how to fix this. If anyone could help that would be amazing.

LihO
  • 41,190
  • 11
  • 99
  • 167

5 Answers5

1

When working with streams please test the state before using the result.

Hence:

while(std::cin >> value) {
    ...
}

if(std::getline(cin, entry)) {
    ...
}
1

If you are taking input from terminal then you have no other option than Ctrl+Z because this signals the end of file to terminal. But if you are using a file to give input from terminal then use scanf("%d",&entry)!=EOF this will auto detect end of file and terminate the program. PS: if you are going to use scanf then first include the cstdio library.

  • Modern C++ has but-rare use of `scanf()` as it is, but this case especially *not* since it is based on an assignment specifically dealing with testing iostream states. – WhozCraig Sep 07 '13 at 08:51
1

"I couldn't figure out what the problem was, so I made a super simple version of the code" - This was very reasonable decision and right thing to do, however the code you made isn't simple at all:

do {
    cout << "Enter a number: ";
    do {
        cout << "k";
        getline(cin, entry);
        value = atoi(entry.c_str());
    } while(value == 0);

    while (cin >> value) {
        cout << "L";
        dog.push_back(value);
    }
} while(cin >> entry);

If you wanted to test how while (cin >> value) works in run-time, you should start with this:

while (cin >> value) {
    dog.push_back(value);
}

In case you want more complex parsing and thus it makes sense to read every line into std::string object before the actual retrieving of numbers, it might look like this:

std::string line;
while (std::getline(std::cin, line)) {
    if (line.empty())
        ...
    ...
}
LihO
  • 41,190
  • 11
  • 99
  • 167
0

cin >> value is not just a test for EOF, it reads data from input buffer. So you should not simply discard the values after you read them.

Now your code enters a line (via getline), discards its data and enters a number (via cin >> value), and then it wants another line and discards it also (cin >> entry). That's why you have to enter multiple numbers while it processes only one of them.

nullptr
  • 11,008
  • 1
  • 23
  • 18
0

consider the following simple example. You could use ctrl-d on linux or ctrl-z on windows to end the cin and have the code continue or just hit q in this case as well.

#include <iostream>
#include <string>
#include <vector>

int main()
{
  std::vector<int> v;
  std::string buffer;
  while ((std::cin >> buffer) && (buffer != "q"))
    v.emplace_back(atoi(buffer.c_str()));

  for ( auto& i : v )
  {
    std::cout << i << " ";
  }
  std::cout << std::endl;
}
output:

12
13
177
205
q
12 13 177 205
bjackfly
  • 3,236
  • 2
  • 25
  • 38