Hello, I have a program that I'm writing and it seems to just stop. I've looked at the code and I can't seem to figure it out. This is for a class, so please don't just fix it, but please tell me how to go about fixing it, I want to learn this so it's important that I can learn it, but any suggestions would be appreciated!!!

This program is reading a txt file and echoing back three lines if it matches what the user inputted.

Here is the code:

#include <iostream>
#include <fstream>
#include <cstring>
#include <cctype>
using namespace std;
  
 
int main() {
	//Local variables
	char line0[256], line1[256], line2[256], line3[256]; // Lines used for class, date, and assignment
	char fname[256];
	char request[25];
	
	//Welcome message and file request
	cout << "Welcome to the program, this program will read assignments from a file for you based on what class you're looking for.  But first, what file would you like to look in?" << endl;
	cin.get(fname, 256, '\n');
	cin.ignore();
	
	//Prompt for the class they are looking for and store it in request
	cout << "What class are you looking for?" << endl;
	cin >> request;
	cin.ignore();
	cout << endl;
	
	ifstream content; //name for file stream content
	content.open(fname); //Open the file that the user requested under codename content
	
	if(!fname) { 
		//If the file failed to open, display an error message
		cout << "There was an error opening the file." << endl;
	}
	
	// if the file opened fine, continue
	else { 
		content.get(line0, 256, '\n');
		char ch = content.get();
		int i;
		i = 1;
		
		while (!content.eof()) {
			content.get(line2, 256, '\n');
			ch = content.get();
			content.get(line3, 256, '\n');
			ch = content.get();
			content.get(line1, 256, '\n');
			ch = content.get();
			
			//stops endless loop
			while (content.peek()=='\n') { 
				content.ignore();
			}
			
			// if the request is same as the content, then echo it
			if ((strcmp(line3, request) ==0) || (strcmp(line2, request) ==0) || (strcmp(line1, request) ==0) || (strcmp(line0, request) ==0)) { 
				if (i = 1) {
					cout << line0 << endl;
					cout << line2 << endl;
					cout << line3 << endl;
				}
				else {
					cout << line1 << endl;
					cout << line2 << endl;
					cout << line3 << endl;				
				}
			}
			++i;
		}

	}
	
	return(0);
}

C++ streams have to be treated with a little respect. You have assumed that the only error condition is eof. That might be true if you were reading into values BUT you decided to use peek. Peek CAN set fail().
You do not check eof BEFORE the peek so when you are at eof THEN you go to fail.

If you put replace while (!content.eof()) with while (content.good())) . The program does not sit in an infinite loop.

BUT WHY did you not just use your debugger???? I mean that is what they do so well, run the program and interrupt it and see what has gone wrong, maybe step through a few commands.

Finally, look up getline in the istream class. It will help make you program a little tidier.

If you put replace while (!content.eof()) with while (content.good())) . The program does not sit in an infinite loop.
.

I can't, our instructor wants us to use the end of file method to check the text file. The loop seems to run through the while loop once, then stops, but if I search for anything beyond the first three lines, it won't echo it, so I'm thinking the problem is with the if statements, but I'm not 100% sure...

I can't, our instructor wants us to use the end of file method to check the text file. The loop seems to run through the while loop once, then stops, but if I search for anything beyond the first three lines, it won't echo it, so I'm thinking the problem is with the if statements, but I'm not 100% sure...

Your PROBLEM is that you are not using a debugger. I cannot state that too strongly. If you are on Linux then try ddd. If you are on windows, there must be good free debugger, don't do anything until you have found and installed one. If need be ask here or anywhere else [Start a new thread]. This is why you do not know what is causing the problem.

My mistake was not seeing that your code can get to the fail state in a number of other ways. (i) If you have a blank line (just '\n') AND it is not on the three line boundary then you can hit the fail because of the function get() will set that when if gets no characters.

Solution:

(i) use getline
(ii) Bin your peek and the whole of that while loop.
(iii) Never write [icode]!content.eof()[/icode] ever again. (unless you are separately handling fail )

Alternatively:

you can use the code you have written without the ch=get();, but you need to use your ignore loop after EACH read.

The second solution is nothing but ugly.

our instructor wants us to use the !variable.eof() so how would I use it without messing things up? Also, I tried the .good(), and it just ran through the file once, didn't actually loop. Second, I used a debugger, it came back with no errors. Which is why I came onto here, for help. I took out the peek, nothing happened. The getline(), I will try that and see if things work better! Thanks.

our instructor wants us to use the !variable.eof() so how would I use it without messing things up? Also, I tried the .good(), and it just ran through the file once, didn't actually loop. Second, I used a debugger, it came back with no errors. Which is why I came onto here, for help. I took out the peek, nothing happened. The getline(), I will try that and see if things work better! Thanks.

I trust you have stepped through execution line by line to see the exact moment it goes to pot?

p.s tell you lecturer to stop teaching bad practise.

Chris

Ok Now you have updated your code. Post what you have and the error message. However, I will be seeing getline :S , won't I?

Then tell us who many times it looped through etc, and the output
and the line that it failed to read from your file.

I am afraid I concur with Freaky_Chris, you didn't use a debugger, or you would have known that you hit the fail state when you got to the
while in the first post. Debuggers DONT "come back with no errors",
they help you step through the code, and see the state of variables/classes/memory at instants in the execution sequence.

Here is the new code, its now just exiting the program without displaying anything. If you want to, you all can continue helping me, but I'm afraid I'm too much of a newbie and need to actually go see the tutor or I'm going to go insane....

Here is the updated code block:

content.getline(line0, 256, '\n');
		char ch = content.get();
		int i;
		i = 1;
		
		while (!content.eof()) {
			content.getline(line2, 256, '\n');
			ch = content.get();
			content.getline(line3, 256, '\n');
			ch = content.get();
			content.getline(line1, 256, '\n');
			ch = content.get();
			
			// if the request is same as the content, then echo it
			if ((strcmp(line3, request) ==0) || (strcmp(line2, request) ==0) || (strcmp(line1, request) ==0) || (strcmp(line0, request) ==0)) { 
				if (i <= 1) {
					cout << line0 << endl;
					cout << line2 << endl;
					cout << line3 << endl;
				}
				else {
					cout << line1 << endl;
					cout << line2 << endl;
					cout << line3 << endl;				
				}
			}
			else {
			}
			++i;
		}

This is the output from the debugger I used:

'programsix.exe': Loaded 'C:\Users\Josh\Documents\Visual Studio 2008\Projects\programsix\Debug\programsix.exe', Symbols loaded.
'programsix.exe': Loaded 'C:\Windows\System32\ntdll.dll'
'programsix.exe': Loaded 'C:\Windows\System32\kernel32.dll'
'programsix.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.1_none_bb1f6aa1308c35eb\msvcr90d.dll'
'programsix.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.1_none_bb1f6aa1308c35eb\msvcp90d.dll'
The thread 'Win32 Thread' (0x1714) has exited with code -1073741510 (0xc000013a).
The program '[7528] programsix.exe: Native' has exited with code -1073741510 (0xc000013a).

Like I said though, I have no clue what that means...

Your basic problem is that some of your code can encounter errors, but you're not testing for them.

What do you expect a sequence of calls to content.get() (with different argument types) to do if one of the previous calls encounters an error? And, if an error occurs, what do you expect the contents of line1, line2, etc to be?

If your instructor is insisting your code loop based on content.eof() s/he should be summarily shot for encouraging bad practice.

Well that is not much of an improvement!

You have left the get() in. You haven't bothered to print out
ch to find that it is always the FIRST character on the next line.

You didn't read what getline does. It consumes the '\n' character.

You need to either (a) learn how to use the debugger.
(b) write a lot of std::cout<< statements.

I asked three questions:

(A) a to put getline (well you sort of have)
(B) to find out how many times it goes through the loop
(C) the line that your code failed to read.

You failed on 2/3. I used to use logarithm marking when I had students so that makes you on ln(1)/ln(3) == 0% More effort required.

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.