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