プログラムをオブジェクト指向コードとして書かなければならない課題を行う。
編集:VS2012コマンドラインコンパイラを使用して、コマンド「cl History.cpp -EHs」
コンパイルしようとすると、エラーが発生します
History.obj
History.obj : error LNK2019: unresolved external symbol "public: void __thiscall Course::setName(char * const)" (?setNam
e@Course@@QAEXQAD@Z) referenced in function _main
History.obj : error LNK2019: unresolved external symbol "public: void __thiscall Course::setTerm(char * const)" (?setTer
m@Course@@QAEXQAD@Z) referenced in function _main
History.obj : error LNK2019: unresolved external symbol "public: void __thiscall Course::setUnits(int)" (?setUnits@Cours
e@@QAEXH@Z) referenced in function _main
History.obj : error LNK2019: unresolved external symbol "public: void __thiscall Course::setGrade(char)" (?setGrade@Cour
se@@QAEXD@Z) referenced in function _main
History.obj : error LNK2019: unresolved external symbol "public: void __thiscall Course::printCourse(void)const " (?prin
tCourse@Course@@QBEXXZ) referenced in function "void __cdecl printClasses(class std::list<class Course,class std::alloca
tor<class Course> > &)" (?printClasses@@YAXAAV?$list@VCourse@@V?$allocator@VCourse@@@std@@@std@@@Z)
History.obj : error LNK2019: unresolved external symbol "public: static bool __cdecl Course::compareNames(class Course,c
lass Course)" (?compareNames@Course@@SA_NV1@0@Z) referenced in function _main
History.obj : error LNK2019: unresolved external symbol "public: static bool __cdecl Course::compareTerms(class Course,c
lass Course)" (?compareTerms@Course@@SA_NV1@0@Z) referenced in function _main
History.obj : error LNK2019: unresolved external symbol "public: static bool __cdecl Course::compareUnits(class Course,c
lass Course)" (?compareUnits@Course@@SA_NV1@0@Z) referenced in function _main
History.obj : error LNK2019: unresolved external symbol "public: static bool __cdecl Course::compareGrades(class Course,
class Course)" (?compareGrades@Course@@SA_NV1@0@Z) referenced in function _main
History.exe : fatal error LNK1120: 9 unresolved externals
私のファイルは、Course.h、Course.cpp、および History.cpp です。
Course.h ファイルは次のとおりです。
#ifndef COURSE_H
#define COURSE_H
//////////////////////////////
/* struct/class definitions */
//////////////////////////////
class Course
{
private:
char name[11];
char term[7];
int units;
char grade;
public:
void setName(char[]);
void setTerm(char[]);
void setUnits(int);
void setGrade(char);
void printCourse() const;
static bool compareNames(Course, Course) ;
static bool compareTerms(Course, Course) ;
static bool compareUnits(Course, Course) ;
static bool compareGrades(Course, Course) ;
static bool CourseCmp(Course, Course) ;
};
#endif
Course.cppは
// Lab 15 - Course.cpp
// Programmer: Dan Tahir
// Editor(s) used: notepad++
// Compiler(s) used: VC++ 2010 Express
#include "Course.h"
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::ios;
#include <iomanip>
using std::setprecision;
using std::setw;
#include <cstring>
int myStricmp(const char* dst, const char* src)
{
int f, l;
do
{
if (((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z')) f -= 'A' - 'a';
if (((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z')) l -= 'A' - 'a';
} while (f && (f == l));
return(f - l);
}
int myStrnicmp(const char* dst, const char* src, int count)
{
int f, l;
do
{
if (((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z')) f -= 'A' - 'a';
if (((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z')) l -= 'A' - 'a';
} while (--count && f && (f == l));
return (f - l);
}
//setters
void Course::setName(char enteredName[])
{
strcpy(name, enteredName);
}
void Course::setTerm(char enteredTerm[])
{
strcpy(term, enteredTerm);
}
void Course::setUnits(int enteredUnits)
{
units = enteredUnits;
}
void Course::setGrade(char enteredGrade)
{
grade = enteredGrade;
}
//getters
void Course::printCourse() const
{
cout.setf(ios::left, ios::adjustfield);
cout
<< setw(12)
<< name
<< setw(10)
<< term
<< setw(7)
<< units
<< setw(7) // doesn't matter for last row but whatev
<< grade << endl;
}
static bool Course::compareNames(Course a, Course b)
{
bool result = false;
if ( strcmp( a.name , b.name ) == 0 ) result = true;
return result;
}
static bool Course::compareTerms(Course a, Course b)
{
bool result = false;
if ( strcmp( a.term , b.term ) > 0 ) result = true;
return result;
}
bool Course::compareUnits(Course a, Course b)
{
bool result = false;
if ( a.units > b.units ) result = true;
return result;
}
bool Course::compareGrades(Course a, Course b)
{
bool result = false;
if ( a.grade > b.grade ) result = true;
return result;
}
/*//////////////////
COURSE COMPARE
//////////////////*/
bool Course::CourseCmp ( const Course a, const Course b)
{
// validate string length
if ( ( strlen( a.term ) != 6) || ( strlen( b.term ) != 6 ) )
{
if ( myStricmp( a.name, b.name ) < 1 )
return true;
else
return false;
}
// handle ties
if( myStricmp( a.term, b.term ) == 0 )
{
if ( myStricmp( a.name, b.name ) < 1 )
return true;
else
return false;
}
// compare the years
int yearA = atoi( a.term + 2 );
int yearB = atoi (b.term + 2);
if( yearA < yearB )
return true; // termA comes first
if( yearA > yearB )
return false; // termB comes first
// compare semesters in case of same year
if( myStrnicmp( a.term, "SP", 2 ) == 0 )
return true;
if( myStrnicmp( a.term, "SU", 2 ) == 0 )
return myStrnicmp( b.term, "SP", 2 ) ? true : false;
return false; // does this if myStrnicmp would == 0 for FA
}
History.cppは
#include "Course.h"
#include <fstream>
using std::fstream;
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::ios;
#include <iomanip>
using std::setprecision;
using std::setw;
#include <list>
using std::list;
#include <sstream>
using std::ostringstream;
#include <vector>
#include <cctype> // use for: tolower(), toupper()
#include <cstdlib> // use for: atof(), atoi()
///////////////////////
/* const definitions */
///////////////////////
/////////////////////////
/* function prototypes */
/////////////////////////
void printClasses(list<Course>& );
void restoreList(list<Course>&);
void saveList(list<Course>&);
///////////////////
/* main function */
///////////////////
int main()
{
/////////////////
/* TITLE BLOCK*/
/////////////////
{
// print my name and this assignment's title
cout << "Lab 15 - History.cpp" << endl;
cout << "Programmer: Dan Tahir" << endl << endl;
}
////////////////////////
/* ASSIGNMENT CONTENT */
////////////////////////
list<Course> courseList;
// begin data import loop
while (true)
{
/*
data import - user choice entry
ask the user whether to read Course history from the file
*/
cout << "Would you like to import your saved Course data?" << endl;
cout << "[y] to import, [n] to start with a blank list:" << endl;
char yOrN = 0;
cin >> yOrN;
cin.ignore(1000,10);
cout << endl;
yOrN = tolower(yOrN);
/*
data imort loop - userchoice response statement
- if user said y
- read from file
- set tail
- break
- if user said n, break
- for any other input output an error message then rerun the loop
*/
if ( 'y' == yOrN )
{
// god willing, the list will be loaded here
restoreList(courseList);
// exit loop
break;
}
else if ( 'n' == yOrN )
{
// exit loop
break;
}
else
{
cout << "Invalid entry! Press [ENTER] to retry" << endl;
cin.get();
}
}
// begin print/add classes loop
while (true)
{
/*
ask the user to add a Course.
take input from the user for the if statement below
y or n - y to add a class, n to quit
use tolower so Y/N work too
*/
cout << "would you like to add a Course to your schedule?" << endl;
cout << "[y] to add, [n] to print ordered Courselists, then quit: ";
char yOrN = 0;
cin >> yOrN;
cin.ignore(1000,10);
cout << endl;
yOrN = tolower(yOrN);
/*
BEGIN USER Y/N IF STATEMENT
- if user said y, run the add-class dequence in that
if consequential
- if user said n, print again then exit the print/add loop
- for any other input output an error message then rerun the loop
*/
if ('y' == yOrN)
{
/*
Course input sequence
- begin by declaring a new Course and assigning it
to a pointer
- take input from the user on a single line, then output to the pointed Course's data members
*/
Course courseToAdd;
cout <<"Please enter your Course information on a single line as follows:" << endl
<< "[CourseNAME] [TERM] [UNITS] [GRADE]" << endl << endl;
char tempName[11];
cin >> tempName;
courseToAdd.setName(tempName);
char tempTerm[7];
cin >> tempTerm;
courseToAdd.setTerm(tempTerm);
// added all this to make sure only a single
// digit is taken, note - ask if there's a
// better way to do this
char unitBufferA[32];
char unitBufferB[2] = {0};
cin >> unitBufferA;
unitBufferB[0] = unitBufferA[0];
courseToAdd.setUnits( atoi( unitBufferB ) );
char tempGrade;
cin >> tempGrade;
courseToAdd.setGrade(tempGrade);
cin.ignore(1000, 10);
// end Course input sequence
/*
Course ADDITION SEQUENCE
- add new Course at (i guess the front) of list
- i guess all of this is handled by pushback basically
*/
courseList.push_back(courseToAdd);
// end Course addition sequence
}
else if ( 'n' == yOrN )
{
// nothin fancy here just print and exit
cout << "your Course schedule: " << endl << endl;
printClasses(courseList);
break;
}
else
{
// silly user put a wrong answer, let them know
// they messed up
cout << "Invalid entry! Press [ENTER] to retry" << endl;
cin.get();
}
}// end print/add classes loop
// save list
saveList(courseList);
// print ordered Courses
cout << "Your Courses by Name: " << endl << endl;
courseList.sort(Course::compareNames);
printClasses(courseList);
cout << "Your Courses by Term: " << endl << endl;
courseList.sort(Course::compareTerms);
printClasses(courseList);
cout << "Your Courses by Credit Units: " << endl << endl;
courseList.sort(Course::compareUnits);
printClasses(courseList);
cout << "Your Courses by Grades: " << endl << endl;
courseList.sort(Course::compareGrades);
printClasses(courseList);
} // end main
//////////////////////////
/* function definitions */
//////////////////////////
void printClasses(list<Course>& courseList)
{
cout.setf(ios::left, ios::adjustfield);
cout << setw(12) << "Course" << setw(8) << "TERM" << setw(7) << "UNITS" << "GRADE" << endl;
cout << setw(12) << "----------" << setw(8) << "------" << setw(7) << "-----" << "-----" << endl;
for (list<Course>::iterator p = courseList.begin(); p != courseList.end(); p++)
{
p->printCourse();
}
cout << setw(12) << "----------" << setw(8) << "------" << setw(7) << "-----" << "-----" << endl << endl;
}
void restoreList(list<Course>& courseList)
{
fstream fin;
fin.open("Courses.dat", ios::binary|ios::in);
if (!fin)
return;
// read the number of objects from the disk file
int nRecs;
fin.read((char*)&nRecs, sizeof(int));
// read the objects from the disk file
// editing to use a queue insert here
// note: will have to set the tail outside of this function in the if statement that calls it, since I have to use this function's return to return the head and i'm not messing around with pointer-pointers
for (int i = 0; i < nRecs; i++)
{
Course courseToAdd;
fin.read((char*)&courseToAdd, sizeof(Course));
courseList.push_back(courseToAdd);
}
fin.close();
}
// end restoreList function
///////////////////////////
void saveList(list<Course>& courseList)
{
// open savestream
fstream fSave;
fSave.open("Courses.dat", ios::binary|ios::out);
// count objects in list
int courseCountInt = courseList.size();
// write count of classes to the file
fSave.write((char*)&courseCountInt, sizeof(int));
// write the classes to the file
for (list<Course>::iterator p = courseList.begin(); p != courseList.end(); p++)
{
Course c = *p;
fSave.write((char*)&c, sizeof(Course));
}
fSave.close();
}
History.cpp に #include "Course.cpp" を含めることはできません。
Course.h のクラス Course のメンバー関数は、Course.cpp で定義する必要があります。
関数を定義する際に何か間違ったことをしていると思いますが、それが何であるかは一生わかりません。
編集: 人々が残したコメントに返信するには -
私が使用しているコンパイル コマンドは、単一ファイル プログラムに使用した "cl History.cpp -EHs" です。問題はコードにあるはずだと思っていましたが、完全に見逃していたマルチファイルプログラムをコンパイルするための別のオプションセットまたは別のプロセスがある可能性があります。
「bool」関数の定義にはもともと「static」が含まれていませんでした。クラス内の宣言と .cpp 内の定義の間で何かが一致しないかどうかを確認する過程で、それを追加しました