从ifstream的读取数据将无法读取空白

问题描述 投票:20回答:9

我用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;
        }

我打破了while线和current的每个值看上去它有和\r\n绝对不是他们 - 中输入刚刚跳到输入文件的下一行。

c++ c++11
9个回答
16
投票

有操纵禁用空格跳跃行为:

stream >> std::noskipws;

8
投票

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

编辑:

当心:平台(Windows,Un的X,苹果机)在换行符的编码不同。它可以是 '\ n', '\ r' 或两者兼而有之。这也取决于你如何打开文件流(文本或二进制)。

编辑(分析代码):

  while(input.get(current) && current != L'\n');
  continue;

会有\ncurrent,如果没有文件的末尾。之后,你继续while循环最外层。有下一行的第一个字符被读入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;
}

这一方案,适用于自身,消除其输出的所有C ++行注释。内while循环没有吃掉所有文本文件的末尾。请注意putback(c)声明。如果没有换行不会出现。

如果它不能正常工作同样为wifstream,这将是除了一个原因很奇怪:当打开文本文件没有保存为16bit的焦炭,焦炭\n在错误的字节结束了......


4
投票

包裹在一个std::streambuf_iterator流(或它的缓冲器,具体而言)?这应该忽略所有的格式,也给你一个很好的Iterator接口。

另外,一个更高效,防呆,方法可能只使用Win32 API(或升压)的文件内存映射。然后,你可以使用普通的指针穿越它,你保证什么都不会被跳过或运行时转换。


2
投票

流提取具有相同的行为,并跳过空白。

如果你想读的每一个字节,可以使用未格式化的输入功能,如stream.get(c)


2
投票

为什么不干脆用getline

你会得到所有的空格,而你不会得到的行结束字符,你还是会知道它们就躺在那里:)


2
投票

你可以以二进制方式打开流:

std::wifstream stream(filename, std::ios::binary);

你会失去,如果你做任何格式化操作提供我流。

另一种选择是读取整个流成一个字符串,然后处理字符串:

std::wostringstream ss;
ss << filestream.rdbuf();

当然,从ostringstream获取字符串rquires字符串的额外拷贝,所以你可以考虑在某个时候改变这一点,如果你喜欢冒险使用自定义流。编辑:别人提istreambuf_iterator,这可能是做这件事比读全码流转换为字符串的更好的方法。


1
投票

你可以只包裹流中的std :: streambuf_iterator让所有的空格和换行这样的数据。

           /*Open the stream in default mode.*/
            std::ifstream myfile("myfile.txt");

            if(myfile.good()) {
                /*Read data using streambuffer iterators.*/
    vector<char> buf((std::istreambuf_iterator<char>(myfile)), (std::istreambuf_iterator<char>()));

                /*str_buf holds all the data including whitespaces and newline .*/
                string str_buf(buf.begin(),buf.end());

                myfile.close();
            } 

0
投票

只需使用函数getline。

while (getline(input,current))
{
      cout<<current<<"\n";

}

-3
投票

我结束了刚刚开放破解Windows的API,并用它首先读取整个文件到缓冲区中,然后通过字符读取缓冲字符。多谢你们。

© www.soinside.com 2019 - 2024. All rights reserved.