I am working on the last part of an encryption/decryption program and have to compare the original input file to the final output file character by character to ensure that they are identical. I have tried a few different ways to do this to no avail. When I tried this code:

inputFile.get(inputChar);
outputFile.get(outputChar);

while(inputFile.good() && outputFile.good())
{
	if(inputChar != outputChar)
         {
	         cout << "The files are not identical\n\n\n";
		return 1;
	}

		inputFile.get(inputChar);
		outputFile.get(inputChar);
}

if(inputFile.eof() && outputFile.eof())
{
	cout << "The files are identical.\n\n\n" << endl;
}
	else if(inputFile.eof() || outputFile.eof())
	{
		cout << "One of the files has ended before the other, they are not identical." << endl;
	}

It seems to go straight to telling me that one of the files has ended before the other and that they are not identical. I also tried:

while (inputFile.get(inputChar)) 
{
         if (!outputFile.get(outputChar) || (inputChar != outputChar)) 
	{
		cout << "The files are not identical" << endl;
	}
}
	if (!outputFile.get(outputChar))
	{
		cout << "The files are identical" << endl;
	}
		else
		{
			cout << "The files are not equal";
		}*/

And this is also telling me that they are not identical when I run the program. The two files are exaclty the same size, there is only one character in each of them (that's what I am testing with at the moment, just the letter a in each file), there is no extra characters or spaces in either of the files, the only difference between the two is the name of the file. Does anyone have any ideas, suggestions, or examples as to how to do this correctly, or why it might be telling me that they are not identical when in actuality it seems that they are to me. I will post the full program code if need be, just ask if you need to see if for anything. Thanks in advance for your help.

Recommended Answers

All 10 Replies

cout<<sizeof(original file)<<endl;
cout<<sizeof(new file)<<endl;
cout<<sizeof(original file)<<endl;
cout<<sizeof(new file)<<endl;

I just tried that, added that to my code at the end and replaced the original file and new file with the input and output files and the sizeof comes up the same for both. If this is what you were getting at.

cout<<sizeof(original file)<<endl;
cout<<sizeof(new file)<<endl;

The sizeof() operator gets the size of the variable(class) in bytes, not the size of the file.


This seems to work for me:

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

enum FileResult {
	Identical,
	NotIdentical,
	CantOpen
};

FileResult FilesIdentical(string f1, string f2)
{
	FileResult res;
	ifstream file1(f1.c_str(), ios::in);
	ifstream file2(f2.c_str(), ios::in);
	if(!file1 || !file2)
	{
		res = CantOpen;
		return res;
	}
	
	while(!file1.eof() && !file2.eof())
	{
		char a = file1.get();
		char b = file2.get();
		if(a != b)
		{
			res = NotIdentical;
			return res;
		}
	}

	res = Identical;
	return res;
}

// Test
int main()
{
	FileResult result = FilesIdentical("a.txt", "b.txt");
	switch(result)
	{
		case CantOpen:
		cout << "Can't Open Files!" << endl;
		break;

		case Identical:
		cout << "The files are identical" << endl;
		break;

		case NotIdentical:
		cout << "The files are not identical" << endl;
		break;
	}

	return 0;
}

I'll throw in some debugging hints rather than analyze the code itself.

You need to find out WHERE and HOW these files are considered different. To that end, for each itereation through the loop, display wehn the test PASSES, not just when it fails. It may fail immediately after reading the first character. It may always fail at the very end. Take out the testing code later, but you need more thorough printouts.

Something like this:

File 1: abcdef
File 2: abddef


Output:
File 1 character 1='a'(Ascii=97)
File 2 character 1='a'(Ascii=97)
They match
File 1 character 2='b'(Ascii=98)
File 2 character 2='b'(Ascii=98)
They match
File 1 character 3='c'(Ascii=99)
File 2 character 3='d'(Ascii=100)
They do not match

It'll help you nail down EXACTLY where the problem is.

I'll throw in some debugging hints rather than analyze the code itself.

You need to find out WHERE and HOW these files are considered different. To that end, for each itereation through the loop, display wehn the test PASSES, not just when it fails. It may fail immediately after reading the first character. It may always fail at the very end. Take out the testing code later, but you need more thorough printouts.

Something like this:

File 1: abcdef
File 2: abddef


Output:
File 1 character 1='a'(Ascii=97)
File 2 character 1='a'(Ascii=97)
They match
File 1 character 2='b'(Ascii=98)
File 2 character 2='b'(Ascii=98)
They match
File 1 character 3='c'(Ascii=99)
File 2 character 3='d'(Ascii=100)
They do not match

It'll help you nail down EXACTLY where the problem is.

I completely understand what you mean here, but I am having a problem with it even going into a while loop to be able to test it, here is what I have right now:

inputFile.open(inputFileName, ios::in);
outputFile.open(outputFileName, ios::in);

char a;
char b;

cout << "This is right before the while loop" << endl;
while(!inputFile.eof() && !outputFile.eof())
{
	cout << "this is right inside of the while loop" << endl;
	inputFile.get(a);
	outputFile.get(b);
	cout << "Ch. A: " << a << "   (Ascii = " << int(a) - int('0') << ")" << endl;
	cout << "Ch. B: " << b << "   (Ascii = " << int(b) - int('0') << ")" << endl;
		
	if(a != b)
	{
		cout << "Characters do not match" << endl;
	}

	if(a == b)
	{
		cout << "Characters match" << endl;
	}
	cout << "\n\n";
	cout << "this is at the end of the while loop" << endl;
}
cout << "this is right after the while loop" << endl;

Basically, I'm just trying to test everything with that, it prints out stating that it is right before the loop, then prints that it is right after the loop, nothing in the loop gets printed or read and I'm not sure why. It is set to go in the loop if both files are not EOF, I have closed the files previously and just re-opened right before this loop, when they re-open does the pointer in the file go back to the beginning automatically, I would think it does but I honestly do not know. I don't see where I am doing anything wrong here, but the loops that I posted in the original post did the same thing, they would not enter the while loops, I've never had a problem like that before.

>>but I am having a problem with it even going into a while loop to be able to test it

That's part of the testing. You've narrowed down the problem considerably. It never gets into the loop.

>> I have closed the files previously and just re-opened right before this loop, when they re-open does the pointer in the file go back to the beginning automatically, I would think it does but I honestly do not know.

I would definitely not assume anything after I have opened and closed a stream, then reopened it.

If you want to reopen a file and start from the beginning, check whether it's closed first, and RESET the stream by clearing any bad/eof/fail bits if it's in a failed state.

http://www.cplusplus.com/reference/iostream/ios/clear/

Check to make sure the stream is good and check to make sure it's open and check to make sure it's not in an eof state. Checks, even redundant ones, never hurt.
http://www.cplusplus.com/reference/iostream/ifstream/is_open/
http://www.cplusplus.com/reference/iostream/ios/good/
http://www.cplusplus.com/reference/iostream/ios/eof/

You probably won't need to, but you can always set the pointer manually:
http://www.cplusplus.com/reference/iostream/istream/seekg/

and it, again, never hurts to check to make sure you're at the begginning of the file.

http://www.cplusplus.com/reference/iostream/istream/tellg/

I doubt you'll need all or even most of these, but between them, you should be able to verify the stream is good and fix it if it isn't.

You can't use .eof() in this manner. You don't hit EOF until you actually try to read past end, not when you read the last character. Therefore, you will go through your loop the final time after reading bogus data.

Read the first characters before the loop. Then read the next characters at the end of the loop.

>>but I am having a problem with it even going into a while loop to be able to test it

That's part of the testing. You've narrowed down the problem considerably. It never gets into the loop.

>> I have closed the files previously and just re-opened right before this loop, when they re-open does the pointer in the file go back to the beginning automatically, I would think it does but I honestly do not know.

I would definitely not assume anything after I have opened and closed a stream, then reopened it.

If you want to reopen a file and start from the beginning, check whether it's closed first, and RESET the stream by clearing any bad/eof/fail bits if it's in a failed state.

http://www.cplusplus.com/reference/iostream/ios/clear/

Check to make sure the stream is good and check to make sure it's open and check to make sure it's not in an eof state. Checks, even redundant ones, never hurt.
http://www.cplusplus.com/reference/iostream/ifstream/is_open/
http://www.cplusplus.com/reference/iostream/ios/good/
http://www.cplusplus.com/reference/iostream/ios/eof/

You probably won't need to, but you can always set the pointer manually:
http://www.cplusplus.com/reference/iostream/istream/seekg/

and it, again, never hurts to check to make sure you're at the begginning of the file.

http://www.cplusplus.com/reference/iostream/istream/tellg/

I doubt you'll need all or even most of these, but between them, you should be able to verify the stream is good and fix it if it isn't.

Well, I managed to get it working, it was as simple as putting a .clear for each file after I opened them, then taking WaltP's advice and getting the first characters before going into the while loop then getting the next characters at the end of the while loop. But I tested it with quite a few scenarios and it is working now. Now just a couple small questions and I'll mark this solved.

I was curious which is better to use .eof or .good, and should I use .good instead of .eof in the case of this program?

Also, what is a good way of stopping the program to exit, a lot of people use system("pause") but I heard it's bad to use that, and I used to use _getch() from conio.h, but I've heard that's not an ideal way to do it either, so what is a good acceptable way to end the program?

And thank you so much for your help with this program, it would have taken me forever to get this done without some kind of nudge in the right direction.

You're welcome. Regarding pausing the program, try this thread and the links in it. The concensus seems to be: clear stdin using the "ignore" command, then use cin.get().

http://www.daniweb.com/forums/thread126418.html

Not sure if this link from WaltP is already in the trhead, but if not, check this one out.

http://www.gidnetwork.com/b-61.html


Using eof() is often advised against because, as mentioned, the steam won't hit the end of the file after it reads the last piece of data, but will go one read attempt beyond. It's not so much a matter of what to use, but using it correctly, but I suppose using good() might be better than using eof() because it checks more things. eof() is fine if you have some understanding of what it does, but it's a bit counterintuitive so often people use it incorrectly. But if it ain't broke, don't fix it!

You're welcome. Regarding pausing the program, try this thread and the links in it. The concensus seems to be: clear stdin using the "ignore" command, then use cin.get().

http://www.daniweb.com/forums/thread126418.html

Not sure if this link from WaltP is already in the trhead, but if not, check this one out.

http://www.gidnetwork.com/b-61.html


Using eof() is often advised against because, as mentioned, the steam won't hit the end of the file after it reads the last piece of data, but will go one read attempt beyond. It's not so much a matter of what to use, but using it correctly, but I suppose using good() might be better than using eof() because it checks more things. eof() is fine if you have some understanding of what it does, but it's a bit counterintuitive so often people use it incorrectly. But if it ain't broke, don't fix it!

Alright, well, that gives me a pretty good idea of what to use to exit the program properly, I hated the idea of using something like system("pause"), etc.. So now I have something more to go by. Since my program is working fine at the moment, gives no errors and returns all of the correct information, then I will leave it with .eof for the moment being. I will take note of .good for future use and will likely try to avoid .eof any time that I can get away with it because I do understand the problem with using .eof in certain situations and how .good would be a better alternative, which was why I asked. Thank you for your response and all of the help, have a great day. Marking thread as solved.

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.