【问题标题】:How can I see exactly what's in std::cin input buffer?如何准确查看 std::cin 输入缓冲区中的内容?
【发布时间】:2016-12-23 20:26:29
【问题描述】:

我遇到的问题是,当有人在控制台中键入内容时,我想准确查看输入缓冲区中的内容我知道如何查看它的唯一方法是通过 std::cin::getline()或 std::getline(),但我认为这两个都写入 char 指针或 std::string 对象,具体取决于系统特定的行尾字符是否合适。例如,我认为在 Windows 上,如果您在控制台上按 Enter 键,它会输入 '\r''\n',但是当我尝试从 char 指针或字符串对象中读取它时,它们不会显示任何 '\ r'。例如,如果我在控制台中输入单词 hello,我怀疑 windows 会放:

'h' 'e' 'l' 'l' 'o' '\r' '\n'

进入缓冲区,但在 char 指针或字符串对象中我只看到“hello”。我基本上想看看输入缓冲区中有什么。我可以在一个循环中从缓冲区中一个一个地提取每个字符,而不会丢弃空白字符吗?

【问题讨论】:

  • 通常,标准 C++ 无法实现。在重要的系统上,您有时可以以二进制模式关闭和重新打开std::cin,然后使用read() 获取字符。但这不是标准所保证的。
  • 对于 text 流(即,未使用std::ios_base::binary 打开的文件流),特定于平台的行结束序列在读取时转换为\n。当写入这些流时,应用相反的操作。也就是说,在 Windows 上读取\r\n 时,它会被翻译成\n。标准流对象的行为通常类似于以文本模式打开的文件流。该标准实际上并未规定标准流对象的确切行为。

标签: c++ string std cin cout


【解决方案1】:

std::cin 是一个std::basic_istream,可以这样操作。

通常,您会使用>>getline 来读取流。这两句话都写着“知道何时停止”。

但是,如果您想使用\ns 查看缓冲区,则假定您将从控制台传递带有换行符的流,并且您用来读取它的函数不会“吃掉”换行符。

您可以copy the buffer to a string。但请记住,您将不得不以其他方式signal the EOF

#include <iostream>
#include <string>
#include <sstream>

int main() {
    std::ostringstream oss{};
    oss << std::cin.rdbuf();
    std::string all_chars{oss.str()};
    std::cout << all_chars;
    return 0;
}

在 Windows 上,如果我输入 hello输入there输入 后跟 Ctl+z (Windows 必须换行)然后我看到:

hello
there
^Z
hello
there

所以在本例中,包括换行符在内的所有内容都存储在 std::string 中。


但我只看到 \n 的行尾。我以为Windows应该 使用\r \n 作为行尾

我添加了以下内容以明确显示各个字符:

int index{};
for(auto mychar : all_chars)
    std::cout << std::setw(3) << index++ << ": character number " << std::setw(5) << static_cast<int>(mychar) 
        << " which is character\t"<< ((mychar == 10) ? "\\n" : std::string{}+mychar) << '\n';

对于它产生的相同输入:

hello
there
^Z
hello
there
  0: character number   104 which is character  h
  1: character number   101 which is character  e
  2: character number   108 which is character  l
  3: character number   108 which is character  l
  4: character number   111 which is character  o
  5: character number    10 which is character  \n
  6: character number   116 which is character  t
  7: character number   104 which is character  h
  8: character number   101 which is character  e
  9: character number   114 which is character  r
 10: character number   101 which is character  e
 11: character number    10 which is character  \n

所以这表明只有\ns 从控制台传递,没有找到\rs。我使用 Windows 10 进行此测试,但我想这已经有一段时间了。

【讨论】:

  • 好的,这是一个很酷的技巧。但我只看到 '\n' 表示行尾。我认为 Windows 应该使用 '\r' '\n' 作为行尾,例如在制作记事本文档时。我以为控制台是一样的。
  • 这很奇怪。太感谢了。另一个规则/例外我必须添加到我的脑海中。
【解决方案2】:

我认为这应该可行:

std::string mystring;
std::cin >> mystring;

for(unsigned int i = 0; i < mystring.size(); i++)
{
    switch(mystring[i])
    {
        case ‘\n’:
            cout << “\\n”; // print \n by escaping the slash
            break;
        case ‘\r’:
            cout << “\\r”; // print \r by escaping the slash
            break;
        // OTHER CASES HERE
        default:
            cout << mystring[i]; // print the string normally
            break;
    }
}

【讨论】:

  • 似乎不起作用,如果我在控制台中输入 hello 开关循环只是 couts hello。我认为这是因为 std::string 中的内容只是你好,就是这样,它从未复制任何 '\r' 或 '\n' 到它。
  • 哦,我看错了。但如果是这样的话,那么缓冲区在技术上没有我想的 '\n' 。我猜流只是在 '\n' 处切断字符串并在那个地方放置一个 '\0' 终止符,因为 line 确实在那里结束。
  • 仔细看这个,我才意识到我误解了你的问题对不起。我假设输入缓冲区是指字符串本身。我相信 Mus campester 的答案正是您想要的。
  • 是的,你是对的,在将它复制到 char 指针的情况下,你可以看到它被切断了 '\n' 并且 null 终止了它。但是我认为Windows行尾是'\r''\n',我想看看这个,从另一个答案看来不是这样,也就是说,似乎只有一个'\n'。
猜你喜欢
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-12
  • 2015-12-31
  • 2020-09-02
相关资源
最近更新 更多