HELP on array and function project code.

This is for a project for one of my online classes and I don't understand why it isn't running. It comes up with the error code saying linker command failed and undefined symbols for architecture for the functions printhighest, printlowest, printaverage, and printonenumber from the function evaluate choices. PLEASE HELP.
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include <iostream>
#include <fstream>

using namespace std;
//function prototypes
void displayHeading();
int displayMenu(/*out*/int);
void readNumbers(/*out*/double [],/*in*/ int);
void readFile(/*out*/double [],/*in*/ int);
void printAllScores(/*in*/const double[],/*in*/ int);
void printHighest(/*in*/ const double[],/*in*/ int);
void printLowest(/*in*/ const double[],/*in*/ int);
void printAverage(/*in*/ const double[],/*in*/ int);
void printOneNumber(/*in*/ const double[],/*in*/ int);
void evaluateChoice(/*in*/ int,/*in*/ double[],/*in*/ int);
void quitProgram();
int main(){
   int choice;
    const int numScores =10;
    double userscore[numScores],
    total,
    lowesetScore,
    average;
    
    displayHeading();
    displayMenu(choice);
    while (choice !=8){
    
    evaluateChoice(choice, userscore, numScores);
    displayMenu(choice);
    }
    quitProgram();

return 0;
}
void displayHeading(){
    cout <<" ---------------------------------------------------"<<endl;
cout <<"1-D ARRAY PROCESSING MENU OPTIONS\n";
cout <<"---------------------------------------------------\n";
}

int displayMenu(/*out*/ int choice)
{
cout <<"1. Read in 10 scores from user.\n";
cout <<"2. Read in 10 scores from the file, scores.txt.\n";
cout <<"3. Print all scores.\n";
cout <<"4. Print the highest score.\n";
cout <<"5. Print the lowest score.\n";
cout <<"6. Print the average score.\n";
cout <<"7. Print one score (give its entry number)\n";
cout <<"8. Quit program\n";
cin >> choice;
return choice;
}

void readNumbers(/*out*/double userscore[],/*in*/ const int numScores){
    int count;
    for ( count =0; count < numScores-1; count++) {
    cout <<"Enter score #" <<(count +1) << ": ";
    cin >>userscore[count];
    }
}

void evaluateChoice(/*in*/ int choice,/*in*/ double userscore[],/*in*/ const int numScores){
    
    switch (choice) {
   case 1:
   cout <<"testing\n";
readNumbers(userscore,numScores);
break;
   case 2:
readFile(userscore, numScores);
break;
   case 3:
printAllScores(userscore,numScores);
break;
case 4:
printHighest(userscore, numScores);
break;
case 5:
printLowest(userscore, numScores);
break;
case 6:
printAverage(userscore, numScores);
break;
case 7:
printOneNumber(userscore, numScores);
break;

default : cout << "Invalid entry. Please pick an appropriate menu number.\n";
}
}

void readFile(/*out*/ double userscore[],/*in*/ const int numScores){
   string filename;
    ifstream inFile;
    cout <<"Please enter filename: ";
    cin >>filename;
    if (filename == "scores.txt"){
inFile.open(filename.c_str());

for(int count = 0; count < numScores; count++)
inFile>> userscore[count];
cout <<"File has successfully opened and 10 scores have been read.\n";
cout <<"Please select the print all scores menu option to view the scores.\n";

if (!inFile)
{
cout << "File error." << endl;
}
}
else
cout <<"File not found. Please retype the file." << endl;
cin >>filename;
inFile.close();
}

void printAllScores(/*in*/const double array1[], /*in*/const int numScores){
int count;
cout<<"Here are your scores:"<<endl;
for (count =0; count <numScores-1; count++){
cout <<" Score #"<<count +1;
cout << ": " <<array1[count]<<endl;
}
}

void quitProgram(){
    cout <<"Now exiting the program."<<endl;
    exit(0);
}

void printHighest(/*in*/ double userscore[],/*in*/ const int numScores){
int highest;
highest = userscore[9];
for (int i = 0; i < numScores; i++) {
if (highest > userscore[i]){ 
highest = userscore[i];
}
}
cout <<"The highest score is "<<highest<<endl;
}

void printLowest(/*in*/ double userscore[],/*in*/ const int numScores){
int lowest = userscore[9];
for (int i = 0; i < numScores; i++) {
if (lowest < userscore[i]){
    lowest = userscore[i];
}
}
cout <<"The lowest score is "<<lowest<<endl;
}

void printAverage(/*in*/double userscore[],/*in*/ const int numScores){
    int sum = 0;
    for (int count = 0; count < numScores; count++) {
    sum = sum + userscore[count];
    }
    int average = sum / numScores;
    cout <<"The average score is "<<average<<endl;
}

void printOneNumber(/*in*/double userscore[],/*in*/ const int numScores){
int userRow;
cout <<"Please enter entry or row # of score you want: \n";
cin >>userRow;
cout <<"Entry #"<<userRow<<"  ";
cout <<"Score: "<<userscore[userRow]<<endl;
cout <<"Score statistics: ";
}[code][code]
Last edited on
> void printHighest(/*in*/ const double[],/*in*/ int);
vs
> void printHighest(/*in*/ double userscore[],/*in*/ const int numScores){
You need to be absolutely consistent in your use of const here.

The compiler assumed you wanted the first one when you called it at line 78.
But you implemented something just slightly different.

In C++, with function overloading, everything has to match up exactly - including all the types and qualifiers of parameters.
I just compared the error messages produced by ld, lld, and gold.

lld produces the most helpful error message. gold is not far behind. ld's error messages are not quite as good.

Compare:
lld wrote:
mbozzi@sys11:~$ clang++ -fuse-ld=lld misc/foo.cpp
ld.lld: error: undefined symbol: printHighest(double const*, int)
>>> referenced by foo.cpp
>>>               /tmp/foo-530456.o:(evaluateChoice(int, double*, int))
>>> did you mean: printHighest(double*, int)
>>> defined in: /tmp/foo-530456.o

ld.lld: error: undefined symbol: printLowest(double const*, int)
>>> referenced by foo.cpp
>>>               /tmp/foo-530456.o:(evaluateChoice(int, double*, int))
>>> did you mean: printLowest(double*, int)
>>> defined in: /tmp/foo-530456.o

ld.lld: error: undefined symbol: printAverage(double const*, int)
>>> referenced by foo.cpp
>>>               /tmp/foo-530456.o:(evaluateChoice(int, double*, int))

ld.lld: error: undefined symbol: printOneNumber(double const*, int)
>>> referenced by foo.cpp
>>>               /tmp/foo-530456.o:(evaluateChoice(int, double*, int))
clang: error: linker command failed with exit code 1 (use -v to see invocation)


gold wrote:
mbozzi@sys11:~$ clang++ -fuse-ld=gold misc/foo.cpp
/tmp/foo-e23831.o:foo.cpp:function evaluateChoice(int, double*, int): error: undefined reference to 'printHighest(double const*, int)'
/tmp/foo-e23831.o:foo.cpp:function evaluateChoice(int, double*, int): error: undefined reference to 'printLowest(double const*, int)'
/tmp/foo-e23831.o:foo.cpp:function evaluateChoice(int, double*, int): error: undefined reference to 'printAverage(double const*, int)'
/tmp/foo-e23831.o:foo.cpp:function evaluateChoice(int, double*, int): error: undefined reference to 'printOneNumber(double const*, int)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)


ld wrote:
mbozzi@sys11:~$ clang++ -fuse-ld=ld misc/foo.cpp
/usr/bin/ld: /tmp/foo-ec4a07.o: in function `evaluateChoice(int, double*, int)':
foo.cpp:(.text+0x28d): undefined reference to `printHighest(double const*, int)'
/usr/bin/ld: foo.cpp:(.text+0x29e): undefined reference to `printLowest(double const*, int)'
/usr/bin/ld: foo.cpp:(.text+0x2af): undefined reference to `printAverage(double const*, int)'
/usr/bin/ld: foo.cpp:(.text+0x2c0): undefined reference to `printOneNumber(double const*, int)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)


Last edited on
Okay thank you, I got rid of the error message. The next part I am having trouble with is the switch statement I think. Whenever I run the program and choose an option from the menu, nothing actually happens. Also, what does * mean in function prototypes.
alexdieter wrote:
Okay, thanks. What does that necessarily mean?

It's just for your information. It could be taken as a suggestion to use the linker which produces the error messages you find make the most sense.

When it comes to the topic question, I have nothing to add to @salem c's reply (just above mine).
Last edited on
what does * mean in function prototypes.

It is just a different way to represent an array being passing into a function:
void evaluateChoice(int, double*, int): is syntactically the same as
void evaluateChoice(int, double[], int):.

When passing a regular array into a function the array decays to a pointer to the first element of the array.

Array decay happens when you invoke a function with a C-style array. The function takes the array via a pointer to its first element and its length. This means you start with a type-rich data structure C-array and end with a type-poor pointer to its first element.

I'm going to mention using a C-style array in C++ code can be a burden, especially when passed into a function. C++ has a number of containers that are easier to pass into a function and don't suffer container decay.

A common C++ container that can easily cross-over from a C-style array is std::vector.

https://cplusplus.com/reference/vector/vector/
Okay thank you. Could anyone help me on figuring out why nothing is showing up when I choose an option from the menu?
> int displayMenu(/*out*/int);
Just putting out in comments doesn't make it an out parameter.

If you want to get something back, you need to make it a pointer
int displayMenu(/*out*/int *);

Or better, a reference
int displayMenu(/*out*/int &);


Or use the function in the way you wrote it, by using the return value
choice = displayMenu(choice);

Choose a reference or a return.
Having both is a waste of effort.


Perhaps something like:

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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <iostream>
#include <fstream>

using std::cout;
using std::cin;

void displayHeading();
int displayMenu();
void readNumbers(double[]);
void readFile(double[]);
void printAllScores(const double[]);
void printHighest(const double[]);
void printLowest(const double[]);
void printAverage(const double[]);
void printOneNumber(const double[]);
void evaluateChoice(int, double[]);
void quitProgram();

const int numScores { 10 };

int main() {
	double userscore[numScores] {};

	displayHeading();

	for (int choice {}; (choice = displayMenu()) != 8; )
		evaluateChoice(choice, userscore);

	quitProgram();
}

void displayHeading() {
	cout << " ---------------------------------------------------\n";
	cout << "1-D ARRAY PROCESSING MENU OPTIONS\n";
	cout << "---------------------------------------------------\n";
}

int displayMenu() {
	int choice {};

	cout << "\n1. Read in 10 scores from user.\n";
	cout << "2. Read in 10 scores from the file, scores.txt.\n";
	cout << "3. Print all scores.\n";
	cout << "4. Print the highest score.\n";
	cout << "5. Print the lowest score.\n";
	cout << "6. Print the average score.\n";
	cout << "7. Print one score (give its entry number)\n";
	cout << "8. Quit program\n";

	cout << "Enter choice: ";

	cin >> choice;
	return choice;
}

void readNumbers(double userscore[]) {
	for (int count {}; count < numScores; ++count) {
		cout << "Enter score #" << (count + 1) << ": ";
		cin >> userscore[count];
	}
}

void evaluateChoice(int choice, double userscore[]) {
	switch (choice) {
		case 1:
			cout << "testing\n";
			readNumbers(userscore);
			break;

		case 2:
			readFile(userscore);
			break;

		case 3:
			printAllScores(userscore);
			break;

		case 4:
			printHighest(userscore);
			break;

		case 5:
			printLowest(userscore);
			break;

		case 6:
			printAverage(userscore);
			break;

		case 7:
			printOneNumber(userscore);
			break;

		default:
			cout << "Invalid entry. Please pick an appropriate menu number.\n";
			break;
	}
}

void readFile(double userscore[]) {
	std::string filename;

	cout << "Please enter filename: ";
	cin >> filename;

	std::ifstream inFile(filename);

	if (inFile) {
		for (int count {}; count < numScores; ++count)
			inFile >> userscore[count];

		cout << "File has successfully opened and 10 scores have been read.\n";
		cout << "Please select the print all scores menu option to view the scores.\n";
	} else
		cout << "File not found.\n";
}

void printAllScores(const double array1[]) {
	cout << "Here are your scores:\n";

	for (int count {}; count < numScores; ++count) {
		cout << " Score #" << count + 1;
		cout << ": " << array1[count] << '\n';
	}
}

void quitProgram() {
	cout << "Now exiting the program.\n";
	exit(0);
}

void printHighest(const double userscore[]) {
	double highest { userscore[0] };

	for (int i = 1; i < numScores; ++i)
		if (userscore[i] > highest)
			highest = userscore[i];

	cout << "The highest score is " << highest << '\n';
}

void printLowest(const double userscore[]) {
	double lowest { userscore[0] };

	for (int i = 1; i < numScores; ++i)
		if (userscore[i] < lowest)
			lowest = userscore[i];

	cout << "The lowest score is " << lowest << '\n';
}

void printAverage(const double userscore[]) {
	double sum {};

	for (int count {}; count < numScores; ++count)
		sum += userscore[count];

	cout << "The average score is " << (sum / numScores) << '\n';
}

void printOneNumber(const double userscore[]) {
	int userRow {};

	cout << "Please enter entry or row # of score you want (1 - " << numScores << "): ";
	cin >> userRow;

	if (userRow >= 1 && userRow <= numScores) {
		cout << "Entry #" << userRow << "  ";
		cout << "Score: " << userscore[userRow - 1] << '\n';
	} else
		cout << "Invalid entry\n";
}

Thank you. My professor does not allow global variables though.
This is the assignment.
Important note: DO NOT USE global variables and NO inline functions (i.e.., functions defined above main), Each function should have an appropriately named function prototype (aka. a function declaration) with or without a parameters listed above main and the related function algorithm with a function heading defined directly after main.

Make sure to do your best to also include function specific documentation, such as (1) data flow comments in function prototype and function heading parameter lists and (2) detailed function descriptions above each function heading which should also include comments related to pre/post conditions.
Write a program that gives the user a menu of 8 options and utilizes at least seven functions with specialized array processing related algorithms to process specific array related data request. Display a menu with the following options:

Read in 10 scores (integers) from the user.
Read in 10 scores from a file, scores.txt.
Print the 10 scores.
Print the highest score.
Print the lowest score.
Print the mean (average) of the 10 scores.
Print a score based on an entry or row# and show how many scores are higher.
Exit the program.
Both the size of the array (a named constant) and the array itself must be declared locally inside of int main( ). You should initialize the array to some value (probably 0) in case the user chooses options 3 - 7 before 1 or 2. Options 1 or 2 will overwrite any value previously stored in the array.
Each option in the menu must contain a call to a specific array processing related function. Each function must at minimum pass in the array and the size of the array. You must list all function prototypes above int main ( ) and all function definitions must appear after int main( ). Make sure to use good program format, style, naming conventions and include appropriate function related documentation (such as, data flow comments in all function prototype and function heading parameter lists, detailed function descriptions as well as pre/post comments in the function heading). No need to loose points for poor program format, style, function setup, naming conventions or missed function related documentation (see grading rubric for project).
You will find a few helpful programs in Gaddis text - Chapter 7 that provide examples on how to declare and process homogenous data with 1-D arrays as well as the set-up of some useful array functions.
You should use the input file, provided here => scores.txt Download scores.txt or you may create your own. You do not need to turn in your input file. Please note that I will be using this version of the scores.txt when testing your program.
Make sure to redisplay the menu after each option has been processed.
Provide appropriate input validation where necessary, use meaningful identifier names and DO NOT declare any variables globally.
DO NOT use array pointers or setup a vector with any vector related processing for this project.
An inline function is not a function "defined above main"....

https://www.geeksforgeeks.org/inline-functions-cpp/

Posting the FULL text of the assignment should have been done at the start so we don't do coding that isn't allowed. Please do that in the future so those trying to help you don't apply advanced coding techniques.

M'ok, I get the function declaration/definition split requirement, I do it myself most of the times. That way if I decide my project uses multiple files I can easily create a header/source file combo easily.

Calling functions being fully defined above main as "inline" makes me question the competence of the course material, it is just such a weird and wrongly worded requirement.
The only global is numScores which is a const and hence doesn't go against good practice guidelines. If a number is used throughout a program, why pass that number around functions when it's known? That's making the program un-necessarilly over-complicated.

Both the size of the array (a named constant) and the array itself must be declared locally inside of int main( )


Yes for the array
No for the constant for the size of the array.

Well if you really want the const as part of main(), then you're going to have to lug that variable all around the functions - as per original 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <iostream>
#include <fstream>

using std::cout;
using std::cin;

void displayHeading();
int displayMenu();
void readNumbers(double[], int);
void readFile(double[], int);
void printAllScores(const double[], int);
void printHighest(const double[], int);
void printLowest(const double[], int);
void printAverage(const double[], int);
void printOneNumber(const double[], int);
void evaluateChoice(int, double[], int);
void quitProgram();

//const int numScores { 10 };

int main() {
	const int numScores { 10 };
	double userscore[numScores] {};

	displayHeading();

	for (int choice {}; (choice = displayMenu()) != 8; )
		evaluateChoice(choice, userscore, numScores);

	quitProgram();
}

void displayHeading() {
	cout << " ---------------------------------------------------\n";
	cout << "1-D ARRAY PROCESSING MENU OPTIONS\n";
	cout << "---------------------------------------------------\n";
}

int displayMenu() {
	int choice {};

	cout << "\n1. Read in 10 scores from user.\n";
	cout << "2. Read in 10 scores from the file, scores.txt.\n";
	cout << "3. Print all scores.\n";
	cout << "4. Print the highest score.\n";
	cout << "5. Print the lowest score.\n";
	cout << "6. Print the average score.\n";
	cout << "7. Print one score (give its entry number)\n";
	cout << "8. Quit program\n";

	cout << "Enter choice: ";

	cin >> choice;
	return choice;
}

void readNumbers(double userscore[], int numScores) {
	for (int count {}; count < numScores; ++count) {
		cout << "Enter score #" << (count + 1) << ": ";
		cin >> userscore[count];
	}
}

void evaluateChoice(int choice, double userscore[], int numScores) {
	switch (choice) {
		case 1:
			cout << "testing\n";
			readNumbers(userscore, numScores);
			break;

		case 2:
			readFile(userscore, numScores);
			break;

		case 3:
			printAllScores(userscore, numScores);
			break;

		case 4:
			printHighest(userscore, numScores);
			break;

		case 5:
			printLowest(userscore, numScores);
			break;

		case 6:
			printAverage(userscore, numScores);
			break;

		case 7:
			printOneNumber(userscore, numScores);
			break;

		default:
			cout << "Invalid entry. Please pick an appropriate menu number.\n";
			break;
	}
}

void readFile(double userscore[], int numScores) {
	std::string filename;

	cout << "Please enter filename: ";
	cin >> filename;

	std::ifstream inFile(filename);

	if (inFile) {
		for (int count {}; count < numScores; ++count)
			inFile >> userscore[count];

		cout << "File has successfully opened and 10 scores have been read.\n";
		cout << "Please select the print all scores menu option to view the scores.\n";
	} else
		cout << "File not found.\n";
}

void printAllScores(const double array1[], int numScores) {
	cout << "Here are your scores:\n";

	for (int count {}; count < numScores; ++count) {
		cout << " Score #" << count + 1;
		cout << ": " << array1[count] << '\n';
	}
}

void quitProgram() {
	cout << "Now exiting the program.\n";
	exit(0);
}

void printHighest(const double userscore[], int numScores) {
	double highest { userscore[0] };

	for (int i = 1; i < numScores; ++i)
		if (userscore[i] > highest)
			highest = userscore[i];

	cout << "The highest score is " << highest << '\n';
}

void printLowest(const double userscore[], int numScores) {
	double lowest { userscore[0] };

	for (int i = 1; i < numScores; ++i)
		if (userscore[i] < lowest)
			lowest = userscore[i];

	cout << "The lowest score is " << lowest << '\n';
}

void printAverage(const double userscore[], int numScores) {
	double sum {};

	for (int count {}; count < numScores; ++count)
		sum += userscore[count];

	cout << "The average score is " << (sum / numScores) << '\n';
}

void printOneNumber(const double userscore[], int numScores) {
	int userRow {};

	cout << "Please enter entry or row # of score you want (1 - " << numScores << "): ";
	cin >> userRow;

	if (userRow >= 1 && userRow <= numScores) {
		const double score { userscore[userRow - 1] };

		cout << "Entry #" << userRow << "  ";
		cout << "Score: " << score << '\n';

		cout << "Higher scores are:\n";

		for (int i {}; i < numScores; ++i)
			if (userscore[i] > score)
				cout << userscore[i] << "  ";

		cout << '\n';
	} else
		cout << "Invalid entry\n";
}

@seeplus, how many times have C++ assignments given here end up over-complicating how a program is written? A. Lot. :)
Last edited on
Yeah - I know.

To paraphrase a famous saying:

"it's C++, George, but not as we know it"

:) :)
Dealing with the very-tight strait-jacket approach most C++ courses force on a student wouldn't be such a pain dealing with if the person asking for help were to mention the restriction(s) right off.

Chaps my tuchus no end to spend a chunk of my free time to craft some bit of code only to be whinged at "my teacher/instructor/professor doesn't allow XXX." GRRRR!
Topic archived. No new replies allowed.