Hi, I'm Sven
I'm a student from Belgium and one of my classes is about C++
I'm working on a program for such a long time, but I can't find the solution.
(First of all : sorry for my bad english)

Here's what I'm supposed to do :
I have to write a program to reads in a txt file with the following sentences :
" I'm not sure, but I think you will find the answer in Chapter
That's a good question..
And so on..
Al the sentences in this txt file start ar a new line. And there 8 sentences...

The program should ask the user to enter a question and gives one of the answer.. First question, first answer .. Second question, second answer..

When the first answer in the file is given there should be a number behind Chapter starting from 18.

Each time the whole file is read, the file should be restarted from the beginning and the number behind Chapter should be -1.

When the number behind Chapter is 0, the number should be reset to 18.

But I really can't figure out how I have to close and reopen the file when the program is at the end of the file. And how should I reset the number behind Chapter when it's 0 ?

This is what I have untill now :

#include <fstream>
#include <iostream>
#include <cstdlib>

using namespace std;

void geef_antwoord(ifstream& answer, int chapter_count);
void new_line ();

const int NUMBER_OF_CHAPTERS = 17;

int main ()
{
	using namespace std;

	int ch_count=18;
	
	ifstream fin;
	fin.open("antwoorden.txt");

	if (fin.fail())
	{
		cout << "Het openen van antwoorden.txt is mislukt \n";
		exit(1);
	}

	else
	{
			geef_antwoord (fin, ch_count);
			if (fin.eof())
			{
				fin.close();
				fin.open("antwoorden.txt");
				geef_antwoord (fin, ch_count);
			}	
	}
	
	return 0;
}

void new_line ()
{
	char symbol;
	do
	{
		cin.get(symbol);
	}while (symbol != '\n');
}

void geef_antwoord (ifstream& answer, int chapter_count)
{
	char question, answer_file;
	int answer_count=0;
	
	while (!answer.eof())
	{
		cout << "Give in a question, and the computer will give you the answer ! \n";
		cin.get(question);
		new_line();
		
		do
		{		
			answer.get(answer_file);
			cout << answer_file;
		}while (answer_file != '\n');

		if ((answer_count==0) && (answer_file == '\n'))
		{
			cout << chapter_count << ".";
			answer_count++;
		}

		if (!answer.eof())
		{
			answer_count++;
		}
		cout << endl;
	}
}

Recommended Answers

All 13 Replies

I'm not completely certain what you are attempting to do, but here is one way to do it. It is not necessary to close the file and reopen it. Just reset the stream back to the beginning of the file, as shown below.

std::string line;
for( ;; ) // infinite loop
{
    while( getline(answer, line) ) // get a line of text
    {
          // do something with this line
    }
    // end of file reached, so now rewind back to the beginning
    // and start all over again
    answer.seekg(0, ios::beg);
}

On line 58, you read in a character from the user and store it in a char variable called question ? Is that correct? I don't see you use this question variable anywhere, so what are you supposed to do with it and what does the user enter when prompted? So you have a file with eight questions, one question per line, but where do the answers come from? The same file? There's only one file, correct? Please provide it so we can get a better grip on the input. Might be hard if it's in another language, but it'll be better than nothing. And if there are both questions and answers in the file, highlight them in different colors or something. I'm having difficulty visualizing the contents of this file and what is supposed to happen.

Your new_line () function doesn't make much sense to me. You have a function that takes no parameters and returns nothing. You create a local char variable and continually overwrite it without doing anything with it. What's the point of this function? To clear the input buffer? If so, see Narue's thread pinned to the top of the C++ forum.

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

Here is the full task :

Write a program that allows the user to type in any other one-line question and then answer that question. The program will not really pay any attention to the question, but will simply read the question line and discard all that it reads. It always gives one of the following answers :

I'm not sure, but I think you will find the answer in Chaper #N
That's a good question.
If I were you , I would not worry about such things.
That question has puzzled philosophers for centuries.
I don't know. I'm just a machine.
Think about it and the answer will come to you.
I used to know the answer to that question, but I've forgotten it.
The answer can be found in a secret place in the woods.

These answers are stored in a file (one answer per line), and your program simply reads the next answer from the file and writes it out as the answer to the question. After your program has read the entire file, it simply closes the file, reopens the file, and starts down the list of answers again.

Whenever your program the first answer, it should replace the two symbols #N with a number between 1 and 18 (including the possibility of 1 and 18). In order to choose a number between 1 and 18, your program should initialize a variable to 18 and decrease the variable's value by 1 each time it outputs a number so that the chapter numbers count backward from 18 to 1. When the variable reaches the value 0, your program should change its value back to 18. Give the number 17 the name NUMBER_OF_CHAPTERS with a global named constant declaration using the const modifier.
Hint : Use the function new_line defined in this chapter (that's the one in my code, you can see in my first post. It's the same as in my book) I'm using Problem Solving with C++ by Walter Savitch if that would be any help.

Ancient Dragon, with your help I still don't get how to do it :s ...

Hmm, I just started writing a reply, but hit Enter and lost it. Bummer. I'll recreate it.

You need to step back and look at your program design. Make sure that all of the variables that you define are used. If they aren't, there is probably a problem and you need to delete them, or if they are required, take another look at how they are supposed to be used. You can, but don't have to (and shouldn't) read in one character at a time into a char, then look for a newline character, as you are trying to do. This can be done, as you are doing, but there are better ways. This is C++, there are strings, and there is the getline command. Make life easier and use them.

I see a nested loop for your needs. The outside loop should be an infinite loop. The file is opened and closed once each pass through this outer loop (alternatively you can rewind to the beginning using seekg as Ancient Dragon suggests, but the project specification says that you must open and close the file each time, so do that). The chapter number adjustment could be done in this outer while loop, where you subtract the chapter number by one and reset it to chapter 18 or whatever when it hits 0 or 1.

The inner loop prompts for a question, reads it in from the user, and throws it away, then reads a line from the file. You'll need to look out for the chapter number sign ("N") and replace it with the relevant number. There are a variety of ways to do this. You can use the find command from the string library to find "N", or you can simply look at the last character in the string and replace it. Strings are your best bet all around. Get rid of the cin.get () and answer.get () commands. Use getline with a string, not a char.

Hi, thanks for your answer... I hope it will work now..
The thing about strings... We haven't learned yet about strings, so we're not supposed to use them, and so we have to read in one character at a time into a char..

OK, I'm really not good in this :S
It seems like the inner loop doesn't find the end of the file with the eof-function...
I think the outer loop is now a infinite loop...
About "#N" : the program should read it in and then substitue "#N" for the Chapter Number.. I managed to place the chapter number, but not to delete the "#N"...

#include <fstream>
#include <iostream>
#include <cstdlib>

using namespace std;

void new_line ();

const int NUMBER_OF_CHAPTERS = 17;

int main ()
{
	using namespace std;

	int chapter_count=18;
	
	ifstream fin;
	fin.open("antwoorden.txt");

	if (fin.fail())
	{
		cout << "Opening file antwoorden.txt failed! \n";
		exit(1);
	}

	else
	{
		char question, answer_file;

		while (chapter_count <=18)
		{
			while (!fin.eof())
			{
				cout << "Give in a question, and the computer will give you the answer ! \n";
				cin.get(question);
				new_line();
		
				do
				{		
					fin.get(answer_file);
					cout << answer_file;

					if (answer_file == 'N')
					{
						cout << chapter_count;
					}
				}while (answer_file != '\n' && !fin.eof());
			
				cout << endl;
			}
			
			fin.close();
			fin.open("antwoorden.txt");

			chapter_count--;

			if (chapter_count == 0)
			{
				chapter_count += 18;
			}	
		}
	
	}
	
	return 0;
}

void new_line ()
{
	char symbol;
	do
	{
		cin.get(symbol);
	}while (symbol != '\n');
}

You need to clear the error flags in your ifstream or else that end-of-file flag will stay set even after you close and reopen the file. Closing and opening a file doesn't reset the flags. You must do that yourself:

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

Place this line after line 52 when you close the fin ifstream.

fin.clear ();

As for the chapter number and replacing "#N", perhaps check for the '#' instead of 'N' and stop displaying the file once '#' has been read in. Display the chapter number instead. Just make sure you don't display it for BOTH '#' AND 'N'. Just display it once.

Hi,

thanks for the help, it works !
I managed to remove the "N" of "#N" with the command fin.ignore (1, '#')
But than it displays #18, #17..

I've tried some few things, but I don't know how to replace the full "#N" by a number..

I've tried some few things, but I don't know how to replace the full "#N" by a number..

One, post what you have tried, including using the ignore command. We can only guess what you've tried if you don't post it. If you want to use the ignore method (a good choice for your needs), see the link I posted earlier from Narue. The problem, I am guessing, is that you are only throwing away one character. Throw away all of them until the newline (in your case, you'll throw away two characters, but if you use a big number, it'll simply go to the end of the line, which is what you want). Something like this, perhaps:

fin.get (answer_file);
if (answer_file == '#')
{
     fin.ignore (100, '\n'); // 100 is just a random big number.
     // display chapter number and exit loop
}
else if (answer_file == '\n' || fin.eof ())
{
     // exit loop    
}
else
{
     cout << answer_file;
}

Depending on how you implement this, you may or may not need to cout an endline ( '\n' ) before exiting the loop. You can use a break to exit the loop or you can set up a boolean variable and have your loop test for that. You shouldn't have to change your loop by much, but you will have to change it.

As a side note, a lot of people here recommend not using the eof function and there are many threads on Daniweb dealing with its potential pitfalls. Myself, I use it sometimes. You just have to be careful because it takes a while when you are first learning before you really understand how it works.

while (!fin.eof())
			{
				cout << "Give in a question, and the computer will give you the answer ! \n";
				cin.get(question);
				new_line();
				cout << "Answer : ";
		
				do
				{		
					fin.get(answer_file);
					
					if (answer_file == '#')
					{
						fin.ignore(2, '#' );
						cout << chapter_count << ".";
						cout << endl;
						break;
					}
					else if (answer_file == '\n' || fin.eof ())
					{
						cout << endl;
						break;
					}
					else 
					{
						cout << answer_file;
					}
				}while (answer_file != '\n' && !fin.eof());
			
				cout << endl;
			}

OK, with te ignore-command it works..
The only little problem I have now is that the answer to the second question is empty...
Should I give in a command that says that I have to start reading at a new line ?

fin.get(answer_file);
					
					if (answer_file == '#')
					{
						fin.ignore(2, '#' );
						cout << chapter_count << ".";
						cout << endl;
						break;
					}

OK, with te ignore-command it works..
The only little problem I have now is that the answer to the second question is empty...
Should I give in a command that says that I have to start reading at a new line ?

You'll never read the '#' sign with the ignore command the way you have it in the green line above. You've ALREADY read in the '#' sign in the top red line BEFORE you get to the ignore command, so you are definitely going to read two more characters exactly. This is fine if the next two characters are the 'N' and then '\n', but if they aren't, if you have an extra tab or space before the newline, the line in green will not read all the way to the end of the line. I ran your program and it worked fine, so I can only guess you have an extra space or tab or something at the end of the line. Experiment around and change the 2 to a 3 or whatever till it works, but it's better to do what I suggested,

fin.ignore(100, '\n' );

rather than

fin.ignore (2, '#');

100 is way more than you need, but it doesn't matter since you'll hit the newline long before you read 100 characters. It guarantees that it will work regardless of whether there are extra spaces or tabs or whatever at the end. Note that the second answer will actually show up in the way you have it originally, it will just be the answer to the THIRD question, not the second question.

I works perfectly now !
Thanks for your great help !!

grtz Sven

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.