0
votes

In my Introduction to C++ classes, we were asked to write a function that returns the length of a string using pointers. The code that I wrote (see full code below) seems to work just fine, but here's the thing I don't understand.

I would think typing 'Yes' followed by Ctrl-Z ( I'm using Windows 10) in the console would stop the input. However, after pressing Ctrl-Z -> Enter the console still waits for further input. I have to start a new line after 'Yes', press Ctrl-Z and then hit Enter again to stop the input.

Why is this the case? Is there a way to stop the input after pressing just Ctrl-Z without any of the two new lines?

I read several posts on cin here, including this, this, and this, but they don't seem to answer my question.

#include "pch.h"
#include <iostream>
using namespace std;

unsigned strlen(const char *str)
{
    int count = 0;
    while (*str != '\0') { str++; count++; }
    return count;
}

int main()
{
    char str[100] = {};
    char *pchar;
    pchar = str;
    while (cin >> *pchar) pchar++;
    pchar = str;
    cout << '\n' << strlen(pchar);
    return 0;
}
2
Not trying to put too fine a point to it, but your C++ introduction course appears to teach C first... which is not a good idea. You shouldn't be doing char * in C++. Ever. Nor should you be doing strlen() by hand (a.k.a. "reinventing the wheel"). I know you probably cannot change any of that; I am just voicing my sadness that so many "Intro to C++" courses out there are still "C (with classes)". This is doing both you and C++'s reputation a disservice.DevSolar
@JohnAllison: ...pointers, which you shouldn't have to touch at all, or at least not until you're doing the advanced course. You're being taught all the C stuff -- pointers, arrays, char * -- all of which is unnecessary / bad C++ style, and which you will have to un-learn once you get to "real" C++. Instead of showing you <string> and references and having you do real stuff instead of reinventing the (C) wheel. I feel this is wasting your time, and making things unnecessarily difficult for you (and the instructor).DevSolar
@JohnAllison: In C++ we have std::string and the corresponding functions operating on those. Just two counterquestions: What happens, in your code, if the user enters the 101st character without ending the input? What happens if, e.g. by input redirection, the user enters a null byte somewhere in his input? Also, you can't teach C strings a.k.a. char[] without teaching pointers as well... which IMHO shouldn't be taught in an intro to C++, at all.DevSolar
@marvin: His course should have started with the C++ that makes buffer overflows a non-issue. And I know I am not answering. I am commenting.DevSolar
@JohnAllison: And I understand the "bottom up" approach and all that, but I disagree with its helpfulness. Students want to achieve results. Especially with C++ where everybody tells you how godawful hard it reputedly is (which it is only if you have to learn, then unlearn C first), I find it more helpful to go top-down, and dive right in using string, vector, <algorithm>, polymorphy and templates to their full potential instead of worrying about what's under the hood. That's for the advanced course, "library development"...DevSolar

2 Answers

2
votes

If you press Ctrl-Z after typing some other text, it flushes the line buffer (it does not set end-of-file condition).

You have to press it twice in a row; or press it after a newline; to cause the end-of-file condition to occur.

Your misunderstanding is to do with the windows console behaviour, not with C++ streams per se.

See also: Why do I require multiple EOF (CTRL+Z) characters?

1
votes

Firstly we have to understand what you while loop actually does.

while (cin >> *pchar) pchar++; says that continue getting input from the stdin whilst cin has not encountered an error (or to be specific whilst !cin.fail() == true).

Note that cin is basically an object of std::istream.

Then secondly we have to understand what causes std::istream::fail to return true. Here they are saying that std::istream::fail returns true if the badbit or failbit flags are set (and/or also if any non EOF error occurs).

Having said that, Ctrl-Z is actually EOF (end of file). And based on what I have said above, std::istream::fail will return true if any none EOF error occurs, and of course return false if an EOF occurs.

So in short, EOF/Ctrl-Z does not cause std::istream::fail to return true hence the loop will continue running.

If you really want to have your program cease executing when EOF/Ctrl-Z gets hit, then adjust your loop to something like this...

 while ((cin >> *pchar) && !cin.eof()) pchar++;

Now the loop above reads, whilst std::istream::fail() == false and no EOF/Ctrl-Z character has been entered, continue looping. Else cease the loop.

I hope that fully answers you.