此代码用于输出Hello World。但它输出0x22fed8 [英] This code is meant to output Hello World. but it outputs 0x22fed8

查看:97
本文介绍了此代码用于输出Hello World。但它输出0x22fed8的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm learning File Handling in C++, but there is a problem here. I am trying to read a file. This code is meant to output Hello World. but it outputs 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;
    }

我在做什么错了?

推荐答案

简单解决方案



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

Simple solution

As others have pointed out, directly printing a file to a stream does't work. Printing the file contents would require opening another stream that reads from the file, or re-setting your stream's read pointer to the beginning and then reading the whole file again (as others have shown).

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

C++ doesn't do this automatically but you can do it manually (here, opening a new stream):

ifstream ifs("filename");

现在,将文件内容写入另一个流是不重要的。不用写文件,只需写文件缓冲区:

Now, writing the file contents to another stream is a trivial addition. Instead of writing the file, simply write the file buffer:

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

仅此而已!

循环的主题,请注意以下列方式在循环中读取文件的代码:

While we're on the subject of loops, beware of code that reads files in a loop in the following manner:

while ( !file.eof() )

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

This code produces an endless loop when there's a reading error. This an happen in many, many situations. Consider e.g. that the file is deleted while you read it, or that someone removes the USB device containing the file or that the file is wrongly formatted. All these cases would create an infinity loop here. Never only test for eof in a stream.

幸运的是,解决方案问题也很简单。此外,它解释了为什么您的原始代码产生如此奇怪的结果。实际上,C ++中的流已隐式转换为 bool -like 类型。出于其他地方说明的原因(提示: 安全布尔成语 ),它实际上已转换为 void *

Luckily, the solution to this problem is also quite simple. Furthermore, it explains why your original code yielded such a weird result. In fact, streams in C++ have an implicit conversion to a bool-like type. For reasons explained elsewhere (cue: safe bool idiom), it is actually converted to void*.

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

This makes it easy to test whether a stream is in a valid, not-at-end state and can safely be read from. Therefore, we can reformulate the loop appropriately:

while (file) …

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

The above code relies on the conversion to void* taking place. Any nonnull pointer indicates a valid stream. Now, the same happens in your code:

cout << file;

因为对于运算符没有适当的重载<< 需要一个流,C ++会查找其他重载并为指针找到重载。因此,它暗中调用了这样的内容:

Since there's no appropriate overload for operator << that takes a stream, C++ looks for other overloads and finds an overload for pointers. So it implicitly calls something like this:

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



更好的解决方案



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

Better solution

I've explained a simple, working solution above. However, this solution requires re-opening the file and reading it to memory again. This doubles the work required. We can make this better by introducing a new class that acts like a stream and that actually sends each output to two streams at once. This way, you can write your data both to the file and to the standard stream at the same time. No need to re-read the file.

该类本身非常简单。以下完整代码演示了一般原理:

The class in itself is quite simple. The following complete code demonstrates the general principle:

#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;
}

这篇关于此代码用于输出Hello World。但它输出0x22fed8的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆