【问题标题】:Can't read whole file into string无法将整个文件读入字符串
【发布时间】:2017-04-30 23:27:08
【问题描述】:

我有一个代码:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char *argv[]) {
    ifstream file;

    do {
        string filename;
        cout << "Input file name:" << endl;
        cin >> filename;
        file.open(filename, ios::in);
    } while (!file.is_open());

    string content(istreambuf_iterator<char>(file),
                   istreambuf_iterator<char>());

    cout << "Content:\n" << content << endl;

    if (file.is_open()) {
        file.close();
    }

    return 0;
}

要读取此文件内容:

 1 -1  0 -3  0
-2  5  0  0  0
 0  0  4  6  4
-4  0  2  7  0
 0  8  0  0 -5

但它只输出1 和一个新行。
附:我是个菜鸟,只是通过示例学习 C++。我做错了什么?

【问题讨论】:

  • 为什么要将整数值读入string?将整数值读入整数容器不是更有意义吗?
  • 不,我想将它作为简单的行读入string。正如我所写,它仅供学习。
  • 首先,那个文件里有什么?这些是文件中的实际字符,还是文件由恰好具有这些值的整数组成?这对于文件中的实际内容有很大的不同。
  • 刚才我复制了一个文件内容到这里。它使用 UTF-8 编码,但据我所知,数字代码与 ASCII 标准中的代码相同。
  • @NeilButterworth,我的控制台编码有问题,所以它会输出一些警告而不是正常警告。

标签: c++ c++11


【解决方案1】:

哇,这是一个偷偷摸摸的!

Coliru 上编译您的代码产生了这个警告:

main.cpp:20:29: warning: the address of 'std::__cxx11::string content(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> > (*)())' will always evaluate as 'true' [-Waddress]

地址?什么地址??好吧,如果你仔细观察这个带括号的混乱并眯着眼睛,你最终会注意到:

string content(istreambuf_iterator<char>(file),
               istreambuf_iterator<char>());

...实际上是...一个函数声明!具体来说,一个名为content 的函数,接受两个std::istreambuf_iterator&lt;char&gt; 类型的参数并返回一个std::string
事实上,std::cout &lt;&lt; content; 获取此函数的地址并将其转换为布尔值,产生 1 和一个公平的警告。

这个问题被称为“最棘手的解析”。这是使用统一初始化的原因之一,如下:

string content{istreambuf_iterator<char>{file},
               istreambuf_iterator<char>{}};

不再有语法歧义,content 现在是实际的std::string,一切正常。

但请花点时间联系unlearn using namespace std;。谢谢:)

【讨论】:

  • 感谢您的详细解释。我可以得到{} 允许获得一个它是变量的编译器。但我不明白为什么这个string content((istreambuf_iterator&lt;char&gt;(file)), istreambuf_iterator&lt;char&gt;()); 有效而我的无效?请您稍微解释一下好吗?
  • @Шах 括号没有任何意义(foo 在语义上仍然等同于(foo)),它们的唯一用途是确保 syntax 不能是函数声明。这是因为这样一个模棱两可的行被定义为首先被解析为函数声明。
  • @Шах 这就是精神。在您的情况下,int foo(1); 不能是函数声明。当有一个类型时,就会出现歧义:int foo(float(bar));int 是用 float(bar) 初始化的(bar 转换为 float),还是 int foo(float bar); 的函数签名?声明参数时,您可以将参数的名称括在括号中,因此可以两者兼而有之。因此,选择了函数。但是,您不能包装 whole 参数,因此 int foo((float(bar))); 不能是函数:它无疑是 int
  • @Шах 别担心,这只是 C++ 的怪异角落之一。大多数程序员有时会碰到它,他们只是诅咒一下,添加一些括号或大括号并继续前进:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-29
  • 1970-01-01
相关资源
最近更新 更多