Home > Net >  Cannot read with `std::cin.read`: return key not recognized
Cannot read with `std::cin.read`: return key not recognized

Time:11-22

I am trying to read a string from the keyboard with the std::cin.read() function. What happens is that it looks like the string is being read as I type it, but the [Return] character is treated as a normal new line, and not as a terminator.

What is the terminator for this function? Is it possible to modify it?

#include <iostream>

char* text;
char text_length = 0;

int main() {

    std::cout << "Text length: ";
    std::cin.get(text_length);
    std::cout << "\nText length: " << text_length << std::endl;

    text = new char[1024];
    std::cout << "\n\nText: ";
    std::cin.read(text, text_length);
    std::cout << "\n\nText: " << text << std::endl;
    
    return 0;
}

Code tested on: GCC 11, clang 13. OS: Linux.

CodePudding user response:

On Windows console, the EOF indicator is Ctrl Z (not the Ctrl C, which will invoke a signal handler routine instead, which will call ExitProcess by default). But the problem with Ctrl Z on Windows is that it has to be the first character of a separate line (i.e., you have to press Enter and then Ctrl Z, otherwise the Ctrl Z will not be recognized as an EOF). This means that the newline will also be read before EOF.

The std::cin.get(text_length); line is not doing what you expect. It treats the input as a character, not as a number. So, if you press 5 and Enter, the extracted value will be 53 (the ASCII code for the character 5). Instead, do std::cin >> text_length;.

Also, the text_length should be declared as std::streamsize, not as char. If it is supposed to fit in 8 bits, just clamp the value before further processing.

There are other bugs as well: you don't null-terminate your buffer, and you never explicitly delete the memory dynamically allocated by new (although it will be freed implicitly when the OS ends the process, of course).

To sum it up, check out this code:

#include <algorithm>
#include <iostream>
#include <limits>

int main()
{
    constexpr std::streamsize min_text_length{ 0 };
    constexpr std::streamsize max_text_length{ 255 };

    char* text{ nullptr };
    std::streamsize text_length{ 0 };

    std::cout << "Enter text length: ";
    std::cin >> text_length;
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cout << "Text length entered: " << text_length << '\n';

    text_length = std::clamp(text_length, min_text_length, max_text_length);
    std::cout << "Text length to be used: " << text_length << '\n';

    text = new char[max_text_length   1]{}; // Note this zero-fills the buffer
    std::cout << "Enter text: ";
    std::cin.read(text, text_length);
    std::cout << "Text entered BEGINS-->" << text << "<--ENDS\n";

    delete[] text;
}

After entering the length, enter some text, and when finished, press Enter, followed by Ctrl Z, and Enter again. (As already mentioned, the newline character preceding the Ctrl Z will unfortunately be read in as well, but at least the Ctrl Z allows you to terminate the input.)

  • Related