从ifstream读取不会读取空格

Pup*_*ppy 21 c++ c++11

我正在用C++实现一个自定义词法分析器,当试图读取空格时,ifstream将不会读取它.我正逐字逐句阅读>>,所有的空白都消失了.是否有任何方法可以让ifstream保留所有的空白并将其读出来给我?我知道在阅读整个字符串时,读取将停留在空白处,但我希望通过逐字逐句阅读,我会避免这种行为.

尝试:.get(),由许多答案推荐,但它具有相同的效果std::noskipws,即,我现在获得所有空格,但不是我需要的一些构造的新行字符.

这是违规代码(扩展评论被截断)

while(input >> current) {
    always_next_struct val = always_next_struct(next);
    if (current == L' ' || current == L'\n' || current == L'\t' || current == L'\r') {
        continue;
    }
    if (current == L'/') {
        input >> current;
        if (current == L'/') {
            // explicitly empty while loop
            while(input.get(current) && current != L'\n');
            continue;
        }
Run Code Online (Sandbox Code Playgroud)

我正在打破这一while行并查看其中的每个值current,\r或者\n肯定不在其中 - 输入只是跳到输入文件中的下一行.

R. *_*des 18

有一个操纵器可以禁用空格跳过行为:

stream >> std::noskipws;
Run Code Online (Sandbox Code Playgroud)

  • 你也可以使用`stream.unsetf(ios_base :: skipws)`; 手动删除该格式标志. (3认同)

Ren*_*ter 8

运算符>>吃空格(空格,制表符,换行符).使用yourstream.get()读取每个字符.

编辑:

注意:平台(Windows,Un*x,Mac)在换行编码方面有所不同.它可以是'\n','\ r'或两者.它还取决于您打开文件流(文本或二进制)的方式.

编辑(分析代码):

  while(input.get(current) && current != L'\n');
  continue;
Run Code Online (Sandbox Code Playgroud)

如果没有到达文件的末尾,将会有一个\nin current.之后,继续进行最外面的循环.在那里读取下一行的第一个字符current.这不是你想要的吗?

我试图重现你的问题(使用charcin不是wchar_twifstream):

//: get.cpp : compile, then run: get < get.cpp

#include <iostream>

int main()
{
  char c;

  while (std::cin.get(c))
  {
    if (c == '/') 
    { 
      char last = c; 
      if (std::cin.get(c) && c == '/')
      {
        // std::cout << "Read to EOL\n";
        while(std::cin.get(c) && c != '\n'); // this comment will be skipped
        // std::cout << "go to next line\n";
        std::cin.putback(c);
        continue;
      }
     else { std::cin.putback(c); c = last; }
    }
    std::cout << c;
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

该程序适用于自身,它在输出中消除了所有C++行注释.内部while循环不会占用文件末尾的所有文本.请注意putback(c)声明.没有它,换行就不会出现.

如果它不起作用wifstream,那将是非常奇怪的,除了一个原因:当打开的文本文件没有保存为16位字符并且\n字符以错误的字节结束时...


Pet*_*ete 6

您可以以二进制模式打开流:

std::wifstream stream(filename, std::ios::binary);
Run Code Online (Sandbox Code Playgroud)

如果您这样做,您将丢失任何提供我的流的格式化操作。

另一种选择是将整个流读入一个字符串,然后处理该字符串:

std::wostringstream ss;
ss << filestream.rdbuf();
Run Code Online (Sandbox Code Playgroud)

当然,从 ostringstream 获取字符串需要额外的字符串副本,因此如果您喜欢冒险,可以考虑在某个时候更改它以使用自定义流。编辑:其他人提到 istreambuf_iterator,这可能是比将整个流读入字符串更好的方法。


Pup*_*ppy -4

我最终只是破解了 Windows API 并使用它首先将整个文件读入缓冲区,然后逐个字符读取该缓冲区。多谢你们。