Merging two int text files

I have come up with code for this, but am currently having issues finalizing it. It seems that it only puts out some of the numbers in a numerical order, but not all from both text files. Any suggestions?
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
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

void data (ifstream& v1, ifstream& v2, ofstream& v3);

int main()
{	
	ifstream v1, v2;
	ofstream v3;
	data(v1, v2, v3);

	return 0;
}

void data (ifstream& v1, ifstream& v2, ofstream& v3)
{
	int num1, num2;
	v1.open("File1.txt");
	v2.open("File2.txt");
	v3.open("Output.txt");

	if (v1.fail())
		cout<<"File 1 fail"<<endl;
	if (v2.fail())
		cout<<"File 2 fail"<<endl;

	v1>>num1;
	v2>>num2;

	while((v1.good()) && (v2.good()))
		if(num1<=num2)
			{v3<<num1<< " "<<endl;
			v1>>num1;
			}
		else
		{
			v3<<num2<< " "<<endl;
			v2>>num2;
		}
			

}
Can anyone help me with this?
you are only giving num1 and num2 initial values. consider something like this:
*note* untested, but i think it works

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void merge(std::string UnsortedOne, std::string UnsortedTwo, std::string Sorted) {
    std::ifstream FinOne(UnsortedOne),
                  FinTwo(UnsortedTwo),
                  Product(Sorted);
    int CurrentOne,
        CurrentTwo;

    CurrentOne = FinOne.get();
    CurrentTwo = FinTwo.get();

    while(FinOne && FinTwo) {
        CurrentOne > CurrentTwo ? (
                                    Product << CurrentOne;
                                    CurrentOne = FinOne.get(); :
                                    Product << CurrentTwo;
                                    CurrentTwo = FinTwo.get();
        )
    }
}
That doesn't work for two reasons:

(1) get() doesn't get a number, and OP is using ints.

(2) Not a proper mergesort.


@kdog
I presume your input files are already sorted (in non-decreasing order)?


(1) initially, you must read a number from both files
(1a) Is it possible one or both files have no numbers?

(2) put the smaller number to the output file, and replace it, until there are no more numbers in the file to replace it

(3) output the remaining number to the output file, and repeat until there are no more numbers to replace it

You've done pretty good except for parts 1a and 3.

Lines 24-27: part 1a: You notice that the files are not usable. (I posit that an empty file is usable -- you just need to skip to step 3).

Line 41: part 3 is missing.


If your input files are not already sorted, then you need to just read the two files into a std::deque<int>, one after the other, std::sort() them, then write them to the output file.

Hope this helps.
(1) get() doesn't get a number, and OP is using ints.
well it would grab an ascii value, ie an int, but i see what you are saying.

as to 2, op never said he needed merge sort, and i never claimed to be using merge sort.
@Duoas The files are already sorted, and i'm just trying to understand what you mean by your number 3. Would I just add two more if statements to continue reading the file? Like this?
1
2
3
4
	if(num1<=num2)
		v3<<num1<< " "<<endl;
	if(num1>=num2)
		v3<<num2<< " "<<endl;
@bobby
OP's question is textbook mergesort. I was kind enough to give you the benefit of the doubt with your code, which is currently less correct than OP's.

@kdog
That's the general idea, but remember that (for lines 1-2) you already output num1 (for lines 3-4: you already output num2) in the loop. You need to output the number that you have not yet output.

After that you need to output any numbers remaining in the still-good file.


Here is a restatement of the merge algorithm:
http://www.cplusplus.com/faq/sequences/sequencing/sort-algorithms/mergesort/#algorithm

The sequences A and B are your input files. So:
1
2
3
4
5
6
7
8
9
10
11
12
while (both file A and file B have integers)
  if (integer A < integer B)
    output A
    get next A
  else
    output B
    get next B

if (A still has integers)
  copy remaining integers from A to output
else
  copy remaining integers from B to output

Remember that the trick is you have to attempt to read an integer to know if the file still has integers. (Which is what your code tries to do, so I think you've got that part okay.)

Hope this helps.
You are helping quite a bit @ Duoas, thank you greatly. I made a little progress, but still isn't the correct output. Sorry for being difficult. Here is the updated code.
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
#include <iostream>
#include <fstream>
#include <cmath>
#include <iterator>
#include <algorithm>
using namespace std;

void data (ifstream& v1, ifstream& v2, ofstream& v3);

int main()
{	
	ifstream v1, v2;
	ofstream v3;
	data(v1, v2, v3);

	return 0;
}

void data (ifstream& v1, ifstream& v2, ofstream& v3)
{
	int num1, num2;
	v1.open("File1.txt");
	v2.open("File2.txt");
	v3.open("Output.txt");

	if (v1.fail())
		cout<<"File 1 fail"<<endl;
	if (v2.fail())
		cout<<"File 2 fail"<<endl;

	v1>>num1;
	v2>>num2;

	while((v1.good()) && (v2.good()))
	{	if(num1<=num2)
		{
			v3<<num1<< " "<<endl;
			v1>>num1;
		}

		else
		{
			v3<<num2<< " "<<endl;
			v2>>num2;
		}
	
	}
	if(!v1.eof())
	{
		v1>>num1;
		v3<<num1<< " "<<endl;
	}
	else
	{
		v2>>num2;
		v3<<num2<< " "<<endl;
	}

}
What is the point of passing empty streams? Why not just create local streams in your data function or even pass the file names.

A few other things I noticed in your code is you check if they fail after attempting to open. Why not simply check to see if they opened or not?

1
2
3
4
if(!v1.is_open()) //failed to open
{
    //display error message
}


You also check if the stream is good in the while loop. You can simply put while(v1 && v2) and take advantage of the bool operator. http://www.cplusplus.com/reference/ios/ios/operator_bool/

You also check to see if it is not at the end of file. Why not check if the stream is in a good state?
1
2
3
4
if(v1)
{
    //in a good state do stuff
}


[edit]By the way you are only reading in the next value not everything left in the file.

What I would do is something like this after the loop:
1
2
3
4
5
6
while(v1 >> num1)
{
    //do stuff
}

//same for the other one. 
Last edited on
What is the point of passing empty streams?

For a homework, nothing, but for some I/O, where data is sent in chunks, it is very useful. It means you can call the function again on the same files to process new data as it comes.

Why not simply check to see if they opened or not?

Same difference, AFAIK. There is the potential that checking failbit can report errors unrelated to opening the file, but I am unaware of any implementation that actually does that.

take advantage of the bool operator

Again, same difference. Some people actually prefer to be explicit.

[edit]...

+1
Topic archived. No new replies allowed.