Using an enum for flash card game

I am trying to write this program but i am struggling tremendously. I am not very good at c++ and i was hoping someone could point me in the right direction. Here are my instructions.

Prompt the user for a file that contains the questions – use getline(cin, fname) instead of cin >> fname to read the file name from the user. This will keep you in sync with the user’s input for later in the program
The first line is the number of questions (just throw this line away this week)
The second line is question 1
The third line is answer 1
The fourth line is question 2
The fifth line is answer 2 and so on,
Read the first question/answer from the file
Note you can use getline(yourInputStream, yourString) to read an entire line
Prompt the user for the answer to the question
The prompt is the question from the file, followed by “? “
The user gets 3 tries to get it correct
Make an enum to remember whether the user is answering, correct, or incorrect
Initially the user is answering
If answered incorrectly 3 times, then the user is incorrect
If answered correctly, then the user is correct
Checking if the answer is correct includes some string manipulation
Take the line that the user entered, remove all leading whitespace, remove all trailing whitespace, and convert everything to lowercase
By doing this, you can simply compare the user’s answer to the correct answer with an ==
Note: isspace(c) returns true if c is a whitespace character like a space or tab, false otherwise
Use functions as appropriate – you should have more than just main()
This is what the .txt file contains:
4
child
small fry
happy
tickled pink
mock
poke fun at
dough puncher
baker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

enum ChoiceType { ANSWERING, CORRECT, INCORRECT};


int main()
{
	ifstream inputFile;
	string fName, question, answer, junk, guess;

	cout << "File?" << " ";
	getline(cin, fName);

	inputFile.open(fName);

	getline(inputFile, junk);
	getline(inputFile, question);
	getline(inputFile, answer);

	cout << question << "? ";
	cin >> guess;
	cout << endl;



	cin.ignore(100, '\n');
	cin.get();
	return 0;
}
Last edited on
Your assignment is poorly-written, alas, making your program more complex than it needs to be, in my opinion.

If I understand it correctly, the current status is:
  • ANSWERING, so long as the answer is not correct
  • CORRECT, if the correct answer is given
  • INCORRECT, if three incorrect answers are given

This means you should have a loop that terminates on two conditions:
  • after three attempts
  • user answers CORRECT-ly

If, after the loop terminates, the user is not CORRECT, then the user should be marked as INCORRECT.

I would personally do this with a function.


Your assignment does not say what you should do with the information after that point. To keep it as simple as possible, you could just display the status and, if INCORRECT, print the correct answer.

I would put all of the above in a function.


Next, you need to do that for every pair of lines in the file. So you will need another loop, which calls the function so long as there are lines in the file.

Reading and skipping the first line goes before the loop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <fstream>
#include <iostream>
#include <string>

enum UserStatus { ANSWERING, CORRECT, INCORRECT };

UserStatus 
ask_and_check_answer( 
  const std::string& question, 
  const std::string& correct_answer,
  int attempt_number )
{
  std::string users_answer;
  std::cout << question << "? ";
  getline( std::cin, users_answer );

  /* This is where you should put code to trim(users_answer) and lowercase(users_answer) */
  /* I recommend writing functions to do this, and calling them from here */
  
  if (users_answer == correct_answer) return CORRECT;
  if (n < 3) return ANSWERING;  // user gets three tries!
  return INCORRECT;
}

You can use this easily enough:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void
next_ask_and_answer( std::istream& f )
{
  std::string question, correct_answer;
  getline( f, question );
  getline( f, correct_answer );
  if (!f) return;

  // This is the more-complicated-than-it-should-be part:
  // user's status is ANSWERING until
  //   • user becomes CORRECT
  //   • three attempts and user becomes INCORRECT

  UserStatus user_status = ANSWERING;
  int attempt_number = 1;
  while (user_status == ANSWERING)
  {
    user_status = ask_and_check_answer( question, correct_answer, attempt_number++ );
  }

  if (user_status == CORRECT)
    std::cout << "Good job!\n\n";
  else
    std::cout << "Incorrect. The correct answer is: " << correct_answer << "\n\n";
}

You could just use a loop instead of the fancy procedures:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void
next_ask_and_answer( std::istream& f )
{
  UserStatus user_status = ANSWERING;
  
  std::string question, answer;
  getline( f, question );
  getline( f, answer );
  if (!f) return;
  
  for (int n = 0; (n < 3) && (users_answer != CORRECT); n++)
  {
    std::string users_answer;
    std::cout << question << "? ";
    getline( std::cin, users_answer );
  
    users_answer = trim( users_answer );
    users_answer = lowercase( users_answer );
  
    if (users_answer == correct_answer)
      user_status = CORRECT;
  }
  if (user_status == ANSWERING)
    user_status = INCORRECT;
  
  if (user_status == CORRECT)
    std::cout << "Good job!\n\n";
  else
    std::cout << "Incorrect. The correct answer is: " << correct_answer << "\n\n";
}


Anyway, all that is left is to open your file, skip a line, and repeat until there is no more:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
  std::string filename;
  std::cout << "filename? ";
  getline( std::cin, filename );

  std::ifstream f( filename );

  std::string ignore_line;
  getline( f, ignore_line );

  while (f)
  {
    next_ask_and_answer( f );
  }
}


Again, I am sorry to give such a complete answer... but the assignment is so poorly-designed I don’t see how to get around it. Spend your time working on the functions to trim() and lowercase() a string.

1
2
3
4
5
6
7
8
9
10
11
std::string trim( std::string s );
//
//  Removes leading and trailing whitespace from s.
//  Uses std::isspace() and the overloaded string concatenation + operator 
//

std::string lowercase( std::string s );
//
//  Converts all characters in s to their lowercase equivalents.
//  Uses std::tolower()
// 


Hope this helps.
This is what I have so far if anyone wants to help. The program complies but it is not outputting the cases for each option.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

enum UserStatus { ANSWERING, INCORRECT, CORRECT};

/*
main - logic to read from file and prompt user for answer

return: status
*/
int main()
{
	UserStatus status;
	ifstream inputFile;
	string fName;
	string question;
	string answer;
	string junk;
	string userinput;

	cout << "File?" << " ";
	getline(cin, fName);
	inputFile.open(fName);

	getline(inputFile, junk);
	getline(inputFile, question);
	getline(inputFile, answer);

	cout << question << "? ";
	getline(cin, userinput);
	cout << endl;

	status = ANSWERING;
	switch (status)
	{
		case ANSWERING:
			cout << " " << endl;
			break;
		case CORRECT:
			cout << "Yay" << endl;
			break;
		case INCORRECT:
			cout << "Try Again" << endl; 
			break;
	}

	cin.ignore(100, '\n');
	cin.get();
	return 0;
}

UserStatus status()
{
	string answer;
	string userinput;
	int n;
	n = 0;
	while (n < 3)
	{
		if (userinput != answer)
		{
			return ANSWERING;
		}
		else if (userinput == answer)
		{
			return CORRECT;
		}
	}

}
Topic archived. No new replies allowed.