Home > Back-end >  How to merge two numbers from two sorted files into a third file in ascending order
How to merge two numbers from two sorted files into a third file in ascending order

Time:11-29

I'm trying to merge two files that contain some numbers into a third file but I'm not getting the right result.

This is my code:

void merge(string input_file1, string input_file2, string output_file){
    fstream fs1; 
    fstream fs2; 
    fstream fs3;
    int n1, n2;  
    fs1.open(input_file1); 
    fs2.open(input_file2);
    fs3.open(output_file); 

    while(fs1 >> n1 && fs2 >> n2){
        if(n1 < n2){
            fs3 << n1 << " ";
            fs1 >> n1;
        }
        else{
            fs3 << n2 << " "; 
            fs2 >> n2;
        }
    }
    while(fs1 >> n1)
        fs3 << n1 << " ";
    
    while(fs2 >> n2) 
        fs3 << n2 << " ";
}

input:

input file1: 1 2 3 4 5 6 7

input file2: 34 56 77 78 88 90 100

output file: 1 3 5 7 88 90 100

CodePudding user response:

If n1 < n2, you do fs1 >> n1 twice (once immediately and then once in the loop condition) and discard both the first value and n2; if n1 >= n2, you do fs2 >> n2 twice and discard both its first value and n1.

You can't do any unconditional reading in the "selection loop", as you should only replace the smallest number.

Something like this (untested):

// Potentially read the first two numbers.
fs1 >> n1;
fs2 >> n2;
// This loop is entered only if there were two numbers.  
// Note that the last successfully read number is written only for the shorter input (if any).
while (fs1 && fs2)
{
    if (n1 < n2)
    {
        fs3 << n1 << ' ';
        fs1 >> n1;
    }
    else
    {
        fs3 << n2 << ' ';
        fs2 >> n2;
    }
}
// Write-then-read because the last value read has not been written yet.
while (fs1)
{
    fs3 << n1;
    fs1 >> n1;
}
while (fs2)
{
    fs3 << n2;
    fs2 >> n2;
}

CodePudding user response:

There is already a very good an accepted answer by user molbdnilo. Good.

Maybe, to be complete, I will add a "more modern" C solution.

Please see the very simple example:

#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std::string_literals;

void merge(const std::string& in1, const std::string& in2, const std::string& out) {
    if (std::ifstream ifs1{ in1 }, ifs2(in2); ifs1 and ifs2)
        if (std::ofstream ofs{ out }; ofs) {
            
            std::vector data{ std::istream_iterator<int>(ifs1), {} };
            data.insert(data.end(), std::istream_iterator<int>(ifs2), {});
            std::sort(data.begin(), data.end());
            std::copy(data.begin(), data.end(), std::ostream_iterator<int>(ofs, " "));
        }
        else std::cerr << "\nError: Could not open input files\n\n";
    else std::cerr << "\nError: Could not open output files\n\n";
}
int main() {
    merge("in1.txt"s, "in2.txt"s, "out.txt"s);
}
  • Related