Linker Errors

Pages: 12
I'll start right out and include all of the relevant data.. I am getting linker errors, and as far as I am aware, I've made sure all classes are defined properly, all constructors and destructors are defined properly, and walked through the program flow in my head multiple times.. I cannot seem to find out what's wrong... Is there a good 'step by step' guide for things to check for when you get linker errors?

I would appreciate any help!


1>Microsoft (R) Windows Resource To Object Converter Version 9.00.21022.08
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>adding resource. type:ICON, name:1, language:0x0409, flags:0x1010, size:744
1>adding resource. type:ICON, name:2, language:0x0409, flags:0x1010, size:296
1>adding resource. type:GROUP_ICON, name:1, language:0x0409, flags:0x1030, size:34
1>Module 7 - Assignment 7.obj : error LNK2020: unresolved token (0A0002A4) "class Student * students" (?students@@3PAVStudent@@A)
1>Module 7 - Assignment 7.obj : error LNK2001: unresolved external symbol "class Student * students" (?students@@3PAVStudent@@A)
1>I:\College\~Summer 2010\10SS_INFO_1532_WW - C++ Programming II\Week 8 - Module 7\Module 7 - Assignment 7\Debug\Module 7 - Assignment 7.exe : fatal error LNK1120: 2 unresolved externals
1>Build log was saved at "file://i:\College\~Summer 2010\10SS_INFO_1532_WW - C++ Programming II\Week 8 - Module 7\Module 7 - Assignment 7\Module 7 - Assignment 7\Debug\BuildLog.htm"
1>Module 7 - Assignment 7 - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========



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
//Student.h the specification file for class Student

#include <iostream>

using namespace std;

class Student{

	
friend istream & operator>> (istream&, Student &);
//Function overrides the instream operator.
//Intended to ease the input of student data

friend ostream & operator<< (ostream&, const Student &);
//Function overrides the outstream operator.
//Intended to ease the output of student data
	
private:

char name[46];
//Student’s name: 45 characters, alpha-numeric

char address[55];
//Student’s address: 55 characters, alpha-numeric

char city[15]; 
//Student’s city:  15 characters, alpha-numeric

char state[2];
//Student’s state: 2 characters, alpha

char zipCode[5];
//Student’s zip code: 5 characters, numeric

char id[8];
//Student’s Id: 8 characters, alpha-numeric

char grades[5];
//Student’s 5 grades: Characters, A, B, C, D, & F

float gpa;
//Student GPA: floats


public:

void setName(std::string newName);
//Function to set the name of the student
//Postcondition: name = newName;

std::string getName();
//Function to get the name of the student
//Postcondition: returns the name of the student
//				as a string


void setAddress(std::string newAddress);
//Function to set the address of the student
//Postcondition: address = newAddress;

std::string getAddress();
//Function to get the address of the student
//Postcondition: returns the address of the student
//				as a string


void setCity(std::string newCity);
//Function to set the city of the student
//Postcondition: city = newCity;

std::string getCity();
//Function to get the city of the student
//Postcondition: returns the city of the student
//				as a string


void setState(std::string newState);
//Function to set the state of the student
//Postcondition: state = newState;

std::string getState();
//Function to get the state of the student
//Postcondition: returns the state of the student
//				as a string



void setZipCode(std::string newZipCode);
//Function to set the zipCode of the student
//Postcondition: zipCode = newZipCode;

std::string getZipCode();
//Function to get the zipCode of the student
//Postcondition: returns the ZipCode of the student
//				as a string


void setId(std::string newId);
//Function to set the id of the student
//Postcondition: id = newId;

std::string getId();
//Function to get the id of the student
//Postcondition: returns the id of the student
//				as a string


void setGrades(char newGrades, int index);
//Function to set the Grades of the student
//Postcondition: grades[index] = newGrades;

char getGrades(int index);
//Function to get the grades of the student
//Postcondition: returns the grades[index] of the student
//				as a character


void setGpa(float newGpa);
//Function to set the name of the student
//Postcondition: gpa = newGpa;

float getGpa();
//Function to get the gpa of the student
//Postcondition: returns the gpa of the student
//				as a float




Student();
//Default Constructor
//All variables are set to 0 or "" or ' '

};


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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
//Student.cpp The implementation file

#include "stdafx.h"
#include <String>
//#include <iostream>
#include "Student.h"


using namespace std;

void Student::setName(string newName)
{
	for (unsigned int i = 0; i < newName.length(); i++)
	{
		name[i] = newName.at(i);
	}
}

string Student::getName()
{
	return name;
}


void Student::setAddress(string newAddress)
{
	for (unsigned int i = 0; i < newAddress.length(); i++)
	{
		address[i] = newAddress.at(i);
	}
}

string Student::getAddress()
{
	return address;
}


void Student::setCity(string newCity)
{
	for (unsigned int i = 0; i < newCity.length(); i++)
	{
		city[i] = newCity.at(i);
	}

}

string Student::getCity()
{
	return city;
}


void Student::setState(string newState)
{
	for (unsigned int i = 0; i < newState.length(); i++)
	{
		state[i] = newState.at(i);
	}

}

string Student::getState()
{
	string temp = "";
	temp.push_back(state[0]);
	temp.push_back(state[1]);
	return temp;
}



void Student::setZipCode(string newZipCode)
{
	for (unsigned int i = 0; i < newZipCode.length(); i++)
	{
		zipCode[i] = newZipCode.at(i);
	}

}

string Student::getZipCode()
{
	string temp = "";
	temp.push_back(zipCode[0]);
	temp.push_back(zipCode[1]);
	temp.push_back(zipCode[2]);
	temp.push_back(zipCode[3]);
	temp.push_back(zipCode[4]);
	return temp;
}


void Student::setId(string newId)
{
	for (unsigned int i = 0; i < newId.length(); i++)
	{
		id[i] = newId.at(i);
		
	}
}

string Student::getId()
{
	string temp = "";
	for (int i=0; i < 8; i++)
	{
	temp.push_back(id[i]);
	}
	/*
	temp.push_back(id[0]);
	temp.push_back(id[1]);
	temp.push_back(id[2]);
	temp.push_back(id[3]);
	temp.push_back(id[4]);
	temp.push_back(id[5]);
	temp.push_back(id[6]);
	temp.push_back(id[7]);
	*/
	return temp;
}


void Student::setGrades(char newGrades, int index)
{
	grades[index] = newGrades;
	
}

char Student::getGrades(int index)
{
	return grades[index];
}


void Student::setGpa(float newGpa)
{
	gpa = newGpa;

}

float Student::getGpa()
{
	return gpa;
}



istream& operator>>(istream& cin, Student &studentObject)
{

		char grade;

		//float studentObject.gpa=0;
		cout << "Enter " << studentObject.name << "'s Grades" << endl;

		for ( int y=1; y<6; y++ )
		{
			cout << "Grade # " << studentObject.name << "'s Letter Grade: ";
			cin >> grade;

			switch(grade)
			{
			case 'A': case 'a': studentObject.gpa=studentObject.gpa+4;
				break;
			case 'B': case 'b': studentObject.gpa=studentObject.gpa+3;
				break;
			case 'C': case 'c': studentObject.gpa=studentObject.gpa+2;
				break;
			case 'D': case 'd': studentObject.gpa=studentObject.gpa+1;
				break;
			case 'F': case 'f': studentObject.gpa=studentObject.gpa+0;
				break;
			default: cout << "A Valid Letter Grade is A, B, C, D, or F " << endl;
				y--;
			}
		}

		studentObject.gpa = studentObject.gpa/5;
		return cin;
}

ostream& operator<<(ostream& cout, const Student &studentObject)
{

	return cout;
}


Student::Student()
{

char name[46] = "";
 
char address[56] = "";

char city[16] = "";

char state[2] = "";

char zipCode[5] = "";

char id[8] = "";

char grades[5] = {' '};

float gpa = 0.0;

}

Last edited on
And the main.cpp file:


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
/*
Module7-Assignment7.cpp : main project file.
Written by Schuett, Hugh for Assignment 2, Module 2
10SS_INFO_1532_WW - C++ Programming II, Metropolitan Community College
Modified by Russell, for Assignment 2, Module 2, MCC, JUNE 2010
Modified by Russell, for Assignment 6, Module 6, MCC, JULY 2010
Modified by Russell, for Assignment 7, Module 7, MCC, AUG 2010

*/

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <conio.h>
#include <string>
#include "Student.h"


/*

For this project you are going to take the last project, #6 (the grades program), and this time you are going to add operator overloading.  
	Remember the programming example at the end of the chapter is a great example of this.
Project Requirements:
<!--[if !supportLists]-->1.     <!--[endif]-->A class object of this class will be all the information for one student.
<!--[if !supportLists]-->2.     <!--[endif]-->You will have an array (4) of the objects, one element for each student.
<!--[if !supportLists]-->3.     <!--[endif]-->You will overload the extraction operator (“>>”).  The overloaded operator will then 
	perform all of the grade input for that individual.  The code in your main will look like this:  cin >> students[counter];  
	Where students is the array of objects and counter is the subscript.
<!--[if !supportLists]-->4.     <!--[endif]-->You will overload the insertion operator (“<<”).  The overloaded operator will then 
	perform all of the grade output for that individual.  The code in your main will look like this:  cout << students[counter];  Where 
	students is the array of objects and counter is the subscript.

*/

Student students[];

void gradeRecursion(int);
void displayOutput();

using namespace std;

int main ()
{
	/*
	name = new string[4];

	//DEBUGGING
	//cout << "\n\n " << &name << "\n\n";
	//DEBUGGING

	*name = "Freddie";
	*(++name) = "Jane";
	*(++name) = "Jonathan";
	*(++name) = "Mary";

	//DEBUGGING
	//cout << "\n\n " << &name << "\n\n";
	//DEBUGGING

	name=name-3;
	totalGPA = new double[4];
	*/


	Student students[3];
	students[0].setName("Freddie");
	students[1].setName("Jane");
	students[2].setName("Jonathan");
	students[3].setName("Mary");

	
	gradeRecursion(3);

	displayOutput();  

	cout << "\nPress any key to continue ..." << flush;
	_getch();

	/*
	delete [] name;
	delete [] totalGPA;
	name  = 0;
	totalGPA = 0;
	*/

	return 0;
}

void gradeRecursion(int numGradesToGet)
{
	
	if (numGradesToGet >= 0)
	{
		cin >> students[1];
		
		system("cls");

		if (numGradesToGet > 0)
		{
			gradeRecursion(numGradesToGet-1);
		}

	}
}

void displayOutput()
{
	
	cout << fixed << showpoint << setprecision(3);
	cout << setw(30) << left << "Student" << right << "GPA\n " << endl;

	for( int x=3; x>=0; x-- )
	{
		//cout << students[x];
		//cout << setw(30) << left << name[x] << right << totalGPA[x]/5 << endl;
	}
}
I'm not trying to be impatient.. just realized I didn't really ask a clear question.


Can someone help me diagnose these linker errors? Or at least point me to a resource that can assist me with debugging linker errors?
I've been fiddling, and found out when I comment out Line 94 in Module 7 - Assignment 7.cpp:


 
		//cin >> students[numGradesToGet]; 


it compiles and links correctly.. but obviously this is needed.. I will continue to work as I am very stubborn and usually grind away until I find answers but would still appreciate any assistance =D
Changed some 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
void gradeRecursion(int numGradesToGet)
{
	
	if (numGradesToGet >= 0)
	{
		
		
		//char grade;

		cout << "Enter " << students[numGradesToGet].getName() << "'s Grades" << endl;

		for ( int y=1; y<6; y++ )
		{
			cout << "Grade # " << students[numGradesToGet].getName() << "'s Letter Grade: ";
			
			cin >> students[numGradesToGet];

			switch(students[numGradesToGet].getGrade())
			{
			case 'A': case 'a': students[numGradesToGet].setGpa(students[numGradesToGet].getGpa()+4);
				break;
			case 'B': case 'b': students[numGradesToGet].setGpa(students[numGradesToGet].getGpa()+3);
				break;
			case 'C': case 'c': students[numGradesToGet].setGpa(students[numGradesToGet].getGpa()+2);
				break;
			case 'D': case 'd': students[numGradesToGet].setGpa(students[numGradesToGet].getGpa()+1);
				break;
			case 'F': case 'f': students[numGradesToGet].setGpa(students[numGradesToGet].getGpa()+0);
				break;
			default: cout << "A Valid Letter Grade is A, B, C, D, or F " << endl;
				y--;
			}
		}

		students[numGradesToGet].setGpa(students[numGradesToGet].getGpa()/5);
		
		system("cls");

		if (numGradesToGet > 0)
		{
			gradeRecursion(numGradesToGet-1);
		}

	}
}


and

1
2
3
4
5
6
istream& operator>>(istream& cin2, Student &studentObject)
{

		cin2 >> studentObject.grade;
		return cin2;
}


and still getting errors:

1>Microsoft (R) Windows Resource To Object Converter Version 9.00.21022.08
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>adding resource. type:ICON, name:1, language:0x0409, flags:0x1010, size:744
1>adding resource. type:ICON, name:2, language:0x0409, flags:0x1010, size:296
1>adding resource. type:GROUP_ICON, name:1, language:0x0409, flags:0x1030, size:34
1>Module 7 - Assignment 7.obj : error LNK2020: unresolved token (0A0002A6) "class Student * students" (?students@@3PAVStudent@@A)
1>Module 7 - Assignment 7.obj : error LNK2001: unresolved external symbol "class Student * students" (?students@@3PAVStudent@@A)
1>I:\College\~Summer 2010\10SS_INFO_1532_WW - C++ Programming II\Week 8 - Module 7\Module 7 - Assignment 7\Debug\Module 7 - Assignment 7.exe : fatal error LNK1120: 2 unresolved externals
1>Build log was saved at "file://i:\College\~Summer 2010\10SS_INFO_1532_WW - C++ Programming II\Week 8 - Module 7\Module 7 - Assignment 7\Module 7 - Assignment 7\Debug\BuildLog.htm"
1>Module 7 - Assignment 7 - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========



I have searched everywhere, and linkers usually have to do with lib files.. I have no additional lib files :(


Solved the problem.. thankfully I posted on another forum and somehow moving

Student students[4];

from where it was to where

Student students[]; was.. fixed it..

Can someone please explain why, and how this did it so I won't fall prey to such a weird mistake again?
The difference between Local and Global variables



By the way - this is incorrect. (you are creating local variables rather than initializing the class
member variavles)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Student::Student()
{

char name[46] = "";
 
char address[56] = "";

char city[16] = "";

char state[2] = "";

char zipCode[5] = "";

char id[8] = "";

char grades[5] = {' '};

float gpa = 0.0;

}
Last edited on
How? The above code should be creating class member variables.

It is contained within the constructor of the class, so when the class is created, those variables are also going to be created, within the scope, and members of, said class.


Confused,

Russell
Last edited on
You are indeed confused.
the above code creates local variables same as they would be in any other function.

When you create a variable of a class - all it data members are automatically created.

You cannot create new class members in a constructor.

What you probably wanted to do was to set values for the class data members (refer to the class declaration in the header file).

You need to re-read about constructors and initialization lists


Last edited on
so the above code needs to be changed to
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
 name[46] = "";
 
 address[56] = "";

 city[16] = "";

 state[2] = "";

 zipCode[5] = "";

 id[8] = "";

 grades[5] = {' '};

gpa = 0.0;


because each of those member variables have already been declared to hold enough memory for each datatype.. (float for gpa, 5 char array for grades.. etc..) right? I have known this before.. I don't know why I had those in there.. but I didn't notice what you were talking about until you pointed it out.. I definitely need to practice more
Anyway, you now have the issue of assignment to class member arrays. (this is always a pain)
So an easy fix for you would be:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Student::Student()
{
	 name[0] = '\0';	 
	 address[0] = '\0';	   
	 city[0] = '\0';	
	 state[0] = '\0';	 
	 zipCode[0] = '\0';	   
	 id[0] = '\0';
	
	 //I assume that grades will treaded as 5 individual chars
	 grades[0] = ' ';
	 grades[1] = ' ';
	 grades[2] = ' ';
	 grades[3] = ' ';
	 grades[4] = ' ';
	 
	 gpa = 0.0;
}


But all being said - it is a strange way you have written the program - with all those conversions
between char arrays and std::string
Last edited on
Yea , our instructor had us start by writing a character array, and for some reason, at the end of the assignment 2 one, (as you can see in the citation) whenever I printed out grades[], it would print out the previous object member, then the grades, then the next member variable.. I dont remember exactly but it was really throwing me off.. I had to explicitly chose to print each element of the character array, and never did switch all the way over to strings..

So, I know '\0' is the null character for a character variable.. but why do you just initiate the first character of the array to null instead of each element to some blank, or placeholder value?
Because '\0' indicates the end of the string. If you put it in the place of the first character, your string will be treated as an "empty" string, no matter what the values of the following characters are.
Ok.. let me see if i'm getting it..

1
2
3
4
5
6
7
8
9
10

//say

char charNameArray[10];
charNameArray[0] = '\0';

string test = "";

cout << 1 << charNameArray << test << 0;


This will output


10


right?

and is this legal?

1
2
3
4
5
6
7

//with the above variables still defined..

charNameArray[] = "Stuff";

test = charNameArray;


I've read up on character arrays and strings so many times but the way my program acted that one time threw me off..

Why would anyone ever really need to use character arrays? besides taking control of memory use with a dynamic character array instead of a string..?
SgtPooki wrote:
This will output
10
right?

Yes.

SgtPooki wrote:
and is this legal?

1
2
3
4
5
//with the above variables still defined..

charNameArray[] = "Stuff";

test = charNameArray;

The second statement yes. The first no. You can use that syntax only when declaring your array. Here, you would do it like this:

1
2
3
#include <cstring>
//...
strcpy(charNameArray,"Stuff");

http://cplusplus.com/reference/clibrary/cstring/

EDIT:

SgtPooki wrote:
Why would anyone ever really need to use character arrays?

Compatibility, speed, memory consumption.
Last edited on
Maybe I just need to shut up and wait till I learn more.. but..

Why couldn't we just add a class to the STL that allows us to use a dynamic character array as we currently use strings, so we get the best of both worlds..?
SgtPooki wrote:
to use a dynamic character array as we currently use strings

What do you mean?
Why couldn't we just add a class to the STL that allows us to use a dynamic character array as we currently use strings,


It's already there. It's called std::string.
Why couldn't we just add a class to the STL that allows us to use a dynamic character array as we currently use strings,
*Scratches head*
What? That question doesn't make any sense. "Why couldn't we have a class like string that does the same string does?" Maybe you thought string was an intrinsic like in BASIC?
If you can code a character array to manage memory more effectively than a string can, why not improve the way strings function?

I don't really know of any other way to ask it, but like I said; I probably need to learn more first before asking these types of questions. It is probably a really dumb question, but right now, I don't see it.
Last edited on
Pages: 12