enter image description here
I am supposed to call the function randint to my main function but for some reason it doesn't work. I have 3 files: randint.cpp, randint.h, and main.cpp. And I am supposed to call the function from randint.cpp. I am not sure if I am supposed to just declare the function in the header file and and write the definition in the cpp file.
main.cpp
#include "std_lab_facilities_5.h"
#include "randint.cpp"
#include "randint.h"
int main()
try {
int x = randint();
cout << x;
return 0;
}
catch (exception& e) {
cerr << "error: " <<e.what() << '\n';
return 1;
}
catch (...) {
cerr << "Oops: unknown exception!\n";
return 2;
}
randint.cpp
#include "randint.h"
#include <chrono>
using namespace std::chrono;
//linear congruential pseudorandom number generator
int randint() {
//use the clock for an initial pseudorandom number
static long x = time_point_cast<microseconds>(system_clock::now()).time_since_epoch().count();
//calculate the next pseudorandom number
// parameters from glibc(?)
x = (((1103515245L * int (x)) & 0x7fffffff) + 12345)& 0x7fffffff;
return x;
}
randint.h
int randint();
In the .H file inside the class you want
public:
int randint();
and in the .CPP that you want to call the function you need:
randint randint; //<--- Telling the class in this case main that randint exists(second randint can be whatever name you prefer)
randint.randint(); //<--- Here you call the function
I would also recommend you to use the class wizard when creating new files.
Related
I've read that an #include header.h is a preprocessor (because of #), which means it gets processed before compilation.
Is that why my code can't run? Because I'm trying to make an if statement in main with my function from my header(that takes a parameter) and it won't work.
Source.cpp
#include <iostream>
#include "Header.h"
using namespace std;
int main(){
test(46);
if (test() > 30){
cout << "great";
}
else{
cout << "It needs to be higher";
}
system("PAUSE");
return 0;
}
Header.h
using namespace std;
int test(int x){
return x;
}
That isn't the problem. I suspect you might be getting a compiler error message (or linker error) because you have declared test(int x) with an integer parameter and then you call it with no parameter, e.g.: test().
I've modified your code to include an integer result:
int main(){
int result = test(46); // Save the result of calling the function
if (result > 30){ // Test the value of the result
cout << "great";
}
else{
cout << "It needs to be higher";
}
system("PAUSE");
return 0;
}
The test function in Header.h file takes a int as parameter.But in your code you lose it.Pass a int to test function like this.
if (test(42) > 30)
You will get the output: great.
I have written a class that returns a random string after you provide a seed, a sequence length, and a character set as shown below.
I would like to know how to catch any bad input, such as setting the seed to 0 or to a negative number.
The examples that I have seen have just used cout to send an error message and then exit(1); I am thinking about putting a bool flag as a private variable and setting it to false when invalid input is detected. Then after you attempt to generate a random string with this class you would just check that flag through an accessor function.
Is there a better and/or standard way of handling this that will not just exit the program like exit(1)? Any general input about the class is welcomed also. Thanks for the assistance.
RandomString.h
// This is the header file randomstring.h. This is the interface for the class RandomString.
// Values of this type are a random string of the specified length from the specified string character set.
// The values that are needed for input are a positive integer seed, an integer desired length, and a string character set.
// Uses the mt19937 random number engine with a uniform_int_distribution.
#ifndef RANDOMSTRING_H
#define RANDOMSTRING_H
#include <string>
#include <random>
using namespace std;
namespace RandomString
{
class RandomString
{
public:
RandomString(double newSeed, unsigned int newLength, string newCharacterSet); // Initializes the RandomString object with the provided arguments.
RandomString(); // Initializes the seed to 1, the length to 0, and the character set to '0'.
double getSeed();
unsigned int getLength();
string getCharacterSet();
string getSequence();
void setSeed(double newSeed); // Sets the new seed but does not produce a new random sequence.
void setLength(unsigned int newLength); // This is the length of randomSequence.
void setCharacterSet(string newCharacterSet);
void generateNext(); // Generates the next random sequence.
private:
double seed;
unsigned int length;
string characterSet;
string randomSequence;
mt19937 engine;
};
} // RandomString namespace
#endif
RandomString.cpp
// This is the implementation file randomstring.cpp. This is the implementation for the class RandomString.
// The interface for the class RandomString is in the header file randomstring.h.
#include "stdafx.h"
#include <string>
#include <random>
#include "randomstring.h"
using std::string;
using std::uniform_int_distribution;
namespace RandomString
{
RandomString::RandomString(double newSeed, unsigned int newLength, string newCharacterSet)
{
setSeed(newSeed);
setLength(newLength);
setCharacterSet(newCharacterSet);
}
RandomString::RandomString()
{
seed = 1;
length = 0;
characterSet = '0';
}
double RandomString::getSeed()
{
return seed;
}
unsigned int RandomString::getLength()
{
return length;
}
string RandomString::getCharacterSet()
{
return characterSet;
}
string RandomString::getSequence()
{
return randomSequence;
}
void RandomString::setSeed(double newSeed)
{
seed = newSeed;
engine.seed(seed);
}
void RandomString::setLength(unsigned int newLength)
{
length = newLength;
}
void RandomString::setCharacterSet(string newCharacterSet)
{
characterSet = newCharacterSet;
}
void RandomString::generateNext()
{
randomSequence.resize(length);
uniform_int_distribution<> distribution(0,characterSet.length() - 1);
for (int i = 0; i < length; i++)
{
randomSequence[i] = characterSet[distribution(engine)];
}
}
} // RandomString namespace
Finally, here is the test program that I am using.
// test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "randomstring.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
do
{
double seed = 0;
unsigned int length = 0;
cout << "Enter seed: ";
cin >> seed;
cout << "Enter length of string: ";
cin >> length;
cout << endl;
RandomString::RandomString randomTest(seed,length,"ABCDEFGHJKLMNPQRSTUVWXYZ1234567890");
cout << "class RandomString" << endl;
cout << "seed: " << randomTest.getSeed() << endl;
cout << "length: " << randomTest.getLength() << endl;
randomTest.generateNext();
cout << "random sequence: " << randomTest.getSequence() << endl;
randomTest.generateNext();
cout << "next random sequence: " << randomTest.getSequence() << endl << endl;
}while(true);
}
Throw an exception
void RandomString::setSeed(double newSeed)
{
if (newSeed <= 0) {
throw std::runtime_error("seed should be positive");
}
seed = newSeed;
engine.seed(seed);
}
User would have to use try catch to handle error, else std::terminate is called.
How about letting the user have another chance at giving a good input?
What is the next thing the user will do after they find out they have put in a bad input? There is a high chance they will try again with a good input so just ask for another one.
while(true)
{
cout << "Enter seed: ";
cin >> seed;
if(seed > 0)
{
cout << "ERROR: Seed must be greater than 0." << endl;
break;
}
}
To answer your question about the bool error flag, I wouldn't do it that way. I have no need for bad data that was generated from a bad seed. No data is better than bad data. I generally try to "fail early, fail often", meaning I should stop and report the error as soon as I realize it exists.
If you were set on storing it the error flag, I'd have generateNext() or setSeed return false rather than nothing if there was a problem. Exceptions also work, but are slower and some projects don't like them in C++.
If you plan to have others use RandomString, I'd change the method signature from a double to uint (unsigned int). This would catch negative numbers being used at compile time rather than run time...again helping to fail even earlier. Sounds like this might not work in your classroom scenario, but is a good principle in the real world.
I'm attempting to practice some coding in my free time (combining a number of different interests of mine to help keep myself engaged) and I've encountered a odd error that I can't find the answer to. I have 4 files that I'm working with, two header files, one class definition file and a main file. I'm fairly confident I'm not including the Dice.h file more then once (however that is where the error points to and I'm not sure anymore, hence this question). What have I bungled here to produce these errors?
The error codes
Error 3 error LNK1169: one or more multiply defined symbols found (file path trimmed)
Error 2 error LNK2005: "int __cdecl dice(int,int)" (?dice##YAHHH#Z) already defined in Creature.obj (file path trimmed)
The filepath: c:\Users\Username\documents\visual studio2010\Projects\RPGTest\RPGTest\RPGTest.(error 3 referenced a .exe file, error 2 referenced a .obj file).
The code itself:
Dice.h
#ifndef SET_DICE_H_
#define SET_DICE_H_
#include <iomanip>
#include <iostream>
#include <stdlib.h>
using namespace std;
int dice(int number, int sides){
int total=0, dice;
srand(time(NULL));
int results=0;
do {
dice = rand()%sides+1;
total+=dice;
number--;
} while (number > 0);
results = total;
return results;
}
#endif
Creature.h
#ifndef CREATURE_H_
#define CREATURE_H_
#include <iomanip>
#include <iostream>
#include "Dice.h"
using namespace std;
class Creature {
public:
Creature(int,int,int,int,int,int,int,int,int,int,int,int);
void set_hp();
void set_saves();
void set_ac();
void set_bab();
void set_name();
void update_hp(int);
void update_ac(int);
void update_fsave(int);
void update_rsave(int);
void update_wsave(int);
int get_ac();
int get_hp();
int get_fsave();
int get_rsave();
int get_wsave();
int get_bonus(int);
int get_bab();
string get_name();
private:
int strength, dexterity, constitution, intellegence, wisdom, charisma;
int bab, fbsave, rbsave, wbsave;
int hdnum, hdsize;
int hp, fsave, rsave, wsave, ac;
string name;
};
#endif
Creature.cpp
#include "Creature.h"
#include <math.h>
#include <iostream>
using namespace std;
Creature::Creature(int strength,int dexterity,int constitution,
int intellegence,int wisdom,int charisma,int bab,int fbsave,
int rbsave,int wbsave,int hdnum,int hdsize){
strength = strength;
dexterity = dexterity;
constitution = constitution;
intellegence = intellegence;
wisdom = wisdom;
charisma = charisma;
bab = bab;
fbsave = fbsave;
rbsave = rbsave;
wbsave = wbsave;
hdnum = hdnum;
hdsize = hdsize;
}
int Creature::get_bonus(int stat){
int bonus = floor((double(stat)-10)/2);
return bonus;
}
void Creature::set_ac(){
ac=10+get_bonus(dexterity);
}
void Creature::set_hp(){
hp = dice(hdnum,hdsize) + get_bonus(constitution)*hdnum;
}
void Creature::set_saves(){
fsave = fbsave + get_bonus(constitution);
rsave = rbsave + get_bonus(dexterity);
wsave = wbsave + get_bonus(wisdom);
}
void Creature::set_bab(){
bab = hdnum;
}
void Creature::set_name(){
cout << "Please enter a name for this creature: ";
cout << "\nSorry! I don't work yet!";
cout << "\nInstead all creatures are named Larry!\n";
name = "Larry!";
}
void Creature::update_hp(int input){
hp = hp + input;
}
void Creature::update_fsave(int input){
fsave = fsave+input;
}
void Creature::update_rsave(int input){
rsave = rsave+input;
}
void Creature::update_wsave(int input){
wsave = wsave+input;
}
void Creature::update_ac(int input){
ac = ac+input;
}
int Creature::get_ac(){
return ac;
}
int Creature::get_hp(){
return hp;
}
int Creature::get_fsave(){
return fsave;
}
int Creature::get_rsave(){
return rsave;
}
int Creature::get_wsave(){
return wsave;
}
int Creature::get_bab(){
return bab;
}
RPGTest.cpp
#include "Creature.h"
#include <math.h>
//#include "Dice.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int str = dice(3,6), dex = dice(3,6), con = dice(3,6), intel = dice(3,6), wis = dice(3,6), cha = dice(3,6);
int fbs = dice(1,6), rbs = dice(1,6), wbs = dice(1,6);
int hdn = dice(1,10), hds = 8, bab = dice(1,8);
cout << "Welcome to RPG Creature Tester v0.1\n";
cout << "This .exe file is meant to test the creature class functions and definitions.\n";
cout << "This will be done by randomly generating and displaying a creature.\n";
cout << "What you don't see right now is the random generation of a creature.\n";
cout << "Once it's finished, the \'statsheet\' will be shown.\n";
cout << "Cheers!\n\n";
Creature potato (str, dex, con, intel, wis, cha, bab, fbs, rbs, wbs, hdn, hds);
potato.set_ac();
potato.set_hp();
potato.set_name();
potato.set_saves();
cout << "OUTPUT BRICK YAY\n";
cout << "Str: " << str << endl;
cout << "HP: " << potato.get_hp() << " AC: " << potato.get_ac() << " Fort/Reflex/Will Save: " << potato.get_fsave() << "/" << potato.get_rsave() << "/" << potato.get_wsave();
return 0;
}
Since I'm mainly self-taught I'm happy for any other advice but my main issue is that I'm not sure why I'm getting the "multiple" definition error. I did some research into other questions with similar error messages but I didn't see anything that immediately jumped out at me as "the answer".
Thanks all!
C++ works by compiling single translation units and then linking them together.
This means that each source file gets compiled on its own. Since the #include directive basically inserts all the code included, in your situation you end up having multiple translation units which define
int dice(int number, int sides) {
...
}
Compilation goes through fine but, when linking, multiple definition of this function are found so this generates the error.
To solve this problem you have two ways:
declare int dice(int, int) in a header file but define (implement it) in a source file
keep the definition as it is but prepend static to it. This tells the compiler that each translation unit will get its own dice method. This solution, although tempting, leads to binary size increase since you will have multiple implementation of the same method
so the write elm and getfileID functions require the cursor pos in the file
(write elm appends to the end, getFileID prints lines first to last)
#ifndef file_operations_header
#define file_operations_header
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include "First_classes_header.h"
class fileOPerations
{
private:
string line;
fstream f_myFileOut;
public:
fileOPerations();
void closeFile()
{
f_myFileOut.close();
}
int getFileID()
{
int counter = 0;
if (f_myFileOut.is_open())
{
while(f_myFileOut.good()){
getline(f_myFileOut,line);
++counter;
cout << line << endl;
}
}f_myFileOut.close();
return counter;
}
int writeElm(makeVector& mV,int i)
{
f_myFileOut.open("file.txt",ios::out|ios::app|ios::ate);
if (f_myFileOut.is_open())
{
f_myFileOut << mV.str_vector[i].counter << "\t";
f_myFileOut << mV.str_vector[i].name << endl;
}
else{
cout << "can't open file." << endl;
}
return 0;
}
friend class makeVector;
};
fileOPerations::fileOPerations():f_myFileOut("file.txt",ios::out|ios::app|ios::in){}
#endif // file_operations_header
and the call to getFileID in my main doesn't print anything because writeElm()
set the cursor pos to the end of the file.
#include <iostream>
#include <string.h>
#include <vector>
#include "First_classes_header.h"
#include "file_operations.h"
using namespace std;
int main()
{
fileOPerations fpObject;
makeVector vecObject;
int fileID = fpObject.getFileID();
while(true){
IDgenerator();
int genID = IDgenerator::GetID();
int currentID = fileID + genID;
string workingName = nameGetter::setName();
vecObject.vecSetter(currentID,workingName);
fpObject.writeElm(vecObject, currentID); // error within this function
fpObject.getFileID();
}fpObject.closeFile();
return 0;
}
Is it safe/effecient/effective to call f_myFileOut.open() with different parameters
in each separate function?
int getFileID()
{
f_myFileOut.open(("file.txt",ios::out|ios::app|ios::in)
int counter = 0;
...
...
int writeElm(makeVector& mV,int i)
{
f_myFileOut.open("file.txt",ios::out|ios::app|ios::ate);
Or should I set the cursor pos manually?
While it is certainly not efficient, to open/close the same file over and over again, it would be safe, and I'd even call it better coding style, because currently you are opening a file in one method and closing it in another, and in both cases it is not obvious from the function name that this is one of their side effects (contratry to e.g. closeFile()). Also you are already opening/closing the file in every iteration, so this would "only" double the open/close operations.
In general however, I'd definitively recommend to open the file once at the beginning of your program, close it at the end and e.g. use f_myFileOut.seekg (0,f_myFileOut.beg) and f_myFileOut.seekg (0,f_myFileOut.end) in between, to move your iterator around.
I'm creating a dice game. I'm building the files but get the following error:
No matching function for call to Dice::Dice
main.cpp:
#include "Dice.h"
#include <iostream>
using namespace std;
int main (){
Dice d(1,6);
cout << d.getRoll() << endl;
return 0;
}
Dice.h:
#ifndef DICE_H
#define DICE_H
class Dice
{
public:
Dice();
void getRoll(int m, int n);
};
#endif
Dice.cpp:
#include "Dice.h"
#include <ctime>
#include <iostream>
using namespace std;
Dice::Dice()
{}
void Dice::getRoll(int m, int n) {
srand(time(0));
(rand() % n)+m;
}
I see several problems with the code. Here's are my fixes and tips:
Firstly, your construction and method call of Dice will not compile:
Dice d(1,6); // you give arguments to the constructor
cout << d.getRoll() << endl; // your method call has no arguments
But you defined:
Dice(); // constructor takes no arguments
void getRoll(int m, int n); // method takes arguments
Secondly, srand only needs to be done once, not every time you call roll – maybe in the main function:
srand( (unsigned)time( NULL ) );
This seeds the generator so that you should get different random numbers every time the program runs. Call it only once, before the first dice roll.
Thirdly, your getRoll function returns nothing, meaning you get no value back. And you should name your variables according to what idea they represent in reality or your specification:
int Dice::getRoll(int maxEyes) { // Still no good abstraction
(rand() % maxEyes) + 1;
}
A real dice does not change its maxEyes at runtime. Why not try some object orientation instead of a function library class. Think about a real dice object! Here's a dice abstraction to start with:
main.cpp
#include "Dice.h"
#include <iostream>
using namespace std;
int main()
{
Dice::randomize(); // Try commenting this out and run the program several times, check the result, then comment it back in
Dice diceWith6Sides(6);
cout << "The 6 sided dice rolls a " << diceWith6Sides.getRoll() << endl;
cout << "The 6 sided dice rolls a " << diceWith6Sides.getRoll() << endl;
cout << "The 6 sided dice rolls a " << diceWith6Sides.getRoll() << endl;
Dice diceWith20Sides(20);
cout << "The 20 sided dice rolls a " << diceWith20Sides.getRoll() << endl;
cout << "The 20 sided dice rolls a " << diceWith20Sides.getRoll() << endl;
cout << "The 20 sided dice rolls a " << diceWith20Sides.getRoll() << endl;
return 0;
}
Dice.h
#ifndef DICE_H
#define DICE_H
class Dice
{
public:
Dice(int sides);
int getRoll();
static void randomize(); // Call only once
private:
int sides;
};
#endif
Dice.cpp
#include "Dice.h"
#include <time.h>
#include <stdlib.h>
Dice::Dice(int sides) :
sides(sides)
{
}
int Dice::getRoll()
{
return ((rand() % sides) + 1);
}
void Dice::randomize()
{
srand((unsigned)time(NULL));
}
Hope that is a good starting point. Have a lot of fun!