1

I'm supposed to write a program that merges the numbers in two files and writes all the numbers into a third file. The program takes input from two different files and writes its output to a third file. Each input file contains a list of numbers of type int in sorted order from the smallest to the largest. After the program is run, the output file will contain all the numbers in the two input files in one longer list in sorted order from smallest to largest. I'm not 100% sure my logic is correct. Thank you for your help.

inputFile1:

1 2 3 4 5 6 7 8 9 10

inputFile2:

11 12 13 14 15 16 17 18 19 20

#include <iostream>
#include <conio.h>
#include <fstream>

using namespace std;

int main()
{
int num1, num2;

ifstream inputFile;
ifstream inputFile2;
inputFile.open ("input1.txt");
inputFile2.open("input2.txt");
ofstream outputFile;
outputFile.open("output.txt");

inputFile >> num1;
inputFile2 >> num2;
while(inputFile.eof() && inputFile2.eof())
{
    if (num1 < num2)
    {
        outputFile << num1;
        inputFile >> num1;
    }
    else
    {       
        outputFile << num2;
        inputFile2 >> num2;
    }
    
}

inputFile.close();
inputFile2.close();
outputFile.close();

return 0;
}
Community
  • 1
  • 1
user1742419
  • 49
  • 2
  • 12
  • What do you expect `inputFile2.open();` to accomplish? Also, don't use `while (!eof)`, use `while (in >> var)`. – chris Oct 28 '12 at 06:11
  • Can you explain what in >> var means? I've never learned that. I'm guessing var is just the variable that I'm using, but 'in'? – user1742419 Oct 28 '12 at 06:14
  • It's just being generic. `in` would be the input stream, which, in your case, could be `inputFile` or `inputFile2`. – chris Oct 28 '12 at 06:16
  • @user1742419 Were you taught to use `while (!inputFile.eof())`? – john Oct 28 '12 at 06:19
  • Yes, but it seems like it's a taboo and I'm afraid to say yes to your question. – user1742419 Oct 28 '12 at 06:23
  • 1
    It seems to be an incredibly common error, and it's disappointing to hear you were taught to use it. You weren't to know better of course. You can read here for an explanation as to why it is incorrect http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong Basically people seem to use it as if `eof()` can tell whether you are at the end of file. but that's not what it does at all. It tells you if your last read failed because of an end of file. Which is something else entirely. – john Oct 28 '12 at 06:25

3 Answers3

2

If using the standard library is OK, then you can use merge:

int main()
{
    ifstream inputFile("input1.txt");
    ifstream inputFile2("input2.txt");
    ofstream outputFile("output.txt");

    typedef istream_iterator<int> IT;
    typedef ostream_iterator<int> OT;
    std::merge(IT(inputFile), IT(), IT(inputFile2), IT(), OT(outputFile, " "));

    outputFile.flush();
}

Also note that the i/ofstream constructor is capable of opening file during initialization.

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • This is by far my favourite solution shown, however I would do rid of the explicit closes, that will happen at destruction anyway, RAII is C++ strong point, lets use it! – 111111 Oct 28 '12 at 12:35
  • @111111: Getting rid of closes of `inputFiles` is OK, but getting rid of the close of `outputFile` -- Nah. I would replace it with a flush actually. Basically RAII has rollback semantics, whereas close() and flush() are commit semantics. (Not talking about atomicity here.) The flush may throw an error, so if you are closing a file during a normal flow you may want to get the possible exception thrown. – Yakov Galka Oct 28 '12 at 17:06
  • I am pretty sure that it flushes on destruction too. explicitly closing filestreams has the issue that you end up with named objects with an "invalid" state. – 111111 Oct 28 '12 at 17:11
  • @111111: Yes, it flushes, but you don't know whether it fails. Regarding invalid state, this is why I said that I would flush instead. – Yakov Galka Oct 28 '12 at 17:19
  • but, in the code you have presented .flush() is just returns the stream anyway, which you do not check, so how is that any different to just letting the destructor do it? If you had it in an `if()` with some sort of handling code I would agree. Also you are aware that flush doesn't actually write the data to disk, it just gives it to the OS, which is highly unlikely to fail. – 111111 Oct 28 '12 at 17:22
  • @111111: the code doesn't check for errors at all, because it is not the point of the qstn/answer. As long as we talk about whether one should call `flush` or not in real code, then the answer is 'yes'. 1) Not all streams use std::filebuf, and even the implementation of std::filebuf *may* indicate a failure by throwing an exception, in which case setting `exceptions(badbit)` will give you the desired error handling. 2) The implementation of `std::filebuf` *may* actually flush to disk, although not all of them do this. 3) if flush fails in the above code in sets badbit which you can test later. – Yakov Galka Oct 28 '12 at 17:32
  • The only problem that I have with this is that I have no idea what's happening lol. – user1742419 Oct 28 '12 at 19:03
  • @user1742419: well, if it is homework (and it looks so) then the instructor probably wanted you to implement `merge` yourself and this answer does not help you. If so, you should have added a 'homework' tag. – Yakov Galka Oct 28 '12 at 19:16
  • Last time I added a 'homework' tag I was told it wasn't necessary anymore. Also, I've only learned basics so far so I haven't even learned merge haha. – user1742419 Oct 28 '12 at 20:44
1
inputFile2.open();

should be

inputFile2.close();
codaddict
  • 445,704
  • 82
  • 492
  • 529
1

inputFile2.open(); is clearly a mistype for inputFile2.close();

But I'm afraid your logic is completely wrong. You haven't understood the point of the exercise. You are supposed to open both input files and the output file at the same time and you are not supposed to use an array to store and sort the numbers. If you do this right you will not need an array and will not need to do any sorting at all. That's the point of the exercise.

And to repeat what has already been said at least a million times on this forum. Do not use

while (!inputFile.eof())

It is incorrect. Do use

while (inputFile >> num)

This is a very basic sketch of how to do the merging. There's plenty of detail to fill in.

inFile1 >> num1;
inFile2 >> num2;
while (something or other)
{
  if (num1 < num2)
  {
    outFile << num1;
    inFile1 >> num1;
  }
  else
  {
    outFile << num2;
    inFile2 >> num2;
  }
}

There's an irony here, 'something or other' probably does involve using eof(). This is one occasion when using inFile.eof() is the right thing to do.

BTW the way your input data is not very good. Each file individually should be sorted but you shouldn't have all the numbers in file1 less than all the numbers in file2. That's not required.

john
  • 85,011
  • 4
  • 57
  • 81
  • Wouldn't it be `inputFile >> i`? – user1742419 Oct 28 '12 at 06:20
  • num and i are just variables, you can call them whatever you like. I used num just to mean number. – john Oct 28 '12 at 06:21
  • The variables indicate what exactly? I think I might've used that space wrong, by putting 'i' in there. Does it matter what variable? – user1742419 Oct 28 '12 at 06:24
  • Of course what variable you use matters for the *logic* of your program, if you read into the wrong variable your program isn't going to work. Are you having trouble with the concept of a variable? It's pretty fundamental, and you're going to struggle in the future if you don't have the concept clear. – john Oct 28 '12 at 06:30
  • I mean I don't know what variable to use in the place of that variable that you said. Because technically I have two variables in that loop. I have the array 'num', and then the counter variable 'i'. I don't know which to use and why. – user1742419 Oct 28 '12 at 06:34
  • Well that's for you to work out in solving this exercise. As I said you don't need to use an array to solve this puzzle. Think about how you would solve this if you were doing it yourself. Would you scan the two list of numbers one after the other, or would you scan both at the same time? Remember that the two lists of numbers are *already sorted*, that is crucial. What difference does that make? Basically the point of this exercise is that you can solve it without doing any sorting yourself. – john Oct 28 '12 at 06:38
  • Oh my god. . .I am going to be ashamed to say this. But I didn't realize I was supposed to create two files that had the numbers in _sorted order_ I created files but without sorted order. haha. I read it again and I know how to fix that. Thank you. – user1742419 Oct 28 '12 at 06:44
  • I was thinking about what you said and I don't think I can compare them correctly without an array because what if the tenth number I input from a file is smaller than the first number I take from the file? I can't compare them if I don't use an array. . . – user1742419 Oct 28 '12 at 06:53
  • Well that's where the trick lies. 1) Read one number from each file. 2) Compare them and write the smaller number to your output. 3) Read one more number but *only from the file that had the smaller number*. Repeat from step 2. Carry on until you have no more numbers. This way you are only ever holding two numbers, one from each file, so you only need two int variables, you don't need an array. That's the basic idea but there's a bit more detail to get right (like what you do when you have no more numbers in one file). – john Oct 28 '12 at 06:56
  • 1
    Kind of, but you are outputting both numbers, as I said output the smaller number only. You don't know if the bigger number should be output yet because there might be another smaller number in the other file (as you said in your previous comment). Also it's `while(inputFile>>num1 && inputFile2>>num2)`. – john Oct 28 '12 at 07:02
  • I just noticed nothing is actually being put out into the output file. I don't see why not. . . – user1742419 Oct 28 '12 at 07:08
  • Sorry my last comment was confusing. `while(inputFile>>num1 && inputFile2>>num2)` is not correct either. The important part about this (which I don't think you've grasped yet) is that each time round the loop you read and write *one number only*. Even though you are reading from two files simultaneously, you choose to read from one or the other depending on which number is smaller. Is that clear? Anyway enough, I have to go. – john Oct 28 '12 at 07:11
  • I don't think I do. I tried a different method and still don't think I get the result that I want. The updated code is once again above. I don't even get how to compare it to the last number in the output file. – user1742419 Oct 28 '12 at 07:18
  • I've updated my code above with a basic sketch. The code is not correct but I'll leave you to fix it. – john Oct 28 '12 at 07:22
  • I updated my code to what I've done so far, but not very much. The only question I have is why my code isn't outputting anything at all. I don't get any results. – user1742419 Oct 28 '12 at 19:06
  • I think the logic in your while loop is wrong, should be `while (!inputFile.eof() && !inputFile2.eof())`. I.e. go round the loop when you still have numbers from both files. One other thing, you are going to have work out what to do when you hit the end of file in one file but not in the other. I leave you to think about that, but you are going to have to add some more code to deal with that situation. – john Oct 28 '12 at 20:02
  • My professor is usually elaborate in that making a program more efficient would be extra credit, but right now i just want to make it work. And as of yet my output file crashes when I attempt to open it after changing my code to `while (!inputFile.eof() && !inputFile2.eof())` – user1742419 Oct 28 '12 at 23:25