Text file Program help please

C

ComicCaper

Hi all,

I use a quiz program that accepts a text file for questions and answers
in this format:

Question
Answer1 <----is the correct answer. Quiz randomizes answers.
Answer2
Answer3
Answer4
0 <-------corresponds to which Answer is the correct one.

(4 lines of blank space then the next set.)



In order to make my life easier I created a program that will take 3
files and combine them into one using the above formatting.

Using vocab style questions I have a keyword file for the Questions, one
that has the correct answer and then one that has 3 wrong answers.

Problem: if I have 2 or 3 keywords the program works great. If I dump in
over 300 keywords the program gets stuck in a loop. I can think of only
two things that there is a hidden character in the keyword file that's
causing the problem (how do I find hidden characters?) and (for fear of
sounding stupid) that the CPU and RAM can't keep up with what is going on.

Here's my program:

/*Matt Short

*/

#include <iostream>
#include <fstream>

using namespace std;

int main()
{

const int SIZE = 30; //setting up keywordFile;
fstream keywordFile;
char input[SIZE];

const int LINE = 400; //setting up definition file;
fstream defFile;
char def[LINE];

fstream ansFile; //setting up answer file
char ans[LINE];

ofstream quizFile("c:\\quizFile.txt"); //setting up final quiz file


keywordFile.open("c:\\keyword.txt", ios::in);
defFile.open("c:\\defFile.txt", ios::in);
ansFile.open("c:\\ansFile.txt", ios::in);

while (!keywordFile.eof())
{

keywordFile.getline(input, SIZE);
defFile.getline(def, LINE);
quizFile << input << endl << def << endl;

ansFile.getline(ans, LINE);
quizFile << ans << endl;

ansFile.getline(ans, LINE);
quizFile << ans << endl;

ansFile.getline(ans, LINE);
quizFile << ans << endl << "0" << endl << endl << endl << endl << endl;

}
keywordFile.close();
quizFile.close();
ansFile.close();
defFile.close();


return 0;

}
 
D

Daz

ComicCaper said:
Problem: if I have 2 or 3 keywords the program works great. If I dump in
over 300 keywords the program gets stuck in a loop. I can think of only
two things that there is a hidden character in the keyword file that's
causing the problem (how do I find hidden characters?) and (for fear of
sounding stupid) that the CPU and RAM can't keep up with what is going on.

I would recommend you have a look at the output file when your program
hangs and you terminate it, to see how far it got, and then check out
the other files for anything out of the ordinary. The only hidden
characters that would affect you (as far as I know) , are the common
ones that appear in a plain text file, such as '\n' and '\r'.

Please don't take this as gospel, I am fairly new to C++, but this is
the first logical-sounding step I would take.
 
D

Daz

Daz said:
I would recommend you have a look at the output file when your program
hangs and you terminate it, to see how far it got, and then check out
the other files for anything out of the ordinary. The only hidden
characters that would affect you (as far as I know) , are the common
ones that appear in a plain text file, such as '\n' and '\r'.

Please don't take this as gospel, I am fairly new to C++, but this is
the first logical-sounding step I would take.

In addition, I would also use std::string as opposed to a character
array. In my limited experience, there is nothing you can do with a
character array that you can't do with a std::string. I'm not sure if
this will fix your problem, however, strings are completely dynamic so
it doesn't matter how long it is.

You could also use a regex to flag any characters that aren't in the
range you specify. If you don't already know regex, it's worth
learning, but will probably take too long to learn for the purpose you
need it.
 
D

Daz

Daz said:
In addition, I would also use std::string as opposed to a character
array. In my limited experience, there is nothing you can do with a
character array that you can't do with a std::string. I'm not sure if
this will fix your problem, however, strings are completely dynamic so
it doesn't matter how long it is.

You could also use a regex to flag any characters that aren't in the
range you specify. If you don't already know regex, it's worth
learning, but will probably take too long to learn for the purpose you
need it.

Err... you might find it's also useful to check if the files you are
trying to open, are actually open. For debugging small programs like
this, I often add a few 'cout' lines, so every line that is going to be
added to the file, can be seen on the console. You will see if anything
is out of the ordinary here in your mock-matrix-style screen. :D
 
J

Jonathan Mcdougall

ComicCaper said:
Hi all,

I use a quiz program that accepts a text file for questions and answers
in this format:

Question
Answer1 <----is the correct answer. Quiz randomizes answers.
Answer2
Answer3
Answer4
0 <-------corresponds to which Answer is the correct one.

(4 lines of blank space then the next set.)



In order to make my life easier I created a program that will take 3
files and combine them into one using the above formatting.

Using vocab style questions I have a keyword file for the Questions, one
that has the correct answer and then one that has 3 wrong answers.

Problem: if I have 2 or 3 keywords the program works great. If I dump in
over 300 keywords the program gets stuck in a loop. I can think of only
two things that there is a hidden character in the keyword file that's
causing the problem (how do I find hidden characters?) and (for fear of
sounding stupid) that the CPU and RAM can't keep up with what is going on.

Are you sure it is stuck? Can you output something at each loop to see
what's happening?
Here's my program:

/*Matt Short

*/

#include <iostream>
#include <fstream>

using namespace std;
http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5

int main()
{
const int SIZE = 30; //setting up keywordFile;
fstream keywordFile;
char input[SIZE];

const int LINE = 400; //setting up definition file;
fstream defFile;
char def[LINE];

fstream ansFile; //setting up answer file
char ans[LINE];

For these three blocks:
1) use std::string (from <string>)
2) don't define an object if you cannot initizalise it
3) use either std::eek:fstream or std::ifstream, not std::fstream (except
in special cases)

These should therefore be

std::ifstream keywordFile("c:\\keywork.txt");
std::ifstream defFile("c:\\defFile.txt");
std::ifstream ansFile("c:\\ansFile.txt");

For the character arrays, see below.
ofstream quizFile("c:\\quizFile.txt"); //setting up final quiz file

keywordFile.open("c:\\keyword.txt", ios::in);
defFile.open("c:\\defFile.txt", ios::in);
ansFile.open("c:\\ansFile.txt", ios::in);

When you use std::ifstream, ios::in is redundant.
while (!keywordFile.eof())

You may read past beyond EOF with this. Think: EOF is detected after
reading, that means ....
{
keywordFile.getline(input, SIZE);

..... here. Oups.
defFile.getline(def, LINE);
quizFile << input << endl << def << endl;

ansFile.getline(ans, LINE);
quizFile << ans << endl;

ansFile.getline(ans, LINE);
quizFile << ans << endl;

ansFile.getline(ans, LINE);
quizFile << ans << endl << "0" << endl << endl << endl << endl << endl;

Now, if you decide to use std::string, these would look like

std::string line;

getline(keywordFile, line);
quizFile << line << "\n";

getline(defFile, line);
quizFile << line << "\n";

// ...

Note that outputing std::endl flushes the buffer of the stream, which
may not be what you want (ie a new line).
keywordFile.close();
quizFile.close();
ansFile.close();
defFile.close();

Redundant (that's what destructor are for).


Jonathan
 
D

Daz

Jonathan said:
ComicCaper said:
Hi all,

I use a quiz program that accepts a text file for questions and answers
in this format:

Question
Answer1 <----is the correct answer. Quiz randomizes answers.
Answer2
Answer3
Answer4
0 <-------corresponds to which Answer is the correct one.

(4 lines of blank space then the next set.)



In order to make my life easier I created a program that will take 3
files and combine them into one using the above formatting.

Using vocab style questions I have a keyword file for the Questions, one
that has the correct answer and then one that has 3 wrong answers.

Problem: if I have 2 or 3 keywords the program works great. If I dump in
over 300 keywords the program gets stuck in a loop. I can think of only
two things that there is a hidden character in the keyword file that's
causing the problem (how do I find hidden characters?) and (for fear of
sounding stupid) that the CPU and RAM can't keep up with what is going on.

Are you sure it is stuck? Can you output something at each loop to see
what's happening?
Here's my program:

/*Matt Short

*/

#include <iostream>
#include <fstream>

using namespace std;
http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5

int main()
{
const int SIZE = 30; //setting up keywordFile;
fstream keywordFile;
char input[SIZE];

const int LINE = 400; //setting up definition file;
fstream defFile;
char def[LINE];

fstream ansFile; //setting up answer file
char ans[LINE];

For these three blocks:
1) use std::string (from <string>)
2) don't define an object if you cannot initizalise it
3) use either std::eek:fstream or std::ifstream, not std::fstream (except
in special cases)

These should therefore be

std::ifstream keywordFile("c:\\keywork.txt");
std::ifstream defFile("c:\\defFile.txt");
std::ifstream ansFile("c:\\ansFile.txt");

For the character arrays, see below.
ofstream quizFile("c:\\quizFile.txt"); //setting up final quiz file

keywordFile.open("c:\\keyword.txt", ios::in);
defFile.open("c:\\defFile.txt", ios::in);
ansFile.open("c:\\ansFile.txt", ios::in);

When you use std::ifstream, ios::in is redundant.
while (!keywordFile.eof())

You may read past beyond EOF with this. Think: EOF is detected after
reading, that means ....
{
keywordFile.getline(input, SIZE);

.... here. Oups.
defFile.getline(def, LINE);
quizFile << input << endl << def << endl;

ansFile.getline(ans, LINE);
quizFile << ans << endl;

ansFile.getline(ans, LINE);
quizFile << ans << endl;

ansFile.getline(ans, LINE);
quizFile << ans << endl << "0" << endl << endl << endl << endl << endl;

Now, if you decide to use std::string, these would look like

std::string line;

getline(keywordFile, line);
quizFile << line << "\n";

getline(defFile, line);
quizFile << line << "\n";

// ...

Note that outputing std::endl flushes the buffer of the stream, which
may not be what you want (ie a new line).
keywordFile.close();
quizFile.close();
ansFile.close();
defFile.close();

Redundant (that's what destructor are for).


Jonathan

Nice tutorial Jonathan! Very good explanations and reasons. Very well
done, I take my hat off to you!

Many thanks.

Daz
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,120
Latest member
ShelaWalli
Top