std::cin >> string and EOF

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

int main() {

	std::string input;
	std::string output;

	int i = 0;
	while (std::cin >> input) {
		output += input + ' ';
		++i;
	}
	std::cout << "\nstd::cin read " << i << " times";
	std::cout << "\nstd::cin read " << output;


	return 0;
}


Here is the output I get:

// this is the input I'm giving:
hello ^Z 
^Z // std::cin does not read this

// program output:
std::cin read 2 times
std::cin read hello [?] // hello followed by a white box character thing
// the loop ran twice, once for hello and again for ^Z


^Z (ctrl+Z) is supposed to be EOF (for windows). I would have expected the loop to only execute one time (for hello). How come it executes twice?

It's as though ^Z is only EOF when it is at the beginning of the line, and some character otherwise. Is that accurate to say? If so, why?

(btw, I'm a beginner)
Last edited on
Hello Grime,

^Z (ctrl+Z) is supposed to be EOF (for windows).
Yes it is.

It's as though ^Z is only EOF when it is at the beginning of the line, and some character otherwise. Is that accurate to say?
Yes and No.

You need to start with the formatted input of std::cin >> input. When you type on the keyboard what you type is put in the "input buffer" until you press "Enter" then it will extract or copy the input buffer into the variable until it finds a white space or new line whichever comes FIRST.

So when you type "Hello ^Z", with a space, only "Hello" is put in the variable "input" and the "^Z" and the "\n" is left in the "input buffer". Theoretically the "^Z" should be extracted from the input buffer on the second pass, but it is not. I am not sure why. It may be because the "^Z" may need to be the only entry before you press "Enter".

Removing the space "Hello^Z" will store the "^Z" in the string, but will not read it as the "eof" that you want.

I do not use the "^Z" very often, but I believe that it has to be its own entry to work properly.

A slight change to your code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>

int main()
{
    std::string input;
    std::string output;

    int i = 0;

    while (std::cout << "Enter something: " && std::cin >> input)
    {
        output += input + ' ';

        ++i;
    }

    std::cout << "\nstd::cin read " << i << " time(s)";

    std::cout << "\nstd::cin read " << output;


    return 0;
}

The biggest concept I want to demonstrate is the use of blank lines to break up the code. This makes it much easier to read.

My IDE uses the {}s differently than you do, but you are free to use whatever style you have learned and are use to. See https://en.wikipedia.org/wiki/Indentation_style#Brace_placement_in_compound_statements for examples.

When you have an input be it formatted, std::cin >> or unformatted, std::getline(), it is a good idea to output a prompt, so the user is not staring a blank screen wondering what to do. By leaving out a "\n" or "endl" in the prompt the input statement will be on the same line as the prompt.

With the above code I get this output:
Enter something: Hello
Enter something: World!
Enter something: ^Z

std::cin read 2 time(s)
std::cin read Hello World!



Andy
Thanks for replying (and the tips), Andy.

Theoretically the "^Z" should be extracted from the input buffer on the second pass, but it is not. I am not sure why

Something is extracted on the second pass. My original output had a white box character (with a question mark inside) thing, which was not displayed in the thread for some reason. I have replaced that with a [?] now.

But whatever is extracted, it's not causing the loop to end. What is it and why so?


It may be because the "^Z" may need to be the only entry before you press "Enter".

It does seem as though ^Z must be the only entry (otherwise the loop doesn't exit when it reads it). Why would that be so?
Last edited on
Topic archived. No new replies allowed.