Opening 2 Files Together And Comparing Them

Hello. I have a problem that I am frustrated with. I am writing a program that has to compare two separate files. If the strings in these files match, the output will read "true" and if they do not, the output will read "false."

I just cannot figure out how to open two files at once and compare them. I am able to figure out how to open one file and compare it with what a user inputs manually with a keyboard, but when I try to open two files and compare what is written in each, I get stuck. Any help is much appreciated. Thank you.
You can open the first file and save the lines as strings and make an array. And then open the second file and do the same. And then you can compare the two string arrays using a for loop.
Thanks for your reply. We haven't gone over arrays yet in my class. This is my code so far. I know it's totally screwed up, but I don't know how to fix it exactly. When I compile it, the .exe box just closes.

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
#include <iostream>
#include <fstream>
#include <cstdlib>


    using namespace std;d

    int main()
    {
       ifstream indata, indata2; // indata is like cin
       string num, num2; // variable for input value

      indata.open("example.dat"); // opens the file
       if(!indata) { // file couldn't be opened
          cerr << "Error: file could not be opened" << endl;
          
      indata2.open("example2.dat"); // opens the file
       if(!indata2) { // file couldn't be opened
          cerr << "Error: file could not be opened" << endl;
       
       }

      indata >> num;
       while ( !indata.eof() ) 
       
       indata2 >> num2;
       while ( !indata2.eof() ) {
       
       { 
             
       if (num1=num2)
         {
          cout<<"This order is valid."<<endl;
          }
      else 
      {
          cout<<"This order is invalid."<<endl;
      }
        
        {
       
       indata.close();
       cout << "End-of-file reached.." << endl;
       
       indata2.close();
       cout << "End-of-file reached.." << endl;
       
}
        system("PAUSE");
    return EXIT_SUCCESS;
}

  

Well first off..

You need to include the string library since you're using string.
And your using namespace thing should be std; not std;d
Your num1 should be num instead.

I'm not entirely sure how else to do it without arrays.. if you were to use an array you could do
1
2
3
4
5
	while(!file.eof()){
		getline (file,line);
		array[c] = line;
		c++;
	}


and then compare the array[] from the first file with the array[] from the second file in a for loop and comparing each line.. :-/ Sorry that's not much help.
Don't apologize. You're helping as much as you can :) And thank you for pointing out my errors! So, I'm assuming i would position that array code under both "while(!file.eof())" but assign them two different variables. Then just use these two variables for comparison in the for loop and that should output the correct answer?
closed account (1yR4jE8b)
No need for an array, you could use the getline() function and read each file line by line each into a seperate string and just compare those two strings using the compare() function until either you reach either EOF or two strings that are different.
Thanks so much for the reply. That has helped me. The only problem I have now is no matter what I have in both files, it still always reads out as "invalid." I put the same exact input in each file, but it always returns the same. Could someone tell me what I might have wrong?
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
#include <iostream>
#include <fstream>
#include <string>

    using namespace std;

    int main()
   {
 string str;
  ifstream file ("example.dat",ios::in);
  while (!file.eof())
  {
    str.push_back(file.get());
  }
 string str2;
  ifstream file2 ("example2.dat",ios::in);
  while (!file2.eof())
  {
    str2.push_back(file2.get());
  }
  

if (str == str2)
 {
 cout<<"This order is valid"<<endl;
}
else
{
cout<<"This order is invalid"<<endl;
}
  
  
  
system("pause");
  return 0;

}



Example2.dat is somewhat of a dictionary. It just contains random values such as ABCDEF ABCSDFLO ABCLD UIOP." Now Example1.dat contains part of those values like "ABCDEF ABCSDFLO." Now the problem is that I don't know how to compare them. The only way "Valid" will be printed it seems as if both files are exactly equal. I need so that even if Example1.dat only contains one value that is equal to Example2.dat, such as "ABCDEF" it will print "Valid."

This program is basically comparing the first file to a second file which is a "dictionary" and just telling you if the parts are "valid."
Last edited on
Try changing your code so that you have a bool value that keeps track of if a comparison is equal and rather than doing your if/else at the end, place them inside the while loop.

Right now what is happening is that your str and str2 variables have the entire example.dat and example2.dat files shoved inside them. For example, say example.dat contains

ACBD

and example2.dat contains

ADCD ADEA ADAA

What is happening in your current code is that str contains ACBD and str2 contains ADCD ADEA ADAA. So when it tries to compare str and str2 it returns false because they are not exactly the same.

From what I understand you want them to be storing only 4 letters in str2 at time, rather than the whole file at once. Then you should compare the two strings. If they are equal, set the bool value to true and break out of the while statement. If the comparison returns false just continue with the while statement.

Then at the end of the program do a check for if your "Found" bool is true or not, if it is true the text is present in both files, if false it is not.

I also reccommend using getline() (http://www.cplusplus.com/reference/string/getline/) rather than a combination of push_back() and get(), it's more straight forward and understandable. You may also want to change your
 
ifstream file ("example.dat",ios::in);

to
 
ifstream file ("example.dat",ios::in | ios::binary);


Generally you will always want to edit/read a file in binary mode, if you don't include the ios::binary you will end up picking up unwanted formatting data.
Thank you so much for your reply. You've really gone out of your way to help me, and I appreciate it. I just have a few more questions. I understand about comparing the strings with the bool values, but I don't understand how to continue with the while statement if the comparison returns false. What else would you include for conditions? Won't this still compare all values in the file as one single string, and not as individual values? Unless, is this what getline() is used for, so the values aren't being read in as one single string?

Sorry for so many questions. I've never dealt with comparing multiple files like this, and it is all new to me. All the help is much appreciated.

I understand about comparing the strings with the bool values, but I don't understand how to continue with the while statement if the comparison returns false. What else would you include for conditions?


The first thing you need to do is to change the way your program's loop statements are structured.
Rather than have two seperate while loops, I think a better way would be to use a nested loop structure. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

while(!file.eof() && !Found) // The "Is found true?" check is placed at both while statements to ensure that they both end as soon as a match is found.
{
	// From your post I assume the entries in the files are separated by spaces.
	getline(file, str, ' '); //Get the first string inside example.dat and store it.
	while (!file2.eof() && !Found) //This is one way to end our loop early, when a match is found it stops the loop
	{
		getline(file2, str2, ' '); //Get the first string inside example2.dat and store it
		if (str == str2)
		{
			Found = true; //This is our bool to check if a match was found.
		}
		else
		{
		//Do nothing, this else is not really needed, just doing it to show you.
		}
		str2.clear(); // erase str2 so we can check the next string in example2.dat
	}
	str.clear(); // erase str so we can check the next string in example.dat
}
//The only way for both loops to end is for the program to reach the end of both files, or for a match to be found. 


Won't this still compare all values in the file as one single string, and not as individual values? Unless, is this what getline() is used for, so the values aren't being read in as one single string?


Getline has a argument called the "delimiter" this character tells getline when to stop reading characters from your file. For example, say the separating character for your data is a space ' ', that means if you call getline(file_example,string_example,' ') getline will read characters and from file_example and store them in string_example until it finds a ' ' character.

If you have questions about the code just ask, I'll be more than happy to help.

Last edited on
Thank you so much again! You've helped more than you know. If you don't mind, I borrowed that code you provided. Here's what I have 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
#include <iostream>
#include <fstream>
#include <string>

    using namespace std;

    int main()
   {
  bool Found;     
 string str;
ifstream file ("example.dat",ios::in | ios::binary);

 string str2;
ifstream file2 ("example2.dat",ios::in | ios::binary);

while(!file.eof() && !Found) // The "Is found true?" check is placed at both while statements to ensure that they both end as soon as a match is found.
{
	// From your post I assume the entries in the files are separated by spaces.
	getline(file, str, ' '); //Get the first string inside example.dat and store it.
	while (!file2.eof() && !Found) //This is one way to end our loop early, when a match is found it stops the loop
	{
		getline(file2, str2, ' '); //Get the first string inside example2.dat and store it
		if (str == str2)
		{
			cout<<"This order is valid."<<endl;
            Found = true;//This is our bool to check if a match was found. 
            
		}
		else
		{
		cout<<"This order is invalid."<<endl;//Do nothing, this else is not really needed, just doing it to show you.
		}
		str2.clear(); // erase str2 so we can check the next string in example2.dat
	}
	str.clear(); // erase str so we can check the next string in example.dat
}

//The only way for both loops to end is for the program to reach the end of both files, or for a match to be found
  


  
system("pause");
  return 0;

}


I'm still trying to figure out what else I have to add. It seems to still return "invalid" sometimes, such as if I only have one value in the first file. The output i get is "This order is invalid. This order is invalid. This order is valid." Do I possibly have the cout statement in the wrong spot?
Last edited on
Well, the cout statements are meant to come after both while loops, kinda like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while(....)
{
     while(....)
     {}
}

if (Found)
{ 
     cout<<"This order is valid."<<endl;
}
else 
{
    cout<<"This order is invalid."<<endl;
}


What I was trying to show with that else statement is that for this program you don't care if it doesn't find a match while searching the files, instead you only care if it does find a match(If that makes sense... Not exactly awake here).

The cout statements were meant to come after the while loops have completed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	while (!file2.eof() && !Found) //This is one way to end our loop early, when a match is found it stops the loop
	{
		getline(file2, str2, ' '); //Get the first string inside example2.dat and store it
		if (str == str2)
		{
			
            Found = true;//This is our bool to check if a match was found. 
            cout<<"This order is valid."<<endl;
            
		}
		else
		{
		cout<<"This order is invalid."<<endl;//Do nothing, this else is not really needed, just doing it to show you.
		}
		str2.clear(); // erase str2 so we can check the next string in example2.dat
	}
	str.clear(); // erase str so we can check the next string in example.dat
}


What you showed above is what I have here, correct? For some reason when I try to read in a file with one incorrect value, it reads out "This order is invalid. This order is valid." If there is an incorrect value at all in the file, the output should read "This order is invalid." The if else statements look correct to me, so I don't know why the output is like this.

Here are my two files, by the way:

Example.dat: AAAAB CCC14 QQQQD ZZZZ4 ZE_B12 (This is the file that can be changed).

Example2.dat: AAAAC AAAAB AAAAD CCCC5 CCC14
BBBBE BBBBG ABCD4 _BCD5 _BC13
QQQE3 QQQ3R QQQQD ERFG8 ZZZZ4
ZE_B12 PPP14 REWD2
Last edited on
Wait, did you want the program to say the input is invalid each time it encounters a difference between the two files? Or only after it has scanned the entire file and found no matching entries?

And no, the two cout statements should be outside the while loops, the last part of the program should be set up similarly to how you first had it, just with Found being the conditional statement rather than the string comparison.

The idea behind this setup is this, when the program first starts it reads the first entry in the example.dat file, then it reads the first entry in the example2.dat file. It then compares them, if they are equal it says "Found it!" breaks out of both loops and the conditional statement
1
2
3
4
5
6
7
8
if (Found)
{ 
     cout<<"This order is valid."<<endl;
}
else 
{
    cout<<"This order is invalid."<<endl;
}


prints out
This order is valid
.

If the two strings are unequal it then loads the second string inside example2.dat and compares it with the first string of example.dat, it continues this processes until it reaches the end of example2.dat. At which point it will attempt to load the second string of example.dat(If it exists, if it does not exist then the loop should end) and start it all over again just using the second string of example.dat.

If the cout statements are placed inside the while loop like that then each time a comparison is made between the two strings, it will output "Invalid or "Valid" depending on if they match. I had thought you only wanted either "Invalid or Valid" to show up once which is why I had placed the if statements outside of the loops.

The full code, with a few unneeded things removed should look 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
while(!file.eof() || Found) // The "Is found true?" check is placed at both while statements to ensure that they both end as soon as a match is found.
{
	// From your post I assume the entries in the files are separated by spaces.
	getline(file, str, ' '); //Get the first string inside example.dat and store it.
	while (!file2.eof() || Found) //This is one way to end our loop early, when a match is found it stops the loop
	{
		getline(file2, str2, ' '); //Get the first string inside example2.dat and store it
		if (str == str2)
		{
			Found = true; //This is our bool to check if a match was found.
		}
		str2.clear(); // erase str2 so we can check the next string in example2.dat
	}
	str.clear(); // erase str so we can check the next string in example.dat
}

if (Found)
{ 
     cout<<"This order is valid."<<endl;
}
else 
{
    cout<<"This order is invalid."<<endl;
}


EDIT: Oh, also are you using newline characters in your Example2.dat? You may want to make sure that is consists of nothing but spaces and your data, otherwise getline will pick up those newlines and cause incorrect results.
Last edited on
I appreciate you posting the code. Basically, what the program should do is take whatever values are in example.dat and compare them to example2.dat. If it finds any errors in the comparison, the output will read "This order is invalid." But if all values match, it will read "This order is valid." I'm thinking this could should work for two of the same value also, such as if in example.dat, you have RTUOP RTUOP, or some other random value.

My only other question is why can I not get this new code to run correctly? All that outputs now is the .exe box with no output. I'm sorry for so many questions, but I really really appreciate all this help you've given a struggling student such as myself.

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
#include <iostream>
#include <fstream>
#include <string>

    using namespace std;

    int main()
   {
bool Found;
 string str;
ifstream file ("example.dat",ios::in | ios::binary);

 string str2;
ifstream file2 ("example2.dat",ios::in | ios::binary);



while(!file.eof() || Found) // The "Is found true?" check is placed at both while statements to ensure that they both end as soon as a match is found.
{
	// From your post I assume the entries in the files are separated by spaces.
	getline(file, str, ' '); //Get the first string inside example.dat and store it.
	while (!file2.eof() || Found) //This is one way to end our loop early, when a match is found it stops the loop
	{
		getline(file2, str2, ' '); //Get the first string inside example2.dat and store it
		if (str == str2)
		{
			Found = true; //This is our bool to check if a match was found.
		}
	   str2.clear(); // erase str2 so we can check the next string in example2.dat
	}
	str.clear(); // erase str so we can check the next string in example.dat
}

if (Found)
{ 
     cout<<"This order is valid."<<endl;
}
else 
{
    cout<<"This order is invalid."<<endl;
}


system("pause");
  return 0;

}
Last edited on
if you dont want to do more than simply compare the two files and check wether they are equal or not, and you have to read out your files anyways... why dont u simply traverse these files and check for something like:

pseudo code:

1
2
3
4
if(file1.get() == file2.get())
    continue; //and do something
   //...
break;


in a loop and abort if any unmatching characters are found...


öhm... and to answer your question...
carefully think about your loop condition... there is the error, while it runs forever...
Last edited on
So my problem I'm guessing is just in the loop? For some reason, the only way I can actually having anything print out on the screen is if I change while(!file.eof() || Found) to while(!file.eof() && Found) and while (!file2.eof() || Found) to while (!file2.eof() && Found).

Although, changing this still does not give me any sort of correct answer. All this program simply needs to do is compare whatever is saved in Example.dat with Example2.dat. If values match those in Example2.dat, output is "This order is valid." If even one of the values does not match, output is "This order is invalid." The user can save the values in any order they want to, so it needs to check each value individually instead of as a whole string.
sorry . i did not get it ..
Last edited on
Don't be sorry. It's not your fault. I just need some more perspective on why this isn't functioning correctly.
Topic archived. No new replies allowed.