【问题标题】:C++ compile error on std::basic_ifstreamstd::basic_ifstream 上的 C++ 编译错误
【发布时间】:2012-10-28 06:09:33
【问题描述】:

我应该编写一个程序,将两个文件中的数字合并并将所有数字写入第三个文件。该程序从两个不同的文件中获取输入,并将其输出写入第三个文件。每个输入文件都包含一个 int 类型的数字列表,按从小到大的顺序排列。程序运行后,输出文件将包含两个输入文件中的所有数字,按从小到大的顺序排列在一个较长的列表中。我不是 100% 确定我的逻辑是正确的。 感谢您的帮助。

输入文件1:

1 2 3 4 5 6 7 8 9 10

输入文件2:

11 12 13 14 15 16 17 18 19 20

#include <iostream>
#include <conio.h>
#include <fstream>

using namespace std;

int main()
{
int num1, num2;

ifstream inputFile;
ifstream inputFile2;
inputFile.open ("input1.txt");
inputFile2.open("input2.txt");
ofstream outputFile;
outputFile.open("output.txt");

inputFile >> num1;
inputFile2 >> num2;
while(inputFile.eof() && inputFile2.eof())
{
    if (num1 < num2)
    {
        outputFile << num1;
        inputFile >> num1;
    }
    else
    {       
        outputFile << num2;
        inputFile2 >> num2;
    }
    
}

inputFile.close();
inputFile2.close();
outputFile.close();

return 0;
}

【问题讨论】:

  • 您希望inputFile2.open(); 完成什么?另外,不要使用while (!eof),使用while (in &gt;&gt; var)
  • 你能解释一下 >> var 的意思吗?我从来没学过。我猜 var 只是我正在使用的变量,但是 'in'?
  • 这只是通用的。 in 将是输入流,在您的情况下,可能是 inputFileinputFile2
  • @user1742419 你被教过使用while (!inputFile.eof())吗?
  • 这似乎是一个非常常见的错误,听到你被教导如何使用它令人失望。你当然不会知道得更好。您可以在此处阅读以了解为什么它不正确stackoverflow.com/questions/5605125/… 基本上人们似乎使用它,好像eof() 可以判断您是否在文件末尾。但这根本不是它的作用。它会告诉您上次读取是否由于文件结尾而失败。这完全是另一回事。

标签: c++ ifstream file-handling


【解决方案1】:

如果使用标准库没问题,那么可以使用merge

int main()
{
    ifstream inputFile("input1.txt");
    ifstream inputFile2("input2.txt");
    ofstream outputFile("output.txt");

    typedef istream_iterator<int> IT;
    typedef ostream_iterator<int> OT;
    std::merge(IT(inputFile), IT(), IT(inputFile2), IT(), OT(outputFile, " "));

    outputFile.flush();
}

还要注意 i/ofstream 构造函数能够在初始化期间打开文件。

【讨论】:

  • 这是迄今为止我最喜欢的解决方案,但是我会摆脱显式关闭,无论如何都会在销毁时发生,RAII 是 C++ 的强项,让我们使用它!
  • @111111:摆脱inputFiles 的关闭是可以的,但是摆脱outputFile 的关闭——不。我实际上会用冲洗来代替它。基本上 RAII 具有回滚语义,而 close() 和 flush() 是提交语义。 (这里不讨论原子性。)刷新可能会引发错误,因此如果您在正常流程期间关闭文件,您可能希望抛出可能的异常。
  • 我很确定它也会在破坏时刷新。显式关闭文件流的问题是您最终会得到具有“无效”状态的命名对象。
  • @111111:是的,它会刷新,但你不知道它是否失败。关于无效状态,这就是为什么我说我会改为刷新。
  • 但是,在您提供的代码中, .flush() 无论如何都只是返回流,您没有检查它,那么这与让析构函数执行它有什么不同呢?如果您将它放在带有某种处理代码的if() 中,我会同意。您也知道,flush 实际上并不会将数据写入磁盘,它只是将数据提供给操作系统,这极不可能失败。
【解决方案2】:
inputFile2.open();

应该是

inputFile2.close();

【讨论】:

  • 或者干脆完全删除显式关闭,它们只是错误的来源。
【解决方案3】:

inputFile2.open(); 显然是 inputFile2.close(); 的错误输入

但恐怕你的逻辑是完全错误的。你还没有理解练习的意义。您应该同时打开输入文件和输出文件,并且不应该使用数组来存储和排序数字。如果你做对了,你就不需要数组,也不需要做任何排序。这就是练习的重点。

并且在这个论坛上重复至少一百万次已经说过的话。不要使用

while (!inputFile.eof())

这是不正确的。使用

while (inputFile >> num)

这是一个关于如何进行合并的非常基本的草图。有很多细节要填写。

inFile1 >> num1;
inFile2 >> num2;
while (something or other)
{
  if (num1 < num2)
  {
    outFile << num1;
    inFile1 >> num1;
  }
  else
  {
    outFile << num2;
    inFile2 >> num2;
  }
}

这里有一个讽刺意味,“某事或其他”可能确实涉及使用eof()。这是使用inFile.eof() 是正确做法的一种情况。

顺便说一句,您输入数据的方式不是很好。每个文件都应单独排序,但文件 1 中的所有数字不应小于文件 2 中的所有数字。这不是必需的。

【讨论】:

  • 不会是inputFile &gt;&gt; i吗?
  • num 和 i 只是变量,你可以随意调用它们。我用 num 来表示数字。
  • 变量到底代表什么?我想我可能用错了那个空间,把'i'放在那里。什么变量重要吗?
  • 当然,您使用的变量对程序的逻辑 很重要,如果您读入错误的变量,您的程序将无法运行。您对变量的概念有疑问吗?这是非常基础的,如果你没有明确的概念,你将在未来挣扎。
  • 有点,但是你输出两个数字,正如我所说的,只输出较小的数字。您不知道是否应该输出更大的数字,因为另一个文件中可能还有另一个较小的数字(正如您在之前的评论中所说)。也是while(inputFile&gt;&gt;num1 &amp;&amp; inputFile2&gt;&gt;num2)
猜你喜欢
  • 2015-09-12
  • 2013-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 2017-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多