I'm doing the stanford course cs106b in C++, and I'm stuck and I can't seem to get it right. This probably a very easy fix for someone who knows this kind of stuff.
I have three files, one main.cpp and a randword.h and randword.cpp. In randword.h I have #include "simpio.h" which is a stanford library where GetLine() is defined. I can get GetLine() to work in the main.cpp file but when I try to compile I get "undefined reference to 'GetLine()'" in randword.cpp.
I use codeblocks and I have used the "Add files..." function.
Here's the code for main.cpp:
#include "randword.h"
/* Private function prototypes */
/* Main program */
randword rw;
int main() {
rw.initDictionary();
}
randword.h:
#ifndef RANDWORD_H_INCLUDED
#define RANDWORD_H_INCLUDED
#include <iostream>
#include <fstream>
#include <stdio.h>
#include "simpio.h"
#include "strutils.h"
using namespace std;
class randword{
public:
void initDictionary();
string chooseRandomWord();
string strArray[];
private:
};
#endif // RANDWORD_H_INCLUDED
random.cpp:
#include "randword.h"
using namespace std;
void randword::initDictionary(){
string fileName;
ifstream infile;
fileName = GetLine();
infile.open(fileName.c_str());
if(infile.fail()) cout << "Couldn't read file.";
return;
}
string randword::chooseRandomWord(){
string st1;
return st1;
}
Any help would be much appreciated! I suspect that this question was already posted, but I couldn't find it. Thanks!
try adding the library manually using code blocks
Open up your project
Right click your project and select build options..
select debugger
Go to linker settings
Under Link Librarys click "add"
Find your lib file, select it and keep as a relative path
Your project SHOULD run, if not reply here(as i explained something wrong)
randword.cpp does NOT have the library file needed to use GetLine, you may have included it inside your header file, but this does not carry over to randword.cpp. You need to include the library file just as you would in any other file in order to have access to it's functions.
//randword.cpp
#include <iostream>
#include "simpio.h" //include again!!!
//code here....
Related
While following the book C++ For Dummies, I have three files in my CodeBlocks project, main.cpp, Pen.h, and Pen.cpp. They look like this:
main.cpp:
#include <iostream>
#include "Pen.h"
//#include "Pen.cpp"
using namespace std;
int main()
{
Pen MyPen = Pen();
MyPen.test();
}
Pen.h:
#ifndef PEN_H_INCLUDED
#define PEN_H_INCLUDED
//#include "Pen.cpp" // Uncommenting this gives a different error
using namespace std;
class Pen
{
public:
// attributes omitted
// PROTOTYPES:
// other functions omitted
void test();
};
#endif // PEN_H_INCLUDED
Pen.cpp:
#include <iostream>
#include "Pen.h"
using namespace std;
//other function definitions omitted
void Pen::test()
{
cout << "Test successful." << endl;
}
When I run the code as listed above, I get an "undefined reference to `Pen::test()'" error. To fix this, I changed the #include statements at the top of main.cpp to:
#include <iostream>
//#include "Pen.h"
#include "Pen.cpp"
This works as intended and correctly prints out "Test successful."
My question is this: what in the world is the point of putting a function prototype in a header file if I have to import the .cpp file later on anyways?
EDIT: It turns out this was a problem with not knowing how to use Code::Blocks rather than with the C++ language.
Assuming you're using gcc, you can compile and link in one step by supplying multiple .cpp files via the command line.
g++ Pen.cpp main.cpp
clang should be similar.
clang++ Pen.cpp main.cpp
An #include should never reference a .cpp file. At all. There's no good reason to do it. Include your headers and then supply the names of all .cpp files when you compile. If your project gets big and you have too many .cpp files to reasonably list, then it's time to break out a makefile or similar.
In the main.cpp include the header file:
#include "Pen.h"
The Pen.h file it's ok.
You need to add the Pen.cpp file to the project tree.
Go to Project -> Add files... and add Pen.cpp
I am new to c++ so forgive me if this question doesn't make much sense, but I have the follow files:
// main.cpp
#include <iostream>
#include <fstream>
using namespace std;
#include "second.h"
int main () {
string filename;
cin >> filename;
ifstream fileIn;
if( !openFile(fileIn, filename) ) {
cerr << "Could not open file \"" << filename << "\"" << endl;
cerr << "Shutting down" << endl;
return -1;
}
return 0;
}
// second.h
#include <string>
#include <fstream>
bool openFile(ifstream& inFile, string filename);
// second.cpp
#include "second.h"
#include <iostream>
#include <fstream>
using namespace std;
bool openFile(ifstream& inFile, string filename) {
inFile.open(filename);
if (inFile.fail()) {
return false;
}
return true;
}
My question is, why does c++ need so much redundancy?
Why do I need to #include <iostream> and <fstream> for both main.cpp and second.cpp if main already calls them? Why does the header files also need to include the function parameters (ifstream& inFile, string filename)? This just seems like a waste, when the function in second.cpp already asks for it. Why not just say openFile(); in the header and have function in second.cpp as for the parameters? This may just be more of a rant, but I just want a deeper understanding as to why theses redundancies are needed. Or is there something I am missing?
The general issue
The reason you have to include relevant headers in each .cpp file is because such .cpp files are compiled separately and independently; in more formal parlance: They constitute different "translation units". See also:
What is a "translation unit" in C++
Sometimes, when multiple translation units must all include several headers, we define a common single header file which containing all these inclusions - so that the .cpp files only need to include the common header to get all their necessary inclusions. Remember that inclusion is basically pasting the contents of the included file instead of the #include directive, and parsing that file as well, so an include-in-an-include is the same as making a direct #include.
Your specific example
In your specific example,
You actually don't need to #include <iostream> in second.cpp, because you only seem to be using constructs from <fstream>.
You don't need to #include <fstream> in any of the .cpp files, because they #include "second.h", which in turn includes <fstream> (so that it gets included when they are compiled, as well).
You can include #include <iostream> and <fstream> into second.h and then include it to main.cpp. Don't forget to use Include Guard, when you link to header files.
main.cpp uses std::ifstream, std::cin, and std::cerr, this is why your example requires the includes in main.cpp.
You should
read about #include directive to understand this idea and what's going on during compilation.
I have two similar methods that open a file identically, but process them and return values a bit differently, yet while the first method does that successfully, the second method, which is called after the first one, fails.
I have tried changing the path to this file, its extension, but I think I miss some important knowledge about ifstream.
vector<User> Database::createUserDatabase()
{
vector<User> users;
ifstream inputFile;
inputFile.open(pathToFile, ios::in);
//Some file processing
inputFile.close();
return users;
}
And that works perfectly, while
vector<User> Database::createBookDatabase()
{
vector<Book> books;
ifstream inputFile;
inputFile.open(pathToFile, ios::in);
//Some file processing
inputFile.close();
return books;
}
fails to end whenever I check if the file has been opened or not using
inputFile.is_open()
These functions are defined in class files Database.cpp, User.cpp, Book.cpp, which are correctly linked to the main.cpp with the following content:
#include <iostream>
#include <cstdlib>
#include <string>
#include <cstring>
#include <sstream>
#include <vector>
#include <fstream>
#include "../lib/Book.h"
#include "../lib/User.h"
#include "../lib/Database.h"
using namespace std;
int main()
{
Database userDatabase("../database/users.txt", "users");
Database bookDatabase("../database/lmsdb.txt", "books");
vector<User> users = userDatabase.createUserDatabase();
vector<Book> books = bookDatabase.createBookDatabase();
return 0;
}
Here are my Project directories
Using gdb debugger, I have confirmed that the file is not being opened at all. I assume that I did not close the files properly, but I have a little knowledge of C++ yet (been learning it for only a week or so).
Looking forward to see what you can suggest reading/researching, yet I really would like to see a straightforward solution to this problem.
I assume that I did not close the files properly, [..]
Yes, but that probably isn't the cause of the issue. The C++ way is to not close them explicitly. Due to RAII, the ifstream will close itself once it goes out of scope (i.e. when the enclosing function terminates).
There are many reasons why a file could fail to open, including:
It doesn't exist.
Trying to open a read-only file in write mode.
The file is in use by another process. (Maybe you have it opened in an editor?)
Insufficient privileges (e.g. due to the file being protected).
I'm trying to make a header file called hippiewh. However, I have been running into some problems.
here's the code for the header file:
#include <iostream>
#include <string>
using namespace std;
#ifndef hippiewh_h
#define hippiewh_h
int askInt(string prompt)
{
int var_int;
cout << prompt;
cin >> var_int;
return var_int;
}
#endif
there are functions like that one for every data type. string, float, and so on.
I can't get this header file working with the online IDE and compiler at Compilr.com
The error i'm getting is:
hippiewh.h: No such file or directory
Andrew, I bet you didn't write the include like this #include "hippiewh.h".
and you did it like this #include <hippiewh.h> which is wrong for your own created header files.
If you put all the code here we could help you
It should work without hassle :/
You must include the file this way
#include "hippiewh.h"
After fixing the previous problem (see my one other question that I have asked). I had declared more classes.
One of these is called CombatAdmin which does various things: (Header file)
#ifndef COMBATADMIN_H
#define COMBATADMIN_H
#include <string> // Need this line or it complains
#include <Player.h>
#include <Sound.h>
#include <Enemy.h>
#include <Narrator.h>
using namespace std;
class Enemy;
class Player;
class CombatAdmin // Code yet to be commented here, will come soon.
{
public:
CombatAdmin();
void healthSet(double newHealth, string playerName);
void comAdSay(string sayWhat);
void playerFindsChest(Player *player,Weapon *weapon,Armour *armour);
void youStoleOurStuffEncounter(Player *player);
void comAdWarning(string enemyName);
void comAdAtkNote(string attack, double damage,string target,string aggresor);
void entDefeated(string entName);
void comAdStateEntHp(string ent, double hp);
void comAdStateScanResults(string enemyName, double enemyHealth);
string doubleToString(double number);
string intToString(int number);
bool isRandEncounter();
void randomEncounter(Player *player,Sound *sound,Narrator *narrator);
bool combatRound(Player *player, Enemy *enemy, Sound *sound, bool ran);
void playerFindsItem(string playerName,string itemName,double itemWeight,double playerWeight);
void playerFindsGold(string playerName,double coinCnt,double playerCoinCnt);
};
#endif // COMBATADMIN_H
It is then instanced in the main.cpp file like this: (Snippet of the main.cpp file)
#include <iostream> // Required for input and output
#include <Item.h> // Item header file.
#include <Weapon.h> // Header files that I have made for my classes are needed for this program
#include <sstream> // Needed for proper type conversion functions
#include <windows.h> // for PlaySound() and other functions like sleep.
#include <time.h> // Needed to seed the rand() function.
#include <mmsystem.h> // Not sure about this one, possibly defunct in this program.
#include <stdio.h> // Needed for a similar kind of output as iostream for various functions error msgs.
#include <irrKlang.h> // The header file of the sound lib I am using in this program.
#include <Narrator.h> // The narrators's header file.
#include <Pibot.h> // Other header files of classes.
#include <Armour.h>
#include <Player.h>
#include <Weapon.h>
#include <CombatAdmin.h>
using namespace irrklang;
using namespace std;
// Forward referenced functions
void seedRandom(); // Seeds the random number so it will be random as apposed to pseudo random.
string getPlayerName(string temp); // Gets the player's new name.
int main(int argc, char* argv[])
{
// Variables and object pointers declared here.
CombatAdmin *comAd = new CombatAdmin(); // Handles combat.
Narrator *narrator = new Narrator(); // The Narrator that says stuff
Pibot *piebot = new Pibot(); // PIbot, the player's trusty companion
string temp; // Temp string for input and output
However, when I try to compile the project, I get the following error:
C:\Documents and Settings\James Moran.HOME-B288D626D8\My Documents\C++ projects\Test Project\main.cpp|59|undefined reference to `CombatAdmin::CombatAdmin()'|
I am using the Code::Blocks IDE (ver 10.05), with the GNU GCC compiler. The project is of type "Console application". I am using windows XP 32 bit SP3.
I have tried changing to search directories to include where the object files are, but no success there.
As can be seen from the code, the narrator and PIbot are instanced just fine. (then used, not shown)
My question is, therefore, what do I need to do to stop these errors occurring? As when I encountered similar "Undefined reference to x" errors before using libraries. I had just forgotten to link to them in Code::Blocks and as soon as I did, they would work.
As this class is of my own making I am not quite sure about this.
Do say if you need more information regarding the code etc.
You have declared the default constructor (CombatAdmin()) and thus prevented the compiler from automatically generating it. Thus, you either need to 1) remove declaration of the default constructor from the class, or 2) provide an implementation.
I had this kind of error and the cause was that the CombatAdmin.cpp file wasn't selected as a Build target file: Prject->Properties->Build targets
Are you sure you've to include your header as:
#include <CombatAdmin.h>
?
I think you need to include your header file as:
#include "CombatAdmin.h"
And same for other headers written by you, like these:
#include "Armour.h"
#include "Player.h"
#include "Weapon.h"
//and similarly other header files written by you!
See this topic:
What is the difference between #include <filename> and #include "filename"?
My solution was just to add a line in the header before the class defenition:
class CombatAdmin;