Merging Two Files Into One

Hey guys,

I'm having a problem with merging two text files into a third file. I created two separate text files with five integers each, already sorted.

i.e.
1
2
4
7
9

and
2
4
4
6
8

I need to check each file for the smaller number and add it to a third file in ascending order.
i.e.
1224446789

My current output is this:
12244467

It's not getting to the end of each file. I'm having a problem with the eof() function. I think it's either not reaching the end of the file, or just stopping for some reason. Any help would be appreciated. Here's my code so far:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
        ifstream file1; //declare fstream variables
        ifstream file2;
        ofstream outFile;

        int data1, data2; //declare int variables for reading and writing ints

        file1.open("textFile1.txt"); //open files for input operations
        file2.open("textFile2.txt");
        if (file1.fail() || file2.fail()){ //check for failure to open
          cout << "Error opening file.";
          }            
        outFile.open("out.txt"); //open out file for output operations
        if (outFile.fail()){
          cout << "Outfile open failed.";
          }

        file1 >> data1; //read file1 and first integer
        file2 >> data2; //read file2 and first integer
        while (!file1.eof() || !file2.eof()) //I think my problem lies here
        {
                if (data1 <= data2) //check if data1 <= data2
                {
                        outFile << data1; //if so, record data1
                        file1 >> data1; //read file1 again
                        
                }
                else if (data1 >= data2) //check if data1 >= data2
                {
                      outFile << data2; //if so, record data2
                      file2 >> data2; //read data2 again
                }
                else if (file1.eof()) //check if you are at the end of file1
                {
                     if(!file2.eof()) //while not at the end of file2,
                                      //record data2
                     {
                           outFile << data2;
                     }
                }
                else if (file2.eof()) //check if you are at the end of file2
                {
                     if(!file1.eof()) //while not at the end of file1,
                                      //record data1
                     {
                           outFile << data1;
                     }
                }
                  
        
        }
        
        file1.close(); //close all files
        file2.close();
        outFile.close();
        
        return 0;
}
Last edited on
Lines 39 and 47 (and the bodies of those blocks) in your code will never be reached. data1 will always be either less than, greater than or equal to data2.

If I had to do it the way you're doing it (without using containers) I'd probably do something more like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <fstream>

int main()
{
    std::ifstream file_a("textFile1.txt");
    std::ifstream file_b("textFile2.txt");
    std::ofstream out("out.txt");

    if (!file_a.is_open() || !file_b.is_open() || !out.is_open())
    {
        std::cerr << "Unable to open file(s)\n";
        return 0;
    }

    int data_a;
    int data_b;

    bool need_new_a = true;
    bool need_new_b = true;
    bool a_is_valid = true;
    bool b_is_valid = true;

    while (a_is_valid || b_is_valid)
    {
        if (need_new_a)
        {
            if (file_a >> data_a)
                a_is_valid = true;
            else
                a_is_valid = false;

            need_new_a = false;
        }

        if (need_new_b)
        {
            if (file_b >> data_b)
                b_is_valid = true;
            else
                b_is_valid = false;

            need_new_b = false;
        }

        if (a_is_valid && b_is_valid)
        {
            if (data_a < data_b)
            {
                out << data_a;
                need_new_a = true;
            }
            else
            {
                out << data_b;
                need_new_b = true;
            }
        } 
        else if (a_is_valid)
        {
            out << data_a;
            need_new_a = true;
        }
        else if (b_is_valid)
        {
            out << data_b;
            need_new_b = true;
        }
    }
}

Last edited on
Slightly different logic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <fstream>

int main()
{
    std::ifstream file1("textFile1.txt");
    std::ifstream file2("textFile2.txt");
    std::ofstream fout("output.txt");

    if (!file1.good() || !file2.good() || !fout.good())
    {
        std::cout << "Error opening file(s)" << std::endl;
        return 0;
    }

    int data1;
    int data2;

    file1 >> data1;
    file2 >> data2;

    while (!file1.fail() && !file2.fail())
    {
        if (data1 <= data2)
        {
            fout << data1 << std::endl;
            file1 >> data1;
        }
        else
        {
            fout << data2 << std::endl;
            file2 >> data2;
        }
    }

    while (!file1.fail())
    {
        fout << data1 << std::endl;
        file1 >> data1;
    }

    while (!file2.fail())
    {
        fout << data2 << std::endl;
        file2 >> data2;
    }

}
Last edited on
Or just use std::merge():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <fstream>
#include <iterator>
#include <algorithm>

int main()
{
    std::ifstream file1("textFile1.txt");
    std::ifstream file2("textFile2.txt");
    std::ofstream fout("output.txt");

    using istream_iterator = std::istream_iterator<int> ;

    std::merge( istream_iterator(file1), istream_iterator(),
                istream_iterator(file2), istream_iterator(),
                std::ostream_iterator<int>( fout, "\n" ) ) ;
}
@Chervil: What happens in your logic if:
file1:
1 2 3

file2:
7



This exercise is all about logic and how to consider each possible case.
Last edited on
@Semion1


Why don't you try re-writing this part :
1
2
3
4
5
6
7
8
.
.
file1 >> data1; //read file1 and first integer
file2 >> data2; //read file2 and first integer
while (!file1.eof() || !file2.eof()) //I think my problem lies here
{
.
.


as :
1
2
3
4
5
6
.
.
while(file1 >> data1 && file2 >> data2)
{
.
.
@keskiverto
1
2
3
4
5
file1:
1 2 3

file2:
7

output.txt:
1
2
3
7
Last edited on
Thanks everyone. @The illusionist mirage I'll try that.
Topic archived. No new replies allowed.