此代码用于输出Hello World。但它输出0x22fed8

时间:2009-02-15 15:52:06

标签: c++

我正在学习C ++中的文件处理,但这里有一个问题。我正在尝试读取文件。 此代码用于输出Hello World。但它输出0x22fed8。

#include <iostream>
#include <fstream>

using namespace std;

    int main()
    {
        fstream file;
        file.open("test.txt",ios::in|ios::out);
        file << "Hello World";
        cout << file;
        file.close();

        return 0;
    }

我做错了什么?

4 个答案:

答案 0 :(得分:25)

简单解决方案

正如其他人所指出的那样,直接将文件打印到流不起作用。打印文件内容需要打开从文件中读取的另一个流,或者将流的读取指针重新设置为开头,然后再次读取整个文件(正如其他人所示)。

C ++不会自动执行此操作,但您可以手动执行此操作(此处打开新流):

ifstream ifs("filename");

现在,将文件内容写入另一个流是一个微不足道的补充。不要编写文件,只需编写文件缓冲区:

cout << ifs.rdbuf() << endl;

这就是全部!逐行读取文件不需要循环。

测试有效流

虽然我们讨论的是循环,但要注意以下列方式在循环中读取文件的代码:

while ( !file.eof() )

当出现读数错误时,此代码会产生无限循环。这种情况在很多很多情况下都会发生。考虑例如您在读取文件时删除该文件,或者某人删除了包含该文件的USB设备或该文件格式错误。所有这些情况都会在这里创建一个无限循环。 从不仅测试流中的eof

幸运的是,解决这个问题的方法也很简单。此外,它解释了为什么你的原始代码产生了如此奇怪的结果。实际上,C ++中的流具有隐式转换为 bool - 类似类型。出于其他地方解释的原因(提示:safe bool idiom),它实际上已转换为void*

这样可以轻松测试流是否处于有效的非结束状态,并且可以安全地从中读取。因此,我们可以适当地重新制定循环:

while (file) …

上述代码依赖于转换为void*。任何非null指针都表示有效的流。现在,代码中也会出现同样的情况:

cout << file;

由于operator <<没有适当的重载来获取流,因此C ++会查找其他重载并找到指针的重载。所以它隐含地调用了这样的东西:

cout << static_cast<void*>(file);

更好的解决方案

我已经解释了上面一个简单,有效的解决方案。但是,此解决方案需要重新打开文件并再次将其读取到内存中。这使所需的工作增加了一倍。我们可以通过引入一个类似于流的新类来实现这一点,并且实际上将每个输出一次发送到两个流。这样,您可以同时将数据写入文件和标准流。无需重新读取文件。

这个课本身很简单。以下完整代码演示了一般原则:

#include <iostream>
#include <fstream>

struct sinkpair {
    sinkpair(std::ostream& a, std::ostream& b) : a(a), b(b) { }

    // Forward all ouputs to both streams.
    template <typename T>
    sinkpair& operator <<(T const& value) {
        a << value;
        b << value;
        return *this;
    }

    // Explicit overload needed for manipulators such as `endl`.
    sinkpair& operator <<(std::ostream& (*manip)(std::ostream&)) {
        a << manip;
        b << manip;
        return *this;
    }

private:
    std::ostream& a;
    std::ostream& b;
};

int main() {
    std::ofstream ofs("test.txt");
    sinkpair sp(std::cout, ofs);
    sp << "Hello" << std::endl;
}

答案 1 :(得分:12)

编辑:有mrree的建议。

ifstream fin("file.txt");

if (fin.is_open() == false) {
  // error
}

string line;

while( getline(fin, line) ) {  
  cout << line;
}

答案 2 :(得分:7)

让我们检查一下

cout << file;

这个输出数字的原因是因为引擎盖下的fstream是一个文件指针。通过将文件传递给cout,你基本上要求一个fout的cout。这将默认为文件的基础句柄的值。

如果要输出文件的内容,则需要将其读入并逐行输出。

fstream file;
file.open("test.txt",ios::in|ios::out);
file << "Hello World";
file.seekg (0, ios::beg);
while ( !file.eof() ) {
  string temp;
  file >> temp;
  cout << temp << std::eol;
}

file.close();

答案 3 :(得分:6)

#include <iostream>
#include <fstream>

int main(int, char **) 
{
  std::ifstream input("test.txt");
  char c;                                                          
  while (input >> c) {
    std::cout << c;
  }
  return 0;
}

不要包含整个标准命名空间。 如果您想要输入文件流,请使用ifstream。

您想输出文件的内容,而不是文件。

如果要写入文件,请将其读回并发送到stdout,

#include <iostream>
#include <fstream>

int main(int, char **)
{
  std::fstream file("test.txt",std::ios::in|std::ios::out);
  file << "Hello" << std::endl;
  file.seekp(std::ios::beg);
  char c;
  while (file >>c) {
      std::cout << c ;
  }
  return 0;
}

Konrad有最好的答案,但请考虑高级方法:

#include <algorithm>
#include <iostream>
#include <fstream>
#include <iterator>

int main(int, char **)
{
  std::fstream file("test.txt",std::ios::in|std::ios::out);
  file << "Hello" << std::endl;
  file.seekp(std::ios::beg);
  std::copy(
      std::istream_iterator<char>(file),
      std::istream_iterator<char>(), 
      std::ostream_iterator<char>(std::cout)
      );
  return 0;
}