【问题标题】:What happens when an ofstream object.open() is commented out?当一个 ofstream object.open() 被注释掉时会发生什么?
【发布时间】:2015-12-29 19:00:54
【问题描述】:
#include<iostream>
#include<fstream>
#include<string>
#include<vector>

using namespace std;

int main(){

    ofstream out;
    ifstream in;

    out.open("The Necessary Death of Charlie Countryman2.srt");
        if (out.fail()) {
            perror("The Necessary Death of Charlie Countryman2.srt");
        }

    in.open("The Necessary Death of Charlie Countryman.srt");
        if (in.fail()) {
            perror("The Necessary Death of Charlie Countryman.srt");
        }

    vector<string> input;
    string inc;

    while (getline(in, inc)) {
        input.push_back(inc);
    }

    for (int k = 0; k < input.size(); k++) {
        out << input[k] << endl;
    }    
    return 0;
}

当我使用 ifstream insomefile.txt 读取并使用 写入 anotherfile.txt >ofstream in,一切正常,但假设我注释掉 out.open("anotherfile.txt") 并执行代码,没有错误,当我打开 anotherfile.txt它是空的。

我的问题是在

for (int k = 0; k < input.size(); k++) {
            out << input[k] << endl;
        }

会发生什么?

input[k] 发送到哪里或发送到什么位置?如果是 cout,它会转到命令提示符,如果 out.open("anotherfile.txt") 没有被注释,那么它会转到 anotherfile.txt。

【问题讨论】:

  • 似乎它被发送到一个从未使用过的缓冲区。但我找不到有关它的更多信息
  • 当一个输出文件没有被打开时,文本被简单地加载到一个缓冲区中,并在程序终止时在其中销毁。除非您打开文件进行阅读,否则您尝试发送到输出文件的文本将被转发回堆栈。
  • @I3ck 和@Poriferous 谢谢你们,这就是我想知道我的input[k] 发送到哪里。

标签: c++ iostream fstream


【解决方案1】:

我假设out 被声明为ostream(或ofstream 等子类)。当您注释掉out.open(...) 行时,out 被初始化为一个关闭的文件。因此,当您尝试写入时,什么都没有发生,并且注入失败......但是 无法测试它是否成功!

如果你测试过:

    for (int k = 0; k < input.size(); k++) {
        out << input[k] << endl;
        if out.fail() {
            // process error condition...
        }
    }

你会传入错误条件分支,并且能够知道注入没有发生。

【讨论】:

    【解决方案2】:

    每个&lt;&lt; 操作都会失败,仅此而已(这就是(1)所发生的一切)。


    (1) 流可以设置为失败时抛出异常的模式,但这不是默认设置。默认情况下,失败只是默默地忽略。除了设置了失败状态位,您可以使用fail() 或通过转换为bool 进行检查。

    【讨论】:

    • 我不认为getline 失败,因为getline(in, inc)in 读取,它是ifstream 对象,它与outofstream 对象无关。
    • @nSv23:哦,你说得对:它是另一个被淘汰的流。好的,正在修复。
    • 是的inputstd::vector,但这几乎是整个代码,只需从in 读取并写入out
    【解决方案3】:

    ofstream 使用这个operator&lt;&lt; 签名

    basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb);
    

    来自cpppreference, operator&lt;&lt;, 8)

    在构造并检查哨兵对象后,检查 sb 是否为空指针。如果是,则执行 setstate(badbit) 并退出。

    您可以通过以下方式轻松检查

    #include <iostream>
    #include <fstream>
    
    int main()
    {
        std::ofstream sink;
        //sink.open("/dev/null");
    
        sink << "check state";
    
        switch(sink.rdstate())
        {
            case std::ios_base::failbit:
                std::cout << "stream state is failbit\n";
                break;
            case std::ios_base::goodbit:
                std::cout << "stream state is goodbit\n";
                break;
            case std::ios_base::eofbit:
                std::cout << "stream state is eofbit\n";
                break;
            case std::ios_base::badbit:
                std::cout << "stream state is badbit\n";
                break;
            default:
                break;
        }
    
        return 0;
    }
    

    Prints: 流状态是坏位

    【讨论】:

      【解决方案4】:

      outstd::ostream 类型的对象,类似地,std::cout 是位于全局命名空间中的 std::ostream 类型的对象(它在程序的开头可用)。

      std::ostream 类型的对象(输出流,包括像 std::ofstream 一样扩展它的子类)的 &lt;&lt; 运算符重载。

      这种方式拥有cout&lt;&lt;"hello";std::cout.operator&lt;&lt;("Hello World"); 是一回事

      请注意,重载的&lt;&lt; 运算符返回对ostream 对象的引用,因此cout&lt;&lt;"hi" &lt;&lt; " there"; 基本上是

      std::cout.operator<<("hi").operator<<(" there"));
      

      您需要在写入之前打开任何输出文件流。通过这样做,您正在调用操作系统的系统调用,使您可以访问文件,以便您可以写入它们。否则,您将尝试写入您的进程无权写入的已关闭文件。

      您不必为std::cout 明确执行此操作,但您应该打开自己的输出文件流。

      别忘了关闭你打开的文件!!

      【讨论】:

      • 这没有回答问题。
      • 不确定我是否跟随,他在问为什么他需要在写入之前打开输出流,并且想知道为什么 cout 的行为不同。
      • 他或她询问在写入打开的流时会发生什么。 OP 不会问“如何写入文件?”。
      猜你喜欢
      • 2016-01-15
      • 2011-08-25
      • 2017-03-24
      • 2023-03-25
      • 2011-01-24
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      • 2021-11-08
      相关资源
      最近更新 更多