将已排序的数字从功能输出写入文本文件?

时间:2015-01-23 00:46:13

标签: c++

我有两个文本文件,每个文件都有从最低到最高排序的未知数量的整数...例如:

  

输入文件1:1 3 5 7 9 11 ...
  输入文件2:2 4 6 8 10 ....

我想从两个文件中获取这些数字,从低到高排序,然后将输入文件中的已排序数字的完整列表输出到单个输出文件。我到目前为止......

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "iosort.h"

int main()
{
    const char* filename1 = "numberlist1.txt";
    const char* filename2 = "numberlist2.txt";
    std::ofstream ofs("output.txt");
    std::ifstream ifs1, ifs2;
    std::string input1, input2;

    ifs1.open(filename1);
    std::getline(ifs1, input1);
    std::cout << "Contents of file 1: " << input1 << std::endl;

    ifs2.open(filename2);
    std::getline(ifs2, input2);
    std::cout << "Contents of file 2: " << input2 << std::endl;

    ioSort(ifs1, ifs2, ofs);


    return 0;
}

和我的功能......

#include <fstream>
#include <sstream>
#include <vector>
#include "iosort.h"

void ioSort(std::ifstream& in1, std::ifstream& in2, std::ofstream& out)
{

    int a, b;
    std::vector<int> f1, f2, f3; //create one vector for each input stream

    while (in1 >> a)
    {
        f1.push_back(a);
    }

    while (in2 >> b)
    {
        f2.push_back(b);
    }

    //now f1 and f2 are vectors that have the numbers from the input files
    //we know that in these input files numbers are sorted from low to high

    if (f1.size() > f2.size()) //input stream 1 was larger
    {
        for (int i = 0; i < f2.size(); i++)
        {
            if (f1[i] > f2[i]) //number at input vector 2 less that respective pos
            {                   //in input vector 1
                f3.push_back(f2[i]);
            }
            else if(f1[i] == f2[i]) //numbers are equal
            {
                f3.push_back(f1[i]);
                f3.push_back(f2[i]);
            }
            else //number in 1 is less than that in vector 2
            {
                f3.push_back(f1[i]);
            }
        }

        for (int i = f2.size(); i < f1.size(); i++)
        {
            f3.push_back(f1[i]); //push remaining numbers from stream 1 into vector
        }
    }
    else //input stream 2 was larger
    {
        for (int i = 0; i < f1.size(); i++)
        {
            if (f1[i] > f2[i]) //number at input vector 2 less that respective pos
            {                   //in input vector 1
                f3.push_back(f2[i]);
            }
            else if(f1[i] == f2[i]) //numbers are equal
            {
                f3.push_back(f1[i]);
                f3.push_back(f2[i]);
            }
            else //number in 1 is less than that in vector 2
            {
                f3.push_back(f1[i]);
            }
        }

        for (int i = f1.size(); i < f2.size(); i++)
        {
            f3.push_back(f1[i]); //push remaining numbers from stream 2 into vector
        }

    }

    //send vector contents to output file
    for (int i = 0; i < f3.size(); i++)
    {
        out << f3[i] << " ";
    }


}

每次编译和运行时,都会创建文件output.txt,但它是空的。任何人都可以指出我做错了什么。如果,在主要方面,我做了类似的事情:

out << 8 << " " << 9 << std::endl;

然后它将显示在输出文件中。

3 个答案:

答案 0 :(得分:1)

AHA!发现你的错误。您打开文件,然后直接将其读取到stdout(列出文件内容的位置),然后将相同的流传递给您的函数。你不能做这个。无论何时从文件中读取,流都会进一步移动到文件中。当你进入排序功能时,你就在文件的末尾,所以没有数字被读取!

您需要删除

std::getline(ifs1, input1);
std::cout << "Contents of file 1: " << input1 << std::endl;

std::getline(ifs2, input2);
std::cout << "Contents of file 2: " << input2 << std::endl;

相反,在将它们存储在矢量中之后将它们打印出来。

我将把剩下的回复留在下面,因为你或后代可能需要它。


我不确定输出文件问题是怎么回事。浏览整个链条,看看它失败的地方:

  1. 在您阅读完文件后,用cout打印出f1和f2。他们在那里,你期待什么?如果是,我们可以继续前进。
  2. 算法运行后,你的f3在那里,你期望什么?如果是这样,继续前进!
  3. 这使您可以诊断代码失败的确切行(即没有按照您的预期执行),并且您知道可以统治您已检出的所有内容。
  4. 当然,您可以在调试环境下启动它,而不是使用cout,然后逐步查看会发生什么,但如果您不知道怎么做,那么第一次诊断您的问题需要更长的时间
  5. 您确实遇到其他问题,您的合并功能有错误。您最终会跳过某些元素,因为您只对两个数组使用一个索引。考虑一下:您只需将一个数字推入f1[i] > f2[i]f1[i] < f2[i]的输出数组中,但您可以通过递增i来放弃这两个数字。

    您可以采取合并循环并进行大量简化,同时修复错误:)。

    auto it = f1.cbegin();
    auto jt = f2.cbegin();
    
    while (it != f1.cend() && jt != f2.cend()) {
      if (*it < *jt) f3.push_back(*jt++); //f2 was bigger, push f2>f3 and increment f2 index
      else if (*it > *jt) f3.push_back(*it++); //f1 was bigger, push f1>f3 and increment f1 index 
      else { //implicit equals, only option left
        f3.push_back(*jt++);
        f3.push_back(*it++);
      }
    }
    
    while (it != f1.cend()) f3.push_back(*it++);
    while (jt != f2.cend()) f3.push_back(*jt++);
    

    所以现在f3包含你的排序数组,按O(m + n)时间排序。如果您是为了学习而这样做的话,我会先尝试使用您的方法来解决您的错误,然后再切换到此。

    如果你想编写更少的代码并且速度不是问题,你也可以使用<algorithm>来做这件事,但这是一个糟糕的O((n + m)lg(n + m))

    auto it = f1.cbegin();
    auto jt = f2.cbegin();
    
    while (it != f1.cend()) f3.push_back(*it++);
    while (jt != f2.cend()) f3.push_back(*jt++);
    
    std::sort(f3.begin(), f3.end());
    

答案 1 :(得分:1)

为了做空:

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

int main()
{
    std::ifstream infile1("infile1.txt");
    std::ifstream infile2("infile2.txt");
    std::ofstream outfile("outfile.txt");

    std::merge(
        std::istream_iterator<int>{infile1}, std::istream_iterator<int>{},
        std::istream_iterator<int>{infile2}, std::istream_iterator<int>{},
        std::ostream_iterator<int>{outfile, " "}
        );
}

std::merge是一种STL算法,它将两个已排序的范围合并为一个已排序的范围。范围是这种情况的文件。使用std::istream_iterator<int>将文件视为范围。输出文件使用std::ostream_iterator<int>作为范围进行访问。

答案 2 :(得分:1)

由于您在致电std::getline()之前使用ioSort()正在阅读该文件,因此无需读取排序功能。

您可以使用seekg()回退到文件的开头。

ifs1.clear();
ifs1.seekg(0, ifs1.beg);
ifs2.clear();
ifs2.seekg(0, ifs1.beg);
ioSort(ifs1, ifs2, ofs);

请参阅How to read same file twice in a row