Help with string arrays

Hi, I'm taking an intro course in C++ and I'm having trouble grasping string arrays. Specifically I need help with an assignment involving a grading program and I was hoping to get help here. The assignment:

You will be given an input file. The first line of the file will be the answer key. The answer key will have no spaces and will be exactly 20 characters (example:abcdabcdabcdabcdabcd).

Any line after the first line will be the students first name, last name, and answers (always in that order). There are no more than 50 students. There will only be 1 space between the first and last name, and the last name and answers (example:john smith abcdbacddbcbbacdbaba).

I must design a program that will display the students first and last name and match the students answers with the answer key, grading them accordingly and giving them a score (each correct answer is worth 5 points, maximum points being 100).

I cannot use global variables, goto statements, records and/or classes. The input file can only be read once, and arrays must be used to store the students names and scores. I must also use functions to modularize the code.

I know that each line after the first will have 3 strings (first name, last name, and answers) and I know that there are no more than 50 students. What I don't know is how many characters the first name string, last name string, and answer string will consist of.

My first problem is I don't understand how to declare an array with an unknown size. My next problem is I don't know how to get the input from the file and label each string to first name, last name, and answers (again without knowing their size either).

Not that it will help but I'll post the code. It doesn't compile either :/


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
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cctype>
#include <string>

using namespace std;

bool grades(char);


int main ()
{

  const int firstname = 50;
  const int lastname = 50;
  const int answer = 50;
    ifstream inf;
    ofstream outf;
    string inputfilename;
    string outputfilename;
    string theline;
    string fname[firstname][20];
    string lname[lastname][20];
    string answers[answer][20];
    char key[20];
    int scores;
    int average;
    int standarddev;
    int hiscore;


    cout << "Enter name of input file:" << endl;
    cin >> inputfilename;

    inf.open(inputfilename.c_str());

   

    while (!inf.eof())
    {
        inf >> theline;
        for (size_t j = 0; j< theline.length(); ++j)
        {
            theline[j] = tolower(theline[j]);
        }
	
    }

    inf >> key[20];

    cout << "Enter name of output file" << endl;
    cin >> outputfilename;
    outf.open(outputfilename.c_str());

   

    while (inf)
    {
      inf >> fname[];
      inf >> lname[];
      inf >> answers[];
    }
    
    outf << "# of students: " << endl;
    outf << "Average: " << endl;
    outf << "Standard Deviation: " << endl;
    outf << "\n" << endl;
    outf << "High Score earned by: " << endl;
   
    return 0;
}


Any help is super appreciated, I'm lost with this assignment and it's due by midnight tomorrow night (PST). Thanks in advance for any help.
Array of size x:
1
2
3
4
5
6
//get an integer x by any means necessary such as cin
//make an array of size x
string* lala = new string[x];

//... later when you are done with the array
delete[] lala;


I personally would declare strings like this instead:
1
2
3
4
string key;
string fnames[50];
string lnames[50];
string answers[50];


Each string variable is an array of characters. So that means string key; has the space to store the first line of the file. This is because the string type automatically sizes itself appropriately.

Now to read from the file, you already have the file opened after inf.open(...);. You can use inf >> stringVariable; to read characters from the file until it encounters whitespace. Whitespace consists of end of lines, spaces, carriage returns, etc. In your file the entire first line is the key, so the first thing should be inf >> key; (assuming you declared key like I said earlier). Reading the other things in should not be too hard. You already have a loop that will read the entire file until nothing is left while(inf){...}. You also know how to read things into a string from the file and stop at any whitespace. So the trick is to do three separate reads since there are 3 whitespaces on each of these lines according to the problem description. Namely, the space in between first and last name, the space in between last name and answers, and the space at the end of the line. So all that is left is what to store the reads in?

To answer that you have to think of how to access individual elements in an array. Which is array[0], array[1], ..., array[array_size - 1]. Before the loops begins create an integer to store this increasing index. Then inside the loop read it to the proper spots in the arrays, and additionally increment the index inside the loop.

Like this:
1
2
3
4
5
6
7
8
int index = 0;
while(inf && index < 50) //where && is "and"
{
    inf >> fnames[index];
    inf >> lnames[index];
    inf >> answers[index];
    index++;
}


And the loop on lines 40-48 in your post... Just get rid of that
Hey thanks for your reply Kevinkjt2000!

I forgot to mention that the input from the file may be a mix of lower case and upper case letters so I put line 40-48 in to force everything to lower case and I'll just capitalize what needs it when I do the formatting.

I implemented your changes and I have a better understanding but some things are still pretty fuzzy.

Here's what the sample input would look like (sorry if this is redundant):

1
2
3
4
5
6
thomas johnson ABCDabcdABCDabcdABCD
andy smith dcbaABCDabcdABCdabCaBBBB
terry crews AAAAAAAAAAAA
Mary templeton ABCDABCDABCDABCDABdb
jacob slinky aabbcccdabcdabcdabcd
gary white ABCDABCDABCDABCDaBcD


So now would array[0][0] be the string thomas or would it be simply the character 't'? Because I would want it to be thomas (even though I'm not sure how to reference that in the output table. Also would array[0][2] be the string ABCDabcdABCDabcdABCD or would it be the char A? Because for the answer I need to come up with a way to compare the characters in that string to the key for the score.

So I need to access the first 2 strings in the line as words (first and last name) and simply output them in a table next to the students score. I assume I implement this into the loop since it can only be read once? Then I need to access the answers portion as individual characters because I need to compare them to the key (probably by calling a function).

Here's what the output is supposed to look like (minus the terrible formatting):

1
2
3
4
5
6
7
8
9
10
11
12
13
NAME                          SCORE
Johnson,Terry                    100
Smith,Andy                        75
Adams,Amanda                    15
Masterson,Jake                90
Slinky,Sarah                75
Black,Larry                     100
# of students:                    6
Average:                     75.833
Standard deviation:          71.210
High score of 100 earned by
Jones,Bonnie
Black,Larry


Thanks again for your help! I feel like I'm on the cusp of understanding it.
The loop code I posted would read the data into separate arrays. Using your example input:
thomas johnson ABCDabcdABCDabcdABCD
andy smith dcbaABCDabcdABCdabCaBBBB
terry crews AAAAAAAAAAAA
Mary templeton ABCDABCDABCDABCDABdb
jacob slinky aabbcccdabcdabcdabcd
gary white ABCDABCDABCDABCDaBcD

fnames[0] would be "thomas"
lnames[4] would be "slinky"
lnames[4][5] would be 'y'
answers[2] would be "AAAAAAAAAAAA"

Formatted output is easy once you know about how to do it in C++. You might find these links helpful for formatting output.
http://www.arachnoid.com/cpptutor/student3.html
http://www.cprogramming.com/tutorial/iomanip.html

The first example is probably the one you will understand more easily, but the second example is more concise.
Just keep in mind that outputting
thomas
slinky
y
AAAAAAAAAAAA

Would be as easy as passing the things I listed earlier to cout. cout knows how to handle string type variables.

Edit: Just realized that terry did not give as many answers for their test. My understanding of the assignment you posted earlier is that all the students would give the same number of answers.
Last edited on
Thanks keinkjt2000 I think I've got the bulk of it done, however, a new problem has arisen!

I can't seem to get the student's answers into lower case and it's causing the scoring to be incorrect. I want to say I need to pass something by reference to the gradestudents function but i'm unsure about that. Here's my 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
138
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cctype>
#include <string>

using namespace std;

void readfile(string& f_key, string f_first[], string f_last[], string f_grades[], string inputfilename);
void printstudents(string& f_key, string f_first[], string f_last[], int f_avg[]);
void outputgrades(string& f_key, string f_first[], string f_last[], int f_avg[], string outputfilename);
void gradestudents(string& f_key, string f_grades[], int f_avg[]);

int main()
{
	string first[50];
	string last[50];
	string grades[50];
	int avg[50];
	string key;
	string inputfilename;
	string outputfilename;
	ifstream inf;
	ofstream outf;

	cout << "Enter name of input file: " << endl;
	cin >> inputfilename;
	

	cout << "Enter name of output file: " << endl;
	cin >> outputfilename;
	
	

	readfile(key, first, last, grades, inputfilename);

	gradestudents(key, grades, avg);

	printstudents(key, first, last, avg);

	outputgrades(key, first, last, avg, outputfilename);

	
	outf.close();

	return 0;
}

void readfile(string& f_key, string f_first[], string f_last[], string f_grades[], string inputfilename) 
{
        ifstream inf;
	int studentiterator = 0;

	inf.open(inputfilename.c_str());

	inf >> f_key;

	while (!inf.eof())
	{
		inf >> f_first[studentiterator];
		inf >> f_last[studentiterator];
		inf >> f_grades[studentiterator];
		studentiterator++;
	}

inf.close();

}

void printstudents(string& f_key, string f_first[], string f_last[], int f_avg[]) 
{
        ofstream outf;

	outf << f_key << endl;

	for (int i = 0; i < 5; i++) 
	  {
		outf << f_first[i] << " " << f_last[i] << " " << f_avg[i] << endl;
	}
}

void outputgrades(string& f_key, string f_first[], string f_last[], int f_avg[], string outputfilename) 
{
        ofstream outf;
        outf.open(outputfilename.c_str());

	outf << left << setw(10) << "NAMES" << right << setw(25) << "SCORES" << endl;

	for (int i = 0; i < 5; i++) 
	  {
	    outf << f_last[i] << ", " << f_first[i] << " " << f_avg[i] << endl;
	}

	int students = 0;
	for (int i = 0; i < 50; i++) 
	  {
		if (f_first[i] != "") 
		  {
		    students++;
		}
	}

	outf << "# of students: " << students << endl;

	double dubtemp = 0.0;
	students = 0;
	for (int i = 0; i < 50; i++) 
	  {
		if (f_avg[i] != 0) 
		  {
			dubtemp = dubtemp + f_avg[i];
			students++;
		}
	}
	dubtemp = dubtemp / students;

	outf << "Average: " << dubtemp << endl;

}

void gradestudents(string& f_key, string f_grades[], int f_avg[]) 
{
  for (int i = 0; i < 50; i++)
	  {
		int num = 0;
		for (int j = 0; j < f_grades[i].length(); j++) 
		  {
			char t1, t2;
			t1 = tolower(f_key[j]);
			t2 = tolower(f_grades[i][j]);
			if (t1 == t2)
			  {
				num += 5;
			}
		}
		f_avg[i] = num;
	}
}


So if you compile it and run it it seems to work but the grades aren't being converted to lower case for grading. Any idea on what's going on or what I can do to fix it? Thanks again!
closed account (j3Rz8vqX)
causing the scoring to be incorrect

With the included header:
void gradestudents(string& f_key, string f_grades[], int f_avg[])

Think about the below code; its significance.
f_avg[i] = num;
Last edited on
Thanks for the reply. Yes int f_avg[] is being used in other functions to calculate the the average and display the score.

I believe the issue is with the function not converting the student answers to lower case so when the key and the student answer is tabulated if a student answer is 'A' but the key answer is 'a' it is not incrementing when I want it to. The only solutions I can think of is converting all of the student answers to lower case right off the bat or allowing 'A' and 'a' to be the same thing. I though line 129 and 130 did this but for some reason it isn't.

Any ideas why it's not working?
closed account (j3Rz8vqX)
I believe the issue is with the function not converting the student answers to lower case so when the key and the student answer is tabulated if a student answer is 'A' but the key answer is 'a' it is not incrementing when I want it to


For debugging purposes, add std::cout<<"Characters "<<t1<<" & "<<t2<<std::endl; before the comparison on line 131.

See what kind of a monster you've truly made; kidding, but check out their values.
Ah wow thanks for the heads up on that! I didn't even think about if a student enters less than 20 characters (which they can legitimately do). Man that just destroyed my loop ugh!

Thanks for catching that though I appreciate it.

EDIT: Thanks Dput, the problem was I'm an idiot and placed 19 characters in the key instead of 20 (which it will always have).
Last edited on
Topic archived. No new replies allowed.