I have a project with one main file (assign2.cpp
), one header file (arithcard.hpp
) and another file named arithcard.cpp
file.
In the header file I've defined the class and all the methods to be used. In the arithcard.cpp
I'll be using those methods and in my assign2.cpp
file I'll be calling them.
When I build the project it gives 4 errors for all times times I call a method defined in header file.
Error is:
"Unidentified reference to '(function)'"
I've included the header file in both of .cpp
files.
I'm using Eclipse and minGW. Can anybody help me out here?
O yeah! the code. Sorry for so many comments. It's because it's an assignment.
assign2.cpp
#include <iostream>
#include <sstream>
#include <string>
#include <limits>
#include <random>
#include "arithcard.hpp"
// File-local anonymous namespace
namespace {
int verbosity = 1 ;
}
/*
Read in the files of cards, then loop: query the user to specify a
question, print the question, check the answer. Terminate when the user
types an empty line instead of specifying a question.
*/
int main (int argc, const char *argv[])
{
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " <datafile>" << std::endl ;
return (1) ;
}
std::string dataFile(argv[1]) ;
bool result = false ;
int cardCnt = -1 ;
ArithCard *cards = nullptr ;
/*
Parse the file of questions & answers. A false return value indicates an
absent file or other i/o error. It's also possible the file is present but
contains no valid questions.
*/
result = ArithCard::readCards(dataFile,cardCnt,cards);
if (!result) {
if (verbosity >= 1) {
std::cout
<< "Cannot locate file with questions; exiting." << std::endl ;
}
return (1) ;
}
if (cardCnt == 0) {
if (verbosity >= 1) {
std::cout << "Card file was empty, exiting." << std::endl ;
}
return (1) ;
}
/*
Create a random number generator and distribution to use below.
*/
std::minstd_rand generator ;
std::uniform_int_distribution<int> randNum(1,cardCnt) ;
/*
Set up to ask the user to specify questions and start a loop. Note
that an empty line is the only way to end this loop. Given the context
(valid user input is small integers), go with a fixed maximum line size.
*/
const int MAXLINE = 120 ;
char inBuf[MAXLINE] ;
do {
/*
Prompt the user to select a question. Exit on an empty line. Use getline
because stream i/o with '>>' will eat empty lines and never return.
*/
std::cout
<< "Enter a number between 1 and " << cardCnt
<< " (0 for random, enter to quit): " ;
std::cin.getline(inBuf,MAXLINE) ;
if (inBuf[0] == '\0') {
std::cout << "Exiting." << std::endl ;
break ;
}
/*
Make sure the answer is a valid integer, and nothing but a valid integer. If
the user specifies `0', pick a card at random.
*/
std::istringstream parseStream(inBuf) ;
int userNumber = -1 ;
parseStream >> userNumber ;
if (parseStream.fail()) {
std::cout
<< "The string '" << inBuf << "' is not a valid number."
<< std::endl ;
continue ;
}
if (!parseStream.eof()) {
std::cout
<< "The string '" << inBuf << "' contains more than an integer."
<< std::endl ;
continue ;
}
if (userNumber < 0 || userNumber > cardCnt) {
std::cout
<< "The number " << userNumber << " is out of range." << std::endl ;
continue ;
}
if (userNumber == 0) {
userNumber = randNum(generator) ;
}
userNumber-- ;
/*
Display the question, then read and check the user's answer.
*/
cards[userNumber].displayQuestion(std::cout) ;
result = cards[userNumber].checkAnswer(std::cin) ;
if (result == true) {
std::cout << "Correct!" << std::endl ;
} else {
std::cout
<< "Incorrect; the correct answer is "
<< cards[userNumber].getAnswer() << std::endl ;
}
} while (true) ;
/*
Done! Delete the card array and return.
*/
delete[] cards ;
return (0) ;
}
arithcard.hpp
#include <iostream>
#include <string>
/*
Defines the class ArithCard, for handling arithmetic flash cards.
You may not modify the public method declarations provided below. The main
program used to test your solution will assume that these methods exist.
You can add private attributes and methods as you need them.
You may find it convenient to add additional public methods for testing.
Keep in mind that your code must work with the unmodified main program
or it will fail automated testing.
*/
class ArithCard {
public:
// Default constructor
ArithCard() ;
/*
Read arithmetic questions and answers from the specified file and
construct an array of ArithCard objects. A pointer to the array is
returned in cards. The number of ArithCard objects in the array is
returned in cardCnt.
If the file cannot be opened, the method returns false, otherwise it
returns true.
If there are no valid questions in the file, cardCnt is set to zero. If
cardCnt is zero, the value of cards is undefined and should not be used.
Calling readCards with cardCnt = 0 and cards == nullptr is the expected
way to use this method.
*/
static bool readCards(const std::string &fileName,
int &cardCnt, ArithCard *&cards) ;
/*
Write the question to the specified output stream.
*/
void displayQuestion(std::ostream &out) ;
/*
Read the user's answer from the specified input stream and compare it with
the correct answer.
Returns true if the answer is correct, false otherwise.
*/
bool checkAnswer(std::istream &in) ;
// Return the question as a string.
std::string getQuestion() ;
// Return the answer as a string.
std::string getAnswer() ;
// Return the answer as an integer.
int getAnswerValue() ;
private:
// Add your private methods and attributes here.
std::string question;
int answer;
} ;
arithcard.cpp
#include <iostream>
#include <string>
#include "arithcard.hpp"
#include <sstream>
bool readCards(const std::string &fileName, int &cardCnt, ArithCard *&cards)
{
return (true);
}
void displayQuestion(std::ostream &out)
{
}
bool checkAnswer(std::istream &in)
{
return (false);
}
std::string getQuestion()
{
return("question");
}
std::string getAnswer()
{
return ("answer");
}
int getAnswerValue()
{
return 1;
}