So i have an assignment to take two input files and combine into one output file in alphabetical order.

Example

File1.txt
Adam B Exam 80
Jane D Exam 87
Tom G Exam 77

File2.txt
George S Exam 99
Bob C Exam 67

Output.txt
Adam B
Bob C
George S
Jane D
Tom G

I have tried for hours to get this to work i think i might be on the correct path.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int openFiles (string inFile1, string inFile2, string outFile1);
void mergeFiles (string inFile1, string inFile2, string outFile1,ifstream& File1,ifstream& File2,ofstream& outFile);


int main()
{
		string inFile1,  inFile2,  outFile1;
		ifstream File1;
		ifstream File2;
		ofstream outFile;
		
		cout <<"Enter input file 1:"<<endl;
		cin >>inFile1;
		cout <<"Enter input file 2:"<<endl;
		cin >>inFile2;
		cout <<"Enter output file 1:"<<endl;
		cin >>outFile1;

openFiles (inFile1,  inFile2,  outFile1);	
mergeFiles (inFile1, inFile2,  outFile1, File1, File2, outFile);


return 0;

}

void mergeFiles (string inFile1, string inFile2, string outFile1,ifstream& File1,ifstream& File2,ofstream& outFile)
{	
	File1.open(inFile1.c_str());
        File2.open(inFile2.c_str());
        outFile.open(outFile1.c_str());

string File1_fName, File1_lName,exam1,examGrade1;
string File2_fName, File2_lName,exam2,examGrade2;

 
		
File1 >>  File1_fName >> File1_lName>>exam1>>examGrade1;
File2 >>  File2_fName >> File2_lName>>exam2>>examGrade2;

while (!File1.eof() && 	!File2.eof())
{

	if ((File1_fName<=File2_fName ))
        {
		outFile << File1_fName << '\t'<< File1_lName << endl;
		File1 >>  File1_fName >> File1_lName>>exam1>>examGrade1;	
				
		}
		else
		{
			outFile << File2_fName << '\t'<< File2_lName << endl;
			File2 >>  File2_fName >> File2_lName>>exam2>>examGrade2;
		}
				if (File1.eof() )
				{
					while (!File2.eof())
					{
					outFile << File2_fName << '\t'<< File2_lName << endl;
					}
				}
			
			
				if (File2.eof() )
				{
					while (!File1.eof())
					{
					outFile << File1_fName << '\t'<< File1_lName << endl;
					}
				}
			
			

		File1.close();
		File2.close();
		outFile.close();
		}
	
}



int openFiles (string inFile1, string inFile2, string outFile1)
{
	ofstream outFile;
	outFile.open (outFile1.c_str());

	if (outFile.fail())
	{
	cerr <<  "ERROR: cannot open " <<outFile1
		 <<  " for output." <<endl;
	return EXIT_FAILURE;
	}
	
	
	ifstream File1;
	File1.open (inFile1.c_str());

	if (File1.fail())
	{
	cerr <<  "ERROR: cannot open " <<inFile1
		 <<  " for input." <<endl;
	return EXIT_FAILURE;

	}
	
	ifstream File2;
	File2.open (inFile2.c_str());

	if (File2.fail())
	{
	cerr <<  "ERROR: cannot open " <<inFile2
		 <<  " for input." <<endl;
	return EXIT_FAILURE;
}
}

Recommended Answers

All 7 Replies

you need to put the information in the input files into one vector, then sort the vector, and finally write the vector contents to the output file. From the example files you posted this will be fairly simple. You can use std::sort to sort the vector after reading from the input files.

Also, do not use eof() because they don't work the way you would expect.

vector<string> theList;
string line;
while( getline(File1, line )
{
   theList.push_back(line));
}
while( getline(File2, line) )
{
   theList.push_back(line));
}
// sort the vector
sort(theList.begin(),theList.end());
// now write the vector out the the output file

We have not covered vectors on the class that i am in right now... my instructor said that we should use the getline or the way that i was doing it...if anyone could show me how to retrieve the data using getline i might can change up what i have...or why the way i currently have it is not working...thanks

The algorithm you was using may or may not work, depending on the contents of the two input files. It might work if both input files are already in sorted order. If the lines are scrambled in each file then your algorithm can not and will not work. The only way to do it correctly is to read both files into a single array, whether vectors or c-style character arrays, then sort them and write to the final output file

do you know about c-style character arrays of pointers yet ? You can substitute vector for an array of c-strings then sort the strings using some algorithm such as qsort() or a bubble sort (there are lots of other sort options too).

If this is an exercise in "merge", then shouldn't all the input files be sorted already ?

Try this :

#include<iostream>
#include<string>
#include<fstream>
using namespace std;

int main()
{
	int ndatamax=100;
	string line[ndatamax],linetemp;
	int i=0;
	int ndata;
	ifstream myfile;
       	myfile.open("data.txt");

	if(myfile.is_open())
	{
		while(!myfile.eof())
		{	
		getline(myfile,line[i]);
		i++;			

		}	
	}
	ndata=i-1;
//	One way for sorting
	for(i=0;i<ndata;i++)
	{
		for(int j=i+1;j<ndata;j++)
		
		if( line[i]>line[j]) { linetemp=line[i]; line[i]=line[j];line[j]=linetemp;}
	}
		

//	new sequence
	for(i=0;i<ndata;i++)
	{
		cout<<line[i]<<endl;
	}
	
	
}

>int ndatamax=100;
>string line[ndatamax]
C++ requires array sizes to be constant.

>while(!myfile.eof())
*sigh* It seems we have to tell everyone that this is the wrong way to use the eof member function. The eofbit is only set after an attempt has been made to read from the stream and failed. This means that the body of your loop will execute once more than expected. For example:

#include <cstddef>
#include <fstream>
#include <iostream>
#include <string>

void create_file ( const char *filename, const char *contents )
{
  std::ofstream out ( filename );

  if ( out )
    out<< contents;
}

int main()
{
  const char *filename = "test.txt";

  create_file ( filename, "Line1\nLine2\nLine3\n" );

  {
    std::ifstream in ( filename );
    std::string line;
    std::size_t n = 0;

    if ( in ) {
      while ( !in.eof() ) {
        std::getline ( in, line );
        ++n;
      }

      std::cout<<"The file has "<< n <<" lines\n";
    }
  }

  {
    std::ifstream in ( filename );
    std::string line;
    std::size_t n = 0;

    if ( in ) {
      while ( std::getline ( in, line ) )
        ++n;

      std::cout<<"The file has "<< n <<" lines\n";
    }
  }
}

Even worse, the content of the file will affect the result of the broken loop. If you change "Line1\nLine2\nLine3\n" to "Line1\nLine2\nLine3", the first loop will result in 3 instead of 4, but the second loop will still produce 3. The rule of thumb is that the eof member function (or feof in C) should never be used to drive an input loop. It's just too easy to screw up.

>ndata=i-1;
With your broken loop, this becomes an intermittent bug.

>for(int j=i+1;j<ndata;j++)
>if( line>line[j]) { linetemp=line; line=line[j];line[j]=linetemp;}
Just for future reference, I think this formatting is evil. First, multi-line blocks should never be scrunched up onto a single line. Second, whitespace is your friend, so the conditional should look like this:

if ( line[i] > line[j] ) {
  linetemp = line[i];
  line[i] = line[j];
  line[j] = linetemp;
}

Next, when you format the conditional in an easier to maintain fashion, the seemingly one line loop suddenly has five lines in the body:

for ( int j = i + 1; j < ndata; j++ )
  if ( line[i] > line[j] ) {
    linetemp = line[i];
    line[i] = line[j];
    line[j] = linetemp;
  }

Just because a compound statement counts as a single statement doesn't mean that omitting braces for this loop is a good idea. In fact, not using braces is a pretty bad idea in general except when you have a very trivial single line body. That way it's immediately obvious that braces need to be added with more lines. This is much better:

for ( int j = i + 1; j < ndata; j++ ) {
  if ( line[i] > line[j] ) {
    linetemp = line[i];
    line[i] = line[j];
    line[j] = linetemp;
  }
}

In fact, a good guideline to follow is that every block has braces.

Thanks NArue.. I never realized that thing before.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.