Problem with 'switch'

I am currently writing a simple program for my C++ class. It's almost done, but I'm having some trouble with my switch function that I'm using for a user menu. I've tried several fixes, but have had no luck in figuring out what's wrong, and I think it would help if a more experienced eye looked over the code. Maybe someone else can see something that I am not.

The switch function keeps telling me that 'case' is skipping the initialization of fstream studentInfo.

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
Write a console program that maintains student data in an external data file.
The program will allow the user to view all student records that exist in the external file
and add new records to the external data file.
Program Specifications:
1). Use a structure (struct) to define the elements of data contained in each student data record.
The struct elements must contain the following data types:
int stuID
char stuName[]
char stuMajor[]
double stuGPA
2). Create a menu that allows the user to perform the following operations:
Read Student Records
Write Student Records
Exit Program
3). Demonstrate your understanding of the modularization concept.
Create separate functions for the read and write operations.
The read function should contain the code that allows the user to view all student records.
The write function should contain the code that allows the user to add new student records. 
All read/write operations will directly access and use the external data file.
*/

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

using namespace std;

int const NAME_SIZE = 51;
int const MAJOR_SIZE = 20;
fstream studentInfo;

void readFile(fstream &studentInfo, struct i);
void writeFile(fstream &studentInfo, struct i);


struct infoStruct
{
	int studentID;
	char studentName[NAME_SIZE];
	char chosenMajor[MAJOR_SIZE];
	double studentGPA;
};

infoStruct i;



int main()
{

	
	fstream studentInfo;
	int menuSelect = '0';
	bool fileError = false;
	cout << "Student Information\n";

	

	do
	{
		cout << "<1> View Student Records" << endl;
		cout << "<2> Edit Student Records" << endl;
		cout << "<3> Exit Program" << endl;
		
		int menuSelect = '0';
		cin >> menuSelect;

		switch (menuSelect)
		{
			case '1':               //View student information
				cin.ignore();
				studentInfo.open("studentInfo.dat", ios::in | ios::binary);
				if(!studentInfo)
				{
					cout << "There was an error reading the file.";
					return 0;
				}
				readFile(studentInfo, i);
				
				break;

			case '2':               //Edit student information
				cin.ignore();
				fstream studentInfo("studentInfo.dat", ios::out | ios::binary);

				writeFile(studentInfo, i);

				break;

			case '3':               //Exit Program
				studentInfo.close();
				break;

			default:
				cout << "\n\n Invalid Input" << endl << endl;
		}

	}while (menuSelect != '3');

	return 0;
}

void readFile(fstream &studentInfo, struct infoStruct)
{
	char again;
	cout << "This is the student information: \n\n";
				studentInfo.read(reinterpret_cast<char *>(&i), sizeof(i));
				while (!studentInfo.eof())
				{
					cout << "Student ID: ";
					cout << i.studentID << endl;
					cout << "Student Name: ";
					cout << i.studentName, NAME_SIZE;
					cout << "Major: ";
					cout << i.chosenMajor, MAJOR_SIZE;
					cout << "GPA: ";
					cout << i.studentGPA << endl;

					cout << "\nPress ENTER to see the next record.\n";
					cin.get(again);
				
					studentInfo.read(reinterpret_cast<char *>(&i), sizeof(i));
				}

				cout << "There are no more records on file.";
				studentInfo.close();
}

void writeFile(fstream &studentInfo, struct infoStruct)
{
	char again = 'y';

	do
				{
					cout << "Please enter all of the following information to create a new record.\n";
					cout << "Please enter the Student ID.";
					cin >>  i.studentID;
					cout << "Please enter the student's name.";
					cin.getline(i.studentName, NAME_SIZE);
					cout << "Please enter the student's major.";
					cin.getline(i.chosenMajor, MAJOR_SIZE);
					cout << "Please enter the student's current GPA.";
					cin >> i.studentGPA;

					studentInfo.write(reinterpret_cast<char *>(&i), sizeof(i));

					cout << "Do you want to write another record?\n";
					cin >> again;
					cin.ignore();
				} while (again = 'y');

				studentInfo.close();
}
closed account (jw6XoG1T)
try putting your case arguements within {} brackets
closed account (jw6XoG1T)
so it'll be like this:

1
2
3
4
5
6
7
8

case 1:
{
    //code goes here..
}

break;
closed account (jw6XoG1T)
also, why are you setting int menuSelect equal to '0'? You should just leave it a regular number because putting those quotation marks around it turn it into a character i think.
line 66 needs to be
char menuSelect;

The switch statement never sees '1', '2' or '3', because
 
cin >> menuSelect;


will be 3 when you enter '3', not 51, what the switch statement is looking for.
I'm still having a small problem.

I keep getting the following error messages when I try to run the program:

c:\users\adam\desktop\c++ assignments\adamspaay_assign10\adamspaay_assign10\main.cpp(86): error C2664: 'readFile' : cannot convert parameter 2 from 'infoStruct' to 'i'
1> Source or target has incomplete type
1>c:\users\adam\desktop\c++ assignments\adamspaay_assign10\adamspaay_assign10\main.cpp(95): error C2664: 'writeFile' : cannot convert parameter 2 from 'infoStruct' to 'i'
1> Source or target has incomplete type

I'm not sure what it means when it says it cannot convert the struct (infoStruct) to its instance (i).

Here's the updated code:

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include<iostream>
#include<fstream>
#include<iomanip>
#include<string>

using namespace std;

int const NAME_SIZE = 51;
int const MAJOR_SIZE = 20;
fstream studentInfo;

void readFile(fstream &studentInfo, struct i);
void writeFile(fstream &studentInfo, struct i);


struct infoStruct
{
	int studentID;
	char studentName[NAME_SIZE];
	char chosenMajor[MAJOR_SIZE];
	double studentGPA;
};

infoStruct i;

char menuSelect = '0';

int main()
{

	
	fstream studentInfo;
	bool fileError = false;
	cout << "Student Information\n";

	

	do
	{
		cout << "<1> View Student Records" << endl;
		cout << "<2> Edit Student Records" << endl;
		cout << "<3> Exit Program" << endl;
		
		char menuSelect = '0';
		cin >> menuSelect;

		switch (menuSelect)
		{
			case '1':               //View student information
				{
				cin.ignore();
				studentInfo.open("studentInfo.dat", ios::in | ios::binary);
				if(!studentInfo)
				{
					cout << "There was an error reading the file.";
					return 0;
				}
				readFile(studentInfo, i);
				}
				break;

			case '2':               //Edit student information
				{
				cin.ignore();
				studentInfo.open("studentInfo.dat", ios::out | ios::binary);

				writeFile(studentInfo, i);
				}

				break;

			case '3':               //Exit Program
				{
				studentInfo.close();
				}
				break;

			default:
				cout << "\n\n Invalid Input" << endl << endl;
		}

	}while (menuSelect != '3');

	return 0;
}

void readFile(fstream &studentInfo, struct infoStruct)
{
	char again;
	cout << "This is the student information: \n\n";
				studentInfo.read(reinterpret_cast<char *>(&i), sizeof(i));
				while (!studentInfo.eof())
				{
					cout << "Student ID: ";
					cout << i.studentID << endl;
					cout << "Student Name: ";
					cout << i.studentName, NAME_SIZE;
					cout << "Major: ";
					cout << i.chosenMajor, MAJOR_SIZE;
					cout << "GPA: ";
					cout << i.studentGPA << endl;

					cout << "\nPress ENTER to see the next record.\n";
					cin.get(again);
				
					studentInfo.read(reinterpret_cast<char *>(&i), sizeof(i));
				}

				cout << "There are no more records on file.";
				studentInfo.close();
}

void writeFile(fstream &studentInfo, struct infoStruct)
{
	char again = 'y';

	do
				{
					cout << "Please enter all of the following information to create a new record.\n";
					cout << "Please enter the Student ID.";
					cin >>  i.studentID;
					cout << "Please enter the student's name.";
					cin.getline(i.studentName, NAME_SIZE);
					cout << "Please enter the student's major.";
					cin.getline(i.chosenMajor, MAJOR_SIZE);
					cout << "Please enter the student's current GPA.";
					cin >> i.studentGPA;

					studentInfo.write(reinterpret_cast<char *>(&i), sizeof(i));

					cout << "Do you want to write another record?\n";
					cin >> again;
					cin.ignore();
				} while (again = 'y');

				studentInfo.close();
}


Thanks for the help so far. :)
Last edited on
closed account (jw6XoG1T)
this part right here:

1
2
3

void writeFile(fstream &studentInfo, struct infoStruct)


instead of having "struct infoStruct" in the parameter list, put "infoStruct info". Then where ever you have "i" do something, replace "i" with "info".
closed account (jw6XoG1T)
same thing in "void readFile".
closed account (jw6XoG1T)
should be like this:


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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139


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

using namespace std;

int const NAME_SIZE = 51;
int const MAJOR_SIZE = 20;
fstream studentInfo;

struct infoStruct
{
	int studentID;
	char studentName[NAME_SIZE];
	char chosenMajor[MAJOR_SIZE];
	double studentGPA;
};

void readFile(fstream &studentInfo, infoStruct i);
void writeFile(fstream &studentInfo, infoStruct i);

infoStruct i;

char menuSelect = '0';

int main()
{

	
	fstream studentInfo;
	bool fileError = false;
	cout << "Student Information\n";

	

	do
	{
		cout << "<1> View Student Records" << endl;
		cout << "<2> Edit Student Records" << endl;
		cout << "<3> Exit Program" << endl;
		
		char menuSelect = '0';
		cin >> menuSelect;

		switch (menuSelect)
		{
			case '1':               //View student information
				{
				cin.ignore();
				studentInfo.open("studentInfo.dat", ios::in | ios::binary);
				if(!studentInfo)
				{
					cout << "There was an error reading the file.";
					return 0;
				}
				readFile(studentInfo, i);
				}
				break;

			case '2':               //Edit student information
				{
				cin.ignore();
				studentInfo.open("studentInfo.dat", ios::out | ios::binary);

				writeFile(studentInfo, i);
				}

				break;

			case '3':               //Exit Program
				{
				studentInfo.close();
				}
				break;

			default:
				cout << "\n\n Invalid Input" << endl << endl;
		}

	}while (menuSelect != '3');

	return 0;
}

void readFile(fstream &studentInfo, infoStruct i)
{
	char again;
	cout << "This is the student information: \n\n";
				studentInfo.read(reinterpret_cast<char *>(&i), sizeof(i));
				while (!studentInfo.eof())
				{
					cout << "Student ID: ";
					cout << i.studentID << endl;
					cout << "Student Name: ";
					cout << i.studentName, NAME_SIZE;
					cout << "Major: ";
					cout << i.chosenMajor, MAJOR_SIZE;
					cout << "GPA: ";
					cout << i.studentGPA << endl;

					cout << "\nPress ENTER to see the next record.\n";
					cin.get(again);
				
					studentInfo.read(reinterpret_cast<char *>(&i), sizeof(i));
				}

				cout << "There are no more records on file.";
				studentInfo.close();
}

void writeFile(fstream &studentInfo, infoStruct i)
{
	char again = 'y';

	do
				{
					cout << "Please enter all of the following information to create a new record.\n";
					cout << "Please enter the Student ID.";
					cin >>  i.studentID;
					cout << "Please enter the student's name.";
					cin.getline(i.studentName, NAME_SIZE);
					cout << "Please enter the student's major.";
					cin.getline(i.chosenMajor, MAJOR_SIZE);
					cout << "Please enter the student's current GPA.";
					cin >> i.studentGPA;

					studentInfo.write(reinterpret_cast<char *>(&i), sizeof(i));

					cout << "Do you want to write another record?\n";
					cin >> again;
					cin.ignore();
				} while (again = 'y');

				studentInfo.close();
}
I don't see what you changed in the whole page of code, but I'll try out your suggestion. Thanks a lot.
Okay, I seem to be having one more small problem. I'm not able to enter the student's name when prompted. The prompt is overtaken by the other prompt asking me for the student's major, and I can't enter the name at all.

Looks a little something like this

"Please enter the student ID:" 0001
"Please enter the student's name. Please enter the student's major."

The code is as follows:

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include<iostream>
#include<fstream>
#include<iomanip>
#include<string>

using namespace std;

int const NAME_SIZE = 51;
int const MAJOR_SIZE = 20;
fstream studentInfo;




struct infoStruct
{
	int studentID;
	char studentName[NAME_SIZE];
	char chosenMajor[MAJOR_SIZE];
	double studentGPA;
};

void readFile(fstream &studentInfo, infoStruct i);
void writeFile(fstream &studentInfo, infoStruct i);

infoStruct i;

char menuSelect = '0';

int main()
{

	
	fstream studentInfo;
	cout << "Student Information\n";

	

	do
	{
		cout << "<1> View Student Records" << endl;
		cout << "<2> Edit Student Records" << endl;
		cout << "<3> Exit Program" << endl;
		
		char menuSelect = '0';
		cin >> menuSelect;

		switch (menuSelect)
		{
			case '1':               //View student information
				{
					cin.ignore();
					studentInfo.open("studentInfo.dat", ios::in | ios::binary);
						if(!studentInfo)
						{
							cout << "There was an error reading the file.";
							return 0;
						}
					readFile(studentInfo, i);
				}
				break;

			case '2':               //Edit student information
				{
				cin.ignore();
				studentInfo.open("studentInfo.dat", ios::out | ios::binary);

				writeFile(studentInfo, i);
				}

				break;

			case '3':               //Exit Program
				{
				studentInfo.close();
				}
				break;

			default:
				cout << "\n\n Invalid Input" << endl << endl;
		}

	}while (menuSelect != '3');

	return 0;
}

void readFile(fstream &studentInfo, infoStruct i)
{
	char again;
	cout << "This is the student information: \n\n";
				studentInfo.read(reinterpret_cast<char *>(&i), sizeof(i));
				while (!studentInfo.eof())
				{
					cout << "Student ID: ";
					cout << i.studentID << endl;
					cout << "Student Name: ";
					cout << i.studentName, NAME_SIZE;
					cout << "Major: ";
					cout << i.chosenMajor, MAJOR_SIZE;
					cout << "GPA: ";
					cout << i.studentGPA << endl;

					cout << "\nPress ENTER to see the next record.\n";
					cin.get(again);
				
					studentInfo.read(reinterpret_cast<char *>(&i), sizeof(i));
				}

				cout << "There are no more records on file.";
				studentInfo.close();
}

void writeFile(fstream &studentInfo, infoStruct i)
{
	char again = 'y';

	do
				{
					cout << "Please enter all of the following information to create a new record.\n";
					cout << "Please enter the Student ID.";
					cin >>  i.studentID;
					cout << "Please enter the student's name.";
					cin.getline(i.studentName, NAME_SIZE);
					cout << "Please enter the student's major.";
					cin.getline(i.chosenMajor, MAJOR_SIZE);
					cout << "Please enter the student's current GPA.";
					cin >> i.studentGPA;

					studentInfo.write(reinterpret_cast<char *>(&i), sizeof(i));

					cout << "Do you want to write another record?\n";
					cin >> again;
					cin.ignore();
				} while (again != 'n');

				studentInfo.close();
}
C++ input streams have two different modes of input. When we use the >> operator, we are doing formatted input; when we don't (for instance we do a std::getline() or a std::cin.getline() )we are doing unformatted input.

1
2
int i ; std::cin >> i ; // formatted input
std::string line ; std::getline( std::cin, line ) ; // unformatted input 

The formatted input operator >> discards leading white space, and stops reading when it encounters a white space (or invalid input). Unformatted input on the other hand, does not discard leading whitespace.

If the contents of the input buffer was: <space> <newline> 1 2 3 4 <space> <newline> a b c d <newline> and we do int i ; std::cin >> i ; the formatted input operation discards leading white space: <space> <newline>, reads the next four characters to form an integer: 1 2 3 4 => i and leaves <space> <newline> a b c d <newline> in the input buffer.

Now, if we do std::string line ; std::getline( std::cin, line ) ; the unformatted input does not discard leading whitespace - the getline() reads characters into the string till a <newline> is encountered, and then reads the <newline> and discards it without appending it to the string. After the getline(), the string contains a <space> and the input buffer has a b c d <newline>.

Now let us say, we want to read an int (formatted input) and a string (using unformatted input) from stdin. We write:
1
2
3
4
int number ;
std::string text ;
std::cin >> number ;
std::getline( std::cin, text ) ;

We run the program and enter 12345<newline> on stdin. std::cin >> number ; reads 12345 into number and leaves the <newline> in the input buffer. The program continues with std::getline( std::cin, text ) ; The getline() sees that the input buffer is not empty, so it does not wait for any input to be entered. It returns immediately after reading an empty string, and extracting the <newline> in the buffer and throwing it away.

The best solution to the problem is not to mix formatted and unformatted input - they don't play well together. (How to do this to read numbers and lines of text might be a little beyond your depth right now).

The other option is to make the stream discard trailing white space left by the formatted input operation. This can be done by:
1
2
3
4
5
int number ;
std::string text ;
std::cin >> number ;
std::cin.ignore( 1024, '\n' ) ;
std::getline( std::cin, text ) ;


std::cin.ignore( 1024, '\n' ) ; will extract and discard up to 1024 characters or until a '\n' is extracted and thrown away. The 1024 in the example is just a reasonably large enough value, because we don't expect that more than that many characters would need to be discarded.

A more robust, 'correct' version would be:
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ) ; std::numeric_limits<std::streamsize>::max() being the largest possible number of characters an input buffer can possibly hold at one time.
Still having a problem with the file I'm writing to. It's not appending, but it's replacing any entry I make with any newer entry, and not saving everything I put in.

Thanks a lot, JLBorges. I actually have to have the variables AND the arrays in my struct, so mixing those two types of input is the only way I know how to input both of them correct at this point in my education.

I'm hoping I can correct the file problem myself, but if anyone sees the source of my problem, feel free to point it out.
You might change line 66 to

studentInfo.open("studentInfo.dat", ios::out | ios::binary | ios::app);
Topic archived. No new replies allowed.