Using C++, I declared the following static variable in a class SavingsAccount
static float *waitingInQueue;
But I'm not able to initialize the data pointed, I'm only able to initialize the address of the pointer as follows : float* SavingsAccount::waitingInQueue=0;
I would like the data of this pointer initialized at 0. I don't want to use a setter because I need to be able to initialized it once without using an object of the class SavingsAccount. I would like to do the following statement outside a function : *waitingInQueue=0;
Here is my header file :
#ifndef SAVINGSACCOUNT_H
#define SAVINGSACCOUNT_H
class SavingsAccount
{
public:
SavingsAccount();
float getInterestDue(){return *interestDue;};
float getAmountDue() {return *amountDue;};
int getArrivalTime() {return *arrivalTime;};
int getFinishTime() {return *finishTime;};
void setFinishTime(int newTime) {*finishTime=newTime;};
float computeInterestDue();
// compute the interest due...
float computeAmountDue();
// compute the total amount due
void waitingClient();
// increment *arrivalTime
void waitingProcess();
// increment *finishTime checking if there is not another client already processing, in that case make him wait during the previous client processing
void display();
// display the information about 1 client
void saveAccounts();
// save the information of the 20 clients
// void setWaitingInQueue(float x) {*waitingInQueue=x;}; <- can't be used
private:
float clientTable[8];
// information about a single client
static float globalTable[20][8];
static int clientCount;
float *customerID;
static float *arrivalTime;
static float *finishTime;
static const float depositType[6];
float *depositAmount;
static const float interestRate[12];
float *interestDue;
float *amountDue;
float *PtrDepType, *PtrRate;
static float *waitingInQueue;
};
#endif /* SAVINGSACCOUNT_H */
Here is my .cpp
#ifndef SAVINGSACCOUNT_CPP
#define SAVINGSACCOUNT_CPP
#include<cstdlib>
#include <iostream>
#include <ctime> // include to get the number of seconds since 1970 (srand))
#include <iomanip> // to set precision of numbers setprecision()
#ifdef WIN32
#include <windows.h> // for windows
#else
#include <unistd.h>
#endif // win32 // for unix
#include "SavingsAccount.h"
using namespace std;
float SavingsAccount::globalTable[20][8];
int SavingsAccount::clientCount=0;
const float SavingsAccount::depositType[6]={0.25, 0.5, 1, 2, 3, 5};
const float SavingsAccount::interestRate[]={1.71, 1.80, 2.07, 2.25, 2.25, 2.52, 2.70, 3.06, 3.24, 3.69, 3.60, 4.14};
float* SavingsAccount::arrivalTime;
float* SavingsAccount::finishTime;
float* SavingsAccount::waitingInQueue=0; // should be *waitingInQueue = 0;
SavingsAccount::SavingsAccount()
{
clientCount++;
int index;
srand(time(NULL)); //
index=rand()%6; //
customerID=&clientTable[0];
arrivalTime=&clientTable[1];
finishTime=&clientTable[2];
PtrDepType=&clientTable[3]; // &depositType[index]
depositAmount=&clientTable[4];
PtrRate=&clientTable[5]; // &interestRate[N]
interestDue=&clientTable[6];
amountDue=&clientTable[7];
*customerID=clientCount;
*PtrDepType=depositType[index];
*depositAmount=(rand()%49+1)*1000;
if (clientCount<=10) *PtrRate=interestRate[2*index]; // N=2*index
else *PtrRate=interestRate[2*index+1]; // N=2*index+1
}
float SavingsAccount::computeInterestDue()
{
*interestDue=*PtrDepType*(*depositAmount)**PtrRate*(1-0.2)/100;
}
float SavingsAccount::computeAmountDue()
{
*amountDue=*depositAmount+*interestDue;
}
void SavingsAccount::waitingClient()
{
if (clientCount==1) *arrivalTime=0;
else {
int milliseconds=(rand()%6+3)*1000; // random time in milliseconds
#ifdef WIN32 // for windows
Sleep(milliseconds);
#else // for unix
usleep(milliseconds * 1000); // nano seconds have to be multiplied by 1000
#endif // win32
*arrivalTime = *arrivalTime+milliseconds/1000;
}
}
void SavingsAccount::waitingProcess()
{
if(*finishTime < *arrivalTime)
{
*waitingInQueue =*arrivalTime-*finishTime;
}
int milliseconds=(rand()%6+2)*1000; // random time in milliseconds
#ifdef WIN32
Sleep(milliseconds);
#else
usleep(milliseconds * 1000);
#endif // win32
*finishTime= *arrivalTime + milliseconds/1000 + *waitingInQueue;
}
void SavingsAccount::saveAccounts()
{
globalTable[clientCount-1][0]=*customerID;
globalTable[clientCount-1][1]=*arrivalTime;
globalTable[clientCount-1][2]=*finishTime;
globalTable[clientCount-1][3]=*PtrDepType;
globalTable[clientCount-1][4]=*depositAmount;
globalTable[clientCount-1][5]=*PtrRate;
globalTable[clientCount-1][6]=*interestDue;
globalTable[clientCount-1][7]=*amountDue;
}
void SavingsAccount::display()
{
cout << setprecision(0) << setw(4) << right << clientTable[0];
cout << setprecision(0) << setw(7) << right << clientTable[1];
cout << setprecision(0) << setw(8) << right << clientTable[2];
cout << setprecision(2) << setw(10) << right << fixed << clientTable[3];
cout << setprecision(2) << setw(12) << right << clientTable[4];
cout << setprecision(2) << setw(7)<< right << clientTable[5];
cout << setprecision(2) << setw(12)<< right << clientTable[6];
cout << setprecision(2) << setw(12)<< right << clientTable[7] << endl;
}
#endif
The idea of the program is to display information about 20 clients that are arriving every x seconds (3static float *waitingInQueue; to increase the finishing time of all the client if needed.
If you have any other idea to easily simulated a queue I would be interested.
Even if *waitingInQueue = 0; were valid outside a function, it would be incorrect because you're initializing the pointer to null.
The easiest way to do what you're asking is something like this:
class SavingsAccount
{
...
private:
static float zero;
static float* waitingInQueue;
};
float SavingsAccount::zero = 0.0f;
float SavingsAccount::waitingInQueue = &SavingsAccount::zero;
You can initialise your static variable in many different ways -- but you should be asking a different question - "How can I get rid of my static variables?". static variables are often a sign that something is not quite right, and in that light I think you have a pretty large design problem here.
I'd group all your static variables into a Branch object. Then have each SavingsAccount have a pointer to their Branch. And add a newAccount() to Branch for creation. Then you have no more statics and everything is neater (and easier to test).
There also seems to be a lot of uses of pointers where non-pointer types would be OK, and cases where fixed length arrays are used, but would be improved by switching to std::vector<>
Related
Through Xsens MTw sensors I obtain live data which is displayed on a console. Xsens gives me an example code where the euler angles are obtained. For my case I need to obtain the acceleration data. According to the documentation, this information can be acquired using the structure called XsCalibratedData. I don't know how to get that information in the main of the code given by Xsens.
std::vector<XsEuler> eulerData(mtwCallbacks.size()); // Room to store euler data for each mtw
//std::vector<XsCalibratedData> accelerationData(mtwCallbacks.size()); //
unsigned int printCounter = 0;
while (!_kbhit()) {
XsTime::msleep(0);
bool newDataAvailable = false;
for (size_t i = 0; i < mtwCallbacks.size(); ++i)
{
if (mtwCallbacks[i]->dataAvailable())
{
newDataAvailable = true;
XsDataPacket const * packet = mtwCallbacks[i]->getOldestPacket();
eulerData[i] = packet->orientationEuler();
//accelerationData[i] = //I do not know what i have to put on here;
mtwCallbacks[i]->deleteOldestPacket();
}
}
if (newDataAvailable)
{
if (printCounter % 25 == 0)
{
for (size_t i = 0; i < mtwCallbacks.size(); ++i)
{
std::cout << "[" << i << "]: ID:" << mtwCallbacks[i]->device().deviceId().toString().toStdString()
<< ", Roll: " << std::setw(7) << std::fixed << std::setprecision(2) << eulerData[i].roll()
<< ", Pitch: " << std::setw(7) << std::fixed << std::setprecision(2) << eulerData[i].pitch()
<< ", Yaw: " << std::setw(7) << std::fixed << std::setprecision(2) << eulerData[i].yaw()
//<< ", Acceleration [1]> " << std::setw(7) << std::fixed << std::setprecision(2) << //Also do not know what i can put here
<< "\n";
}
}
++printCounter;
}
}
In the comments is where I think part of the code has to be placed but I don't know which one.
I leave some documentation that can be of help to see the structures and classes that are already created
XsEuler class used to get orientation Euler
XsCalibratedData structure to get acceleration data (i need to implement this)
in XsCalibratedData three vectors are created and each vector has three values at 0. I need the information from m_acc and be able to print it in my main along with the other euler angle variables
#ifndef XSCALIBRATEDDATA_H
#define XSCALIBRATEDDATA_H
#include "xstypesconfig.h"
#include "xsvector3.h"
struct XsCalibratedData;
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __cplusplus
#define XSCALIBRATEDDATA_INITIALIZER {XSVECTOR3_INITIALIZER, XSVECTOR3_INITIALIZER, XSVECTOR3_INITIALIZER}
#endif
XSTYPES_DLL_API void XsCalibratedData_construct(struct XsCalibratedData* thisPtr, const XsReal* acc, const XsReal* gyr, const XsReal* mag);
XSTYPES_DLL_API void XsCalibratedData_destruct(struct XsCalibratedData* thisPtr);
#ifdef __cplusplus
} // extern "C"
#endif
struct XsCalibratedData
{
XsVector3 m_acc; //!< Accelerometer data
XsVector3 m_gyr; //!< Gyroscope data
XsVector3 m_mag; //!< Magnetometer data
#ifdef __cplusplus
//! \brief Constructor \sa XsCalibratedData_construct
inline XsCalibratedData(): m_acc(0, 0, 0), m_gyr(0, 0, 0), m_mag(0, 0, 0)
{
}
//! \brief Copy constructor, copies the values from \a other to this
inline XsCalibratedData(const XsCalibratedData& other)
: m_acc(other.m_acc)
, m_gyr(other.m_gyr)
, m_mag(other.m_mag)
{
}
//! \brief Destructor
inline ~XsCalibratedData()
{}
//! \brief Assignment operator, copies the values from \a other to this
inline XsCalibratedData& operator = (const XsCalibratedData& other)
{
if (this != &other)
{
m_acc = other.m_acc;
m_gyr = other.m_gyr;
m_mag = other.m_mag;
}
return *this;
}
#endif
};
typedef struct XsCalibratedData XsCalibratedData;
#endif
This is the XsCalibratedData class details
I want to display the range of x and f(x) and keep f(x) in array but i always get this error:
invalid type 'float*[float]' for array subscript
can someone help me? I'm still stuck.
Here's the code:
#include <iostream>
#include <cmath>
#include <math.h>
using std::cin;
using std::cout;
using namespace std;
void displayValue(float funx[], float j, float x);
int main()
{
float num9[]={};
float a, r;
displayValue(num9, a, r);
return 0;
}
void displayValue(float funx[], float j, float x)
{
float i;
cout << "Please enter range of x: " << endl;
for (i=0; i<1; i++)
{
cin >> x >> j;
}
for (float i=1; i<=160.5; i++)
{
x+=0.5;
funx[i]=1/sin(x)+1/tan(x);
//1.2 Display f(x) and x within the range
}cout << x << " = " << funx[i] << "\n";
}
The problems you're trying to solve aren't actually problems you need to solve. There's a lot going wrong in this code that can simply be removed because you're using the wrong tools.
You don't need an array here. If you did you'd need to allocate one, not pass in something that's empty, or you'd be using it out of bounds. In C++ for arrays like this use std::vector.
That being said, here's a simplified version of the code:
#include <iostream>
#include <cmath>
#include <math.h>
// Don't add "using namespace std", that separation exists for a reason.
// Separate the math function to make it clear what's being done
float f(const float x) {
return 1/sin(x)+1/tan(x);
}
// Define your functions before they're used to avoid having to declare
// then later define them.
void displayValue(const float min, const float max, const float step = 0.5)
{
for (float x = min; x <= max; x += step)
{
// Note how the f(x) function here is a lot easier to follow
std::cout << "f(" << x << ") = " << f(x) << std::endl;
}
}
int main()
{
std::cout << "Please enter range of x: " << std::endl;
// Capture the range values once and once only
float min, max;
std::cin >> min >> max;
// Display over the range of values
displayValue(min, max);
return 0;
}
There's some important C++ fundamentals here:
float num9[]={}; is not an empty array that you can later add to, it is a permanently zero-length array, or in other words, it's useless.
Pay close attention to the variables you've defined and avoid defining them twice in the same scope.
Turn on all your compiler warnings while you're learning to be alerted to potential problems. C++ is full of nuances and gotchas.
In this code, once I run my program, the output for my death rate becomes corrupt. But all my variables are defined as double and there is no variable type change. Why is my output corrupt? Is it because my value is not being passed correctly?
#include <iostream>;
#include <iomanip>;
using namespace std;
//variable definition
class Population
{
private:
double population, births, deaths;
double b_rate, d_rate;
public:
void setpopulation(double p);
void setdeath(double death);
void setbirth(double b);
double getdrate();
double getbrate();
};
void Population::setpopulation(double p)
{
population = p;
}
void Population::setdeath(double death)
{
deaths = death;
d_rate = births / population;
}
void Population::setbirth(double b)
{
births = b;
b_rate = births/population;
}
double Population::getdrate()
{
cout << d_rate << endl;
return d_rate;
}
double Population::getbrate()
{;
return b_rate;
}
int main()
{
Population pop;
pop.setpopulation(100000);
pop.setdeath(7500);
pop.setbirth(8000);
cout << fixed << setprecision(2);
cout << "Death rate = " << pop.getdrate() << endl;
cout << "Birth rate = " << pop.getbrate() << endl;
return 0;
}
This is the reason. Try to be careful.
This is how you are calling you are functions.
pop.setpopulation(100000);
pop.setdeath(7500);
pop.setbirth(8000);
And here is your setdeadth() -
void Population::setdeath(double death)
{
deaths = death;
d_rate = births / population;
}
Since in main you are calling setdeadth first and in setdeath. You are using births which are not known, or you can say births is uninitialized. So it is undefined.
To correct it do.
pop.setpopulation(100000);
pop.setbirth(8000);
pop.setdeath(7500);
Call setbirth fist. Btw in don't think your formulas are correct. I didn't get why you are using birth in calculating death rate. It should be deaths. But I'm not pointing as it may be possible that you did that by choice. That is up to you.
From the code you provided, in the method setdeath you are making d_rate = births/population, you must be using death there. But at that time births is not initialized, so it takes the garbage value(not zero in all cases, it can be anything as inbuilt default are unknown) which is why you are getting the death rate wrong!!!
Thanks
Rajkumar
Ok, so I am pretty new to C++, I have a couple of questions about header files...
1.) Which variables should you declare, and which should you not in a header file?
2.) When you declare a variable in a header file, should you use extern?
Here is my header file:
#ifndef MAIN_H
#define MAIN_H
class Main
{
public:
int main(); //Constructor
virtual ~Main(); //Destructor
double initialVelocity;
double initialAngle;
private:
double degToRad(double angle);
void simulate(double angle, double velocity);
};
#endif
And here is my Main.cpp
/*******************************************************************
* This program will take input for initial velocity (fps), and a launch angle
* based on this information, the current posotion of the object thrown will be
* calculated until it hits the ground.
*
*
* Date: 30 August 2013
* Version 1.0
*
**/
# include "Main.h"
# include <iostream>
# include <fstream>
# include <cmath>
using namespace std;
/******************************************************************
* General Variables
**/
const int GRAVITY_FACTOR = -16;
const int GROUND = 0;
const double PI = atan(1.0)*4;
double initialVelocity;
double initialAngle;
/******************************************************************
* degToRad function.
*
* This function takes in an angle in degrees, and converts it to
* radians.
*
**/
double degToRad(double angle){
return angle * (PI/180);
}
/******************************************************************
* simulate function.
*
* Takes in the angle in radians, and the velocity. Calculates the
* path of the projectile, and displays it in the terminal.
*
**/
void simulate(double angle, double velocity){
cout << "Entering Simulation" << endl;
double time = 0;
double x = 1;
double y = 1;
double veloUp = 0;
double veloFo = 0;
veloUp = (velocity*sin(angle));
veloFo = (velocity*cos(angle));
cout << "Angle in radians: " << angle << endl;
cout << "Initial velocity upwards (fps): " << veloUp << endl;
cout << "Initial velocity forward (fps): " << veloFo << endl;
while(y >= GROUND){
x = veloFo * time;
y = GRAVITY_FACTOR*(time*time) + (veloUp * time);
cout << "(x, y) at time " << time << " is (" << x << ", " << y << ")" << endl;
++time;
} //while
cout << "Leaving Simulation" << endl;
} //simulate
/***************************************************************************
* The main function.
*
* Produces output to the console in order to coach the user on what to input.
**/
int main()
{
cout << "Execution Beginning" << endl;
cout << "Enter the inital velocity (feet per second):" << endl;
cin >> initialVelocity;
if(initialVelocity > 0){
cout << "Good. " << initialVelocity << " is a valid value for the initial velocity." << endl;
}
else{
cout << "ERROR: " << initialVelocity << " is not a valid value for the initial velocity." <<endl;
return 0;
}
cout << "Enter the initial angle in degrees (from the horizontal):" << endl;
cin >> initialAngle;
if(initialAngle >= 0 && initialAngle <= 90){
cout << "Good. " << initialAngle << " is a valid value for the initial angle." << endl;
}
else{
cout << "ERROR: " << initialAngle << " is not a valid value for the initial angle." << endl;
return 0;
}
simulate(degToRad(initialAngle), initialVelocity);
cout << "Ending Execution" << endl;
return 0;
}
Like I said, I am new to C++, can anyone please explain how these two interact, or what I should do to make them interact more efficiently. The program compiles, and runs correctly, but I am unclear on the protocol and uses of header files with a .cpp file. Also, which functions and variables should be in the private section of the header, and which should go in the public? Thank you.
I think you need to know 2 Things:
Whats the difference between declaration and definition.
you need a declaration to use a class or function (for the compiler to know its there)
the definition is the code that gets compiled (function body, initialization)
What does #include do.
#include just copies the content of the header into the source file including it.
That means, that you probably don’t want definitions in your header files, because if multiple files include your header, you violate the One-Definition-Rule, causing multiple-defintion-errors during the linking stage.
Which variables should you declare, and which should you not in a header file?
The header-file is your interface to other source-files that want to call your functions/use your classes.
So you put in declarations for things which are needed for other source files to work.
When you declare a variable in a header file, should you use extern?
The extern Keyword specifies a declaration for a variable rather than a definition.
Which means that your variable-definition is somewhere else (e.g. your source file).
If you want to use GRAVITY_FACTOR in another source file, which includes your header:
in your source: const int GRAVITY_FACTOR = -16;
in hour header: extern const int GRAVITY_FACTOR;
Remarks:
what you currently have in your header file is a class definition
public and private are accessors to your class’ members
you may rather want a namespace here or plain functions
the main function has nothing to do inside a class definition
In the header file,you can declare all class fields and functions,that you will implement in the cpp file.
You should'nt declare the variables that you will use inside your class functions(because there are like temp variables),But you can declare(and should) const varables,that you will use in your progamm.
You should'nt use extern,extern its for variables that you dont define them,and the compiler doesnt bother you about that,because when its extern,that means that the variable is defined somewhere else in your progamm.
extern is also used for functions that you want to treat your c++ code,as it were in C.
like:
extern "C" { //code. }
or extern "C" int func(int a);
In conclusion-
delcare const variables in .h file,and the classes.else - in cpp(unless its inline).
in your case:
const int GRAVITY_FACTOR = -16;
const int GROUND = 0;
const double PI = atan(1.0)*4;
are better to be in the .h file
+
you shouldnt declare it again:
double initialVelocity;
double initialAngle;
its already in .h file.
Hope it was useful..
/* This program */
using namespace std;
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
void readit();
void calcit(int, int);
void writeit(float, float, float);
int distvels[4] = {15, 25, 35, 45};
int main()
{
readit();
system("pause");
return 0;
}
void readit()
{
int targetdist, angl;
cout << "Enter the distance (meters) to the target:" << endl;
cin >> targetdist;
cout << "Enter the angle to fire the cannon:" << endl;
cin >> angl;
cout << "\n---------------\n\n";
calcit (targetdist, angl);
}
void calcit(int targetdist, int angl)
{
double distvals[4];
double tyme[4];
double maxhite[4];
for (int i=0; i<4; i++) {
distvals[i] = (2 * sin(angl) * cos(angl) * (distvels[i] * distvels[i]))/9.8;
tyme[i] = (2 * cos(angl) * distvels[i])/9.8;
maxhite[i] = ((cos(angl) * cos(angl)) * (distvels[i] * distvels[i]))/9.8;
}
writeit(distvals, tyme, maxhite);
}
void writeit(float distvals[4], float tyme[4], float maxhite[4])
{
cout << "Velocity " << "time " << "height " << "distance " <<endl;
for (int i=0; i<4; i++) {
cout << distvals[i] << " " << tyme[i] << " " << maxhite[i] << " " << endl;
}
whenever I run the program I keep getting this error code cannot convert double* to float for argument 1 to void writeit(float, float, float). I've tried everything I can think of to get rid of it with no luck. Can anyone help?
You declared the function as:
void writeit(float, float, float);
but the definition has it as:
void writeit(float distvals[4], float tyme[4], float maxhite[4])
{
// ...
}
Fix the declaration to match:
void writeit(float[4], float[4], float[4]);
It's also worth pointing out at this juncture that this doesn't do what you think it does. In fact, it's the same as this:
void writeit(float[], float[], float[]);
which is the same as this:
void writeit(float*, float*, float*);
That's because you can't pass an array by value, so it degrades into a pointer-to-the-start-of-the-array instead.
However, you can pass it by reference and keep the dimensions:
void writeit(float (&)[4], float (&)[4], float (&)[4]); // declaration
void writeit(float (&distvals)[4], float (&tyme)[4], float (&maxhite)[4]) // definition
{
// ...
}
I'd even recommend passing it as reference-to-const, as you won't be changing it:
void writeit(float (&)[4], float (&)[4], float (&)[4]);
void writeit(const float (&distvals)[4], const float (&tyme)[4], const float (&maxhite)[4])
{
// ...
}
It would also be easier if you used a std::vector<float>, but that's another discussion.
Plenty to think about there; hope it helps.
Edit Just noticed another problem, in that you're trying to pass an array of double to a function that will be expecting an array of float! Pick one and stick with it.
The error is exactly as you note -- writeit is expecting a pointer to an array of floats and you're trying to pass it an array of doubles, which are a different size. The easiest fix would be to declare the args of writeit to be arrays of doubles, so they match. Barring that, you need to copy to arrays of floats before passing (converting each element as you copy)
The function prototype is different from the function definition. So, change it to -
void writeit(double*, double*, double*);
And the function definition to -
void writeit(double distvals[], double tyme[], double maxhite[])
{
// ......
}
Notice that the array size (i.e., optional, in fact compiler won't consider it) because array decays to a pointer. It is the reason why usually array size is also sent as an argument to the functions and is a good practice.