无法读取“std::cin.read”:无法识别返回键

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

提问人:Pietro 提问时间:11/22/2021 更新时间:11/22/2021 访问量:490

问:

我正在尝试使用该函数从键盘读取字符串。 发生的情况是,当我键入字符串时,它看起来正在被读取,但 [Return] 字符被视为普通的换行符,而不是终止符。std::cin.read()

这个函数的终结器是什么?可以修改它吗?

#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;
}

代码测试:GCC 11、clang 13。操作系统: Linux.

C++ IOSTREAM CIN 回车

评论

0赞 KamilCuk 11/22/2021
en.cppreference.com/w/cpp/io/basic_istream/read
1赞 Pete Becker 11/22/2021
std::basic_istream::read 是一个未格式化的输入函数。它不看它正在复制的字符。若要终止输入,需要让控制台告诉应用程序它已到达输入的末尾。在 Windows 上,这是 ctrl-C;在 Unix 系统上,它是 ctrl-D。要查看这一点,您可以尝试在文件中键入输入,然后重定向程序的输入以从该文件中读取。
0赞 Igor Tandetnik 11/22/2021
没有终结符 ;它尝试读取您要求的任意数量的字节。您可能正在寻找 getlineread
1赞 heap underrun 11/22/2021
@PeteBecker 在 Windows 控制台上,EOF 指示器是(不是 ,它将调用信号处理程序例程,后者将默认调用)。但是在 Windows 上的问题在于它必须是单独行的第一个字符(即,您必须先按 然后按 ,否则不会被识别为 EOF)。这意味着换行符也将在 EOF 之前读取。Ctrl+ZCtrl+CExitProcessCtrl+ZEnterCtrl+ZCtrl+Z
0赞 Pete Becker 11/22/2021
@heapunderrun — ctrl-Z 的好抓点。

答:

1赞 heap underrun 11/22/2021 #1

在 Windows 控制台上,EOF 指示器是 +(不是 +,它将调用信号处理程序例程,默认情况下将调用)。但是 Windows 上 + 的问题在于它必须是单独行的第一个字符(即,您必须先按 +,然后再按 +,否则 + 将无法识别为 EOF)。这意味着换行符也将在 EOF 之前读取。CtrlZCtrlCExitProcessCtrlZEnterCtrlZCtrlZ

该行没有达到您的预期。它将输入视为字符,而不是数字。因此,如果按 和 ,提取的值将为 53(字符的 ASCII 代码)。相反,做 .std::cin.get(text_length);5Enter5std::cin >> text_length;

此外,应声明为 ,而不是 。如果它应该适合 8 位,只需在进一步处理之前钳紧该值。text_lengthstd::streamsizechar

还有其他错误:您不会以 null 终止缓冲区,并且您从不显式动态分配的内存(当然,当操作系统结束该过程时,它会隐式释放)。deletenew

总而言之,请查看以下代码:

#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;
}

输入长度后,输入一些文本,完成后,按 ,然后按 +,然后再按一次。(如前所述,不幸的是,+ 前面的换行符也会被读入,但至少 + 允许您终止输入。EnterCtrlZEnterCtrlZCtrlZ