简体   繁体   中英

C++ Primer 1.4.4 — Importance of EOF and how to write in a code that will end without EOF?

Referring to two questions:

  1. Incorrect output from C++ Primer 1.4.4
  2. Confused by control flow execution in C++ Primer example

My question is answered in both of those posts, but I want to delve further.

First, I know this is only the beginning, but let's say I make a fully functional program that runs in a designed window. By that level, will I already know how to implement a EOF? I can't expect someone running my program to know that they need to hit Control-Z .

Is there a way to implement a specific code that functions so that it does not need me to type in an unrecognized value?

Also one guy in those questions somewhat answered the importance of EOF, but how come the program doesn't even post the final cnt - 1 ?

Let's say I do the numbers 10 10 10 20 20 20. Without EOF, this will only show the "10 repeats 3 times." How come the program doesn't at least type in the count "10 repeats 3 times and 20 repeats 2 times" minus the final one with white space?

lets say I make a fully functional program that runs in a designed window. By that level, will I already know how to implement a eof? I can't expect someone running my program to know that they need to hit ctrl + z.

You could either tell the user explicitly to do a specific action to end input or the design of the window itself could tell the user the information implicitly. For instance, a dialog box could ask the user to enter input and click an OK button when done.

Is there a way to implement a specific code that functions so that it does not need me to type in an unrecognized value?

It seems like you would rather use a newline character to terminate your input. An example of this usage could be std::getline . Instead of writing

while (std::cin >> val)

you could instead use

std::string line;
if (std::getline(std::cin,line))

and assume that your user's input only consists of one line of values. There are plenty of other ways to similarly achieve this task depending on how you want to constrain the user's input.

Let's say I do the numbers 10 10 10 20 20 20. WIthout eof this will only show the "10 repeats 3 times." How come the program doesn't at least type in the count "10 repeats 3 times and 20 repeats 2 times" minus the final one with white space?

Without the eof your program is still executing the while (std::cin >> val) loop since std::cin >> val has not yet received invalid input.

Since the line std::cout << currVal << " occurs " << cnt << " times" << std::endl; occurs after that while loop finishes execution, you don't (yet) see any information about the three 20's in the input.

When you are reading a sequence of inputs you'll need some indication when your down. That could be a sentinel value ("enter 999 to stop reading"; you'd need to detect that while reading), an invalid input ("enter X to stop reading"; when reading an int the value X is illegal and causes the stream to got into failure mode, ie, have std::ios_base::failbit set), or the more conventional "there isn't anything more to read". For a file, the last conditions is straight forward. When reading data from the console you'll either need to teach people how to terminate the input or you'll need to use a different approach.

If you want to intercept any keypressed and react on them directly you may do so, too. You could, eg, use ncurses and control your input via that. You could also set the concole to non-buffering (on POSIX systems using tcgetattr() and tcsetattr() to clear the ICANON flag) and deal directly with all key presses to decide whether you want to continue reading or not.

Although I'm certainly up to doing fancy I/O stuff I normally don't bother: users will understand the "end of input" character and just deal with it. That is, my input normally looks something like this:

while (in >> whatever_needs_to_be_read) { ... }

... or, if the input is genuinely line oriented

for (std::string line; std::getline(in, line); ) { ... }

The function doing this input will then be called with a suitable std::istream which may be std::cin although I have typically some way to also read from a file (in addition to the shell-privided input redirection).

BTW, despite some indications in the questions referenced, "EOF" is not a character being read. It is a character entered, though (normally). ... and it is quite conventional to "know" the end of input character (on POSIX systems a ctrl-D and on Windows a ctrl-Z). You can use other indicators, eg, the "interrupt" (ctrl-C) but that takes more work and doesn't integrate nicely with stream. To use the interrupt chacter you'd need to setup a signal handler for SIGINT and deal with that. One slightly annoying part of doing so is that if you get it wrong you'll need to find a different way to kill the program (eg on POSIX using ctrl-Z to put the process to sleep and kill it via a harsher signal).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM