Accept multiple data types then decipher the type

Basically I do not want to use a menu, instead just accept either an float or a single character. Then send the data to the appropriate spot based on the user input. I have been unable to convert the char to a float, and even if I did the char would probably only accept the first digit, say user enters '15' it would only read the '1'. I've tried strings instead of char but then unable to use the isalpha function. Do I need a char[] and then iterate through to get the numeric data? Then how do i make '1' and '5' become 15. There is probably a solution. I've also tried to use a loop waiting for the correct data while(!(cin >> letter)) which works but how do I get out if the user enters number. Sorry for the rambling length

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
76
77
78
#include <iostream>
#include <cctype>
#include <string>
#include <cstdlib>
using namespace std;

int main() {

	string sUserName;
	char cInput, cGrade;
	int iCreditHrs;
	float fStudyTotal, fStudyHrs;

	cout << "Welcome, this program will determine your expected grade\n";
	cout << "and the number of hours you should study based on the amount\n";
	cout << "of credit hours you are taking this semester.\n\n";
	
	cout << "Please enter your name. ";
	getline(cin, sUserName);
	cout << "\nPlease enter the amount of credit hours you are taking. ";
	cin >> iCreditHrs;
	cout << "\nPlease enter either the letter grade you would like to receive\n";
	cout << "or the number of hours you would like study each week. ";
	cin >> cInput;
	
	if ( isalpha(cInput) ) {
		char cDoAgain;
		cGrade = cInput;
		cDoAgain = 'y';
		do {
			cGrade = cInput;
			if ( cGrade == 'A' || cGrade == 'a' ) {
				fStudyTotal = iCreditHrs * 5;
			} else if ( cGrade == 'B' || cGrade == 'b' ) {
				fStudyTotal = iCreditHrs * 4;
			} else if ( cGrade == 'C' || cGrade == 'c' ) {
				fStudyTotal = iCreditHrs * 3;
			} else if ( cGrade == 'D' || cGrade == 'd' ) {
				fStudyTotal = iCreditHrs * 2;
			} else if ( cGrade == 'F' || cGrade == 'f' ) {
				fStudyTotal = iCreditHrs * 0;
			} else {
				cDoAgain = 'y';
				cout << "ERROR: if entering a letter grade, please enter\n";
				cout << " A, B, C, D, or F. ";
				cin >> cInput;
			}
		} while ( cDoAgain == 'y' && isalpha(cInput) );
		cout << sUserName << "\n\n";
		cout << "In order to receive your desired " << cGrade << ",\n";
		cout << "while taking " << iCreditHrs << " credit hours, you will need\n";
		cout << "to devote " << fStudyTotal << " hours to studying each week.";
	}
	else {
		do {
			fStudyHrs = atof( cInput );
			if ( fStudyHrs >= (iCreditHrs * 5) ) {
				cGrade = 'A';
			} else if ( fStudyHrs >= (iCreditHrs * 4) ) {
				cGrade = 'B';
			} else if ( fStudyHrs >= (iCreditHrs * 3) ) {
				cGrade = 'C';
			} else if ( fStudyHrs >= (iCreditHrs * 2) ) {
				cGrade = 'D';
			} else if ( fStudyHrs >= 0) {
				cGrade = 'F';
			} else 
				cout << "ERROR: Please enter a positive number. ";
				cin >> cInput;
		} while ( fStudyHrs < 0 );
		cout << sUserName << "\n\n";
		cout << "Since you plan to study " << fStudyHrs << " hours each week";
		cout << "while taking " << iCreditHrs << " credit hours,\n";
		cout << "you should receive grade the letter grade " << cGrade;
	}
	system("pause");
	return 0;
}
The user will always press Enter after an input.

Hence, read the user's input as a string, using std::getline().

1
2
3
4
5
6
7
8
	cout << "Please enter your name. ";
	getline(cin, sUserName);
	cout << "\nPlease enter the amount of credit hours you are taking. ";
	cin >> iCreditHrs;
	cin.ignore( numeric_limits<streamsize>::max(), '\n' );
	cout << "\nPlease enter either the letter grade you would like to receive\n";
	cout << "or the number of hours you would like study each week. ";
	getline(cin, sInput);

Now all you have to do is check to see if sInput is a letter (in A..F). Failing that, attempt to convert it to a float with a std::stringstream.

 
#include <sstream> 
1
2
3
4
5
6
7
8
9
	istringstream ss( sInput );
	ss >> fStudyHrs;
	if (!ss.eof()) {
		cout << "That's neither a letter grade nor a number of hours to study."
		//loop to try again
	}
	if (fStudyHrs < 0.0) {
		...
	}

Also, your loops are off. The purpose of the loop is to give the user an opportunity to correct his input. If there is no input in the loop, then user cannot do that.

1
2
3
4
5
while (true) {
	cout << "\nPlease enter either the letter grade you would like to receive\n";
	cout << "or the number of hours you would like study each week. ";
}
	getline(cin, sInput);

Oh, and one last thing -- it's a stylistic issue but in this case a fairly good one: don't use MS "Systems Hungarian Notation".

Those prefixes that tell you the data type of your variable are all but useless, and make maintenance a nightmare.

Read here for more (and enlightenment):
http://www.joelonsoftware.com/articles/Wrong.html

Hope this helps.
Thank you for the reply. I suppose I should have mentioned this is for a class. Hence the Hungarian Notation, is required.

I did realize that about the loops and that i should use a boolean instead of declaring another variable.

So change my char's to strings and use the istringstream. I have been racking my brain to figure it out.

Thank you
Another function you might be able to use is peek.

http://www.cplusplus.com/reference/istream/istream/peek/

You can look at a character at a time, determine it is white space (to be ignored, a letter grade or the beginning of a float value. Then you can extract what you need or handle the error.

The istringstream is probably a better solution, but this gives you another tool in your toolbox.
Topic archived. No new replies allowed.