• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

Repetitive Bug with C++ Program - Needs Help

kuphryn

Senior member
Hello!

I have been working a small program as a way to practice C++. Here is a quick sequence of how the program works and does:

- do-loop menu (2 choices: 1) read/write 2) exit)
- switch
case 1: read/write function
case 2: return 0;
- read/write function
1)enter name of read file
2)enter name of write file
3)fstream.open(read.....)
4)fstream.open(write...)
5)read.getline(temp, 50);
6)write << read // copy everything from data that were saved in memory from read file to write file

For some reason, the work only works: the first time it starts AND the user must enter the correct file name (file exists)

Case: If user enters the name of a file (always stalls upon read file, not write file) that exists the first time the program starts, it works. However, it works only once. Once the user returns to the mean menu and tries the same sequence, the program would say the "file" does not exists even if the user enters the exact same file name. I have tried cout the array used to store the file name. It holds the correct file name each time.

Case: If user enters a file name that does not exists, the program would not work, period.

Does anyone know what is going on? I have tried using dynamically allocated memory to make sure the file name is stored clean each time. I have tried to use different technique like trying different loops and if/else. Nothing has worked. Is there something static about the fstream?

Thanks,
Kuphryn


 
Are you checking the return value of open?
Are you closing the file when you're done?

It would also be easier to help debug if you could post the code, not a big deal if you don't want to though.
 
Nothinman is correct, it would help to see the actual source, without it we are just guessing at what the errors might be.

Check what mode flags you are using for each of the opens...if you use ios::nocreate, the open will fail if the file does not exist...do not use this flag for the writefile. If you use ios::noreplace, the function will fail if the file does exist...do not use this flag for the readfile. If you use ios::trunc, the file will be erased if it already exists...do not use this flag for the readfile.

The constructor can not return a status to indicate an error, and the fstream:: open() method does not return a status either. In order to know whether the open was OK or not, use the ios::good() method (fstream is a subclass of ios, so it inherits this method).

fstream readfs( "readfile", ios::in );

if ( readfs.good() )
{
cout << "readfile opened OK" << endl;
} else {
cout << "readfile open failed" << endl;
}


fstream writefs( "writefile", ios:: out ); // edited to stop face from appearing, remove extra space between "ios::" and "out"

if ( writefs.good() )
{
cout << "writefile opened OK" << endl;
} else {
cout << "writefile open failed" << endl;
}


Once you know that you have opened both files OK, you can work on fixing the input and output calls to work correctly.
It probably only works the first time because you are not closing the files and destroying the fstream objects. The second time through, the file is already open and locked, so the open fails.
 
The code is quite long (three classes, main() and three functions). There is no way I can post everything. This is what I suspect:

Yes. Both the read file and the write files are closed right after EOF(), which is in a class.

input.eof() <--- I use that member function as a sign to close files.

The only thing I could think of is that fstream is declared in main(), however, the actually openning of the file is done in a class. I pass fstream from main() to a class member function which opens it as well as check file.fail() (both for read file and another member function that opens and check the write file. Lastly, I use try/catch algorithms to check file.fail(). For example, if read.fail() or write.fail(), the member class throws an empty class. In the main(), there is a catch that looks for the throw. I do not know if that has anything to do with the repetitive program bug. I have tried disabling try/catch, but I saw the same response, so i enabled it. I believe either something is not right with the dynamically allocated memory, pointers or loops. I have no idea what. If anyone wants me to post a part of the code, please request. Please include exactly what you want to see.

This is becoming exhausting. I know the bug is something really simple, but I cannot figure out the reason. I would almost have to speak to an experience programmer in person.

Please reply if you have any idea on passing fstream (for both read file and right file) via reference (&) to class member function. Yes, the member class closes both the read file and the write file before the program ever returns to main(). Once it returns to main() and repeat at the beginning since it is in a do-while loop, the program never work right again.

Thanks,
Kuphryn


 

Post the section where you prompt for the file names and the section where you open the files.

Don't get discouraged, you have been looking at this code for quite a while, probably fixed a lot of bugs already, but now there is just something wrong, but you keep overlooking it...either just because it is so obvious, or because it is actually quite complex and hidden. This happens to me all the time...usually by calling over another developer and starting to explain the problem and the code to them, I stop overlooking the small details I ignored earlier, and suddenly find the problem.

If the fstream objects are only created in main(), but all of the i/o is done within a class, wouldn't it make more sense to have them as members of that class?

If you need to pass an fstream reference to a method, declare the method as:
MyClass::MyMethod( fstream& rFStream )
{
... // Use rFstream as if it were local to this method or class, e.g. rFStream.open()
}

and call the method as:
...
MyClass myObject;
fstream readfile;

myObject.MyMethod( readfile );
...

 
Thanks.

The reasons I declare fstream for both the read file and write file is because I pass them to *two* classes, not one. In other word:

1) main() declare fstream readFile, fstream writeFile
2) classA *opens/closes* and read/write to fstream readFile & writeFile
3) classB *closes only* and read/write to fstream

Maybe something is not right in the above logic.

I will post the section you want in a few hours. I have to go to class.

Kuphryn
 
Here is the section that asks the user to enter the name of the read file and the write file. Notice that the read file and the write file are in two seperate sections.

Code:
// Definition of function filterIP
void filterIP(bool &veri1, fstream &source, fstream &output, AddIP &aIP, DNS &dns)
{
	char opt;
	do
	{
		char *SFile = NULL;
		SFile = new char[15];
		veri1 = true;                          
		cout << "\nEnter source file: ";
        cin >> SFile;
        cin.ignore();
		try
		{
			aIP.getSFile(source, SFile);
		}
		catch(AddIP::NoFile)
		{
            cout << "\nERROR: File \"" << SFile << "\" not found!\n"
		         << "\nPress (C)ontinue or (E)xit: ";
		    cin >> opt;
		    cin.ignore();
		    while (toupper(opt) != 'C' && toupper(opt) != 'E')
		    {
			    cout << "\nInvalid choice. Press (C)ontinue or (E)xit: ";
			    cin >> opt;
			    cin.ignore();
		    }
            if (toupper(opt) == 'E')
		        exit(0);
	    	else
                veri1 = false;
        }		
		delete [] SFile;
	}while(!veri1);
	do
	{
		char *OFile = NULL;
		OFile = new char[15];
		veri1 = true;
		cout << "\nEnter output file: ";
        cin >> OFile;
        cin.ignore();
        try
		{
			aIP.getOFile(output, OFile);
		}
		catch(AddIP::NoFile)
		{
            cout << "\nERROR: File \"" << OFile << "\" not found!\n"
			     << "Do you want to create an output file? (Y/N): ";
		    cin >> opt;
		    cin.ignore();
		    while (toupper(opt) != 'N' || toupper(opt) != 'Y')
            {
		        cout << "\nInvalid choice. Press (C)ontinue or (E)xit: ";
			    cin >> opt;
			    cin.ignore();
		    }
            if (toupper(opt) == 'Y')
		    {
			    output.open(OFile, ios::out | ios::app);
			    break;
		    }								  
		    else
		        veri1 = false;
        }		
		delete [] OFile;
	}while(!veri1);
	veri1 = false;
	cout << "\nScanning source file...\n"
         << "Writing IP to output file...\n\n";
    aIP.seekIP(source, output);
	cout << "\nProgram has reached the end of source file. Press any key to"
         << " continue";
	cin.get();
	system("cls");
}

Here are the sections that opens the read file and write file:

Code:
void AddIP::getSFile(fstream &source, char *sFile)
{
	source.open(sFile, ios::in);
	if (source.fail())
		throw NoFile();
}

void AddIP::getOFile(fstream &output, char *oFile)
{
    output.open(oFile, ios::out | ios::app);
	if (output.fail())
		throw NoFile();
}

Do you see anything that could cause the repetive "file does not exists" problem even if the user enter a file name that does exist? Remember, the program works perfect when: 1)program first starts AND 2)user enters correct file name

Otherwise, the program either says that the files not exist. I have tried cout the file name right before "source.open" and "output.open." The stored value are valid. Something is keeping it from openning. Maybe "source.fail()" and "output.fail()" do not work right.

Kuphryn
 
Great news. I figured out the problem. What I am about to say is based on personal experience. Whether it is true for everything is arbitrary.

=> passing fstream to a class member function *while in a loop* (do-while, while-loop and for-loop) could potentially produce problems.

From my experience a variable must be "refresh," preferably at the beginning of the loop, if you want the variable to have *the same logic* the second reiteration and beyond.

Example:

int num = 0;

do
{
cout
<< "1) Yes\n"
<< "2) No\n"
<< "3) Exit"\n\n";
cin >> num;
}while(num < 1 || num > 2)

In the example above, the program will work the first time around, but it will act weird the second time around. For example, let say the above do-while loop is in another loop and the loop above is just to ensure the user enters a valid option. Let say the user enters "1," the program outs "Okay" and then returns to the loop above since the loop above is inside another loop. When the program returns the second time around, "num" would still hold the value "1" and the program would open "Okay" no matter what the user enters.

The statement above is probably due to me not using some type of ignore command. Nonetheless, it was something I noticed.

The way I would get around something like that is I would initialize "num" first in the loop. That was how I fix the fstream problem. Rather than declaring fstream in main(), now I declear:

fstream source, output;

right in the function where I use the do-loop. I do not like the way it is right now. For every function that uses the fstream as well as class member function with fstream as one of its parameters, I have declares instances of fstream as instances of the class whose member function use called with fstream parameter. Nonetheless, it does undoubtedly fix a major bug in the program.

Maybe someone have a slick way to get around that. Remember, the problem is occurs only if there is some type of loop.

Kuphryn

P.S. Special thanks to CodeJockey for the word of encouragement. Thanks!
 
Back
Top