How to call a class within a function definition in c++ - c++

Its my first time asking for help on programming. I have been working on a register program for my programming class for weeks which involves classes. Its rather frustrating for me. I have to use two classes: StoreItem and Register. StoreItem deals with the small list of items that the store sells. The register class deals mostly with processing the items, making a total bill and asking the user to pay with cash.
Here is the StoreItem.cpp file:
//function definition
#include <string>
#include <iostream>
#include "StoreItem.h"
#include "Register.h"
using namespace std;
StoreItem::StoreItem(string , double)
{
//sets the price of the current item
MSRP;
}
void StoreItem::SetDiscount(double)
{
// sets the discount percentage
MSRP * Discount;
}
double StoreItem::GetPrice()
{ // return the price including discounts
return Discount * MSRP;
}
double StoreItem::GetMSRP()
{
//returns the msrp
return MSRP;
}
string StoreItem::GetItemName()
{
//returns item name
return ItemName;
}
StoreItem::~StoreItem()
{
//deletes storeitem when done
}
Here is the Register.cpp:
Note that the last 5 function definitions in this one arent finished yet...
// definition of the register header
#include "Register.h"
#include "StoreItem.h"
using namespace std;
Register::Register()
{ // sets the initial cash in register to 400
CashInRegister = 400;
}
Register::Register(double)
{ //accepts initial specific amount
CashInRegister ;
}
void Register::NewTransAction()
{ //sets up the register for a new customer transaction (1 per checkout)
int NewTransactionCounter = 0;
NewTransactionCounter++;
}
void Register::ScanItem(StoreItem)
{ // adds item to current transaction
StoreItem.GetPrice();
// this probably isnt correct....
}
double Register::RegisterBalance()
{
// returns the current amount in the register
}
double Register::GetTransActionTotal()
{
// returns total of current transaction
}
double Register::AcceptCash(double)
{
// accepts case from customer for transaction. returns change
}
void Register::PrintReciept()
{
// Prints all the items in the transaction and price when finsished
}
Register::~Register()
{
// deletes register
}
My main question is where Register::ScanItem(StoreItem)... is there a way to correctly call a function from the storeItem Class into the Register scanitem function?

You have:
void Register::ScanItem(StoreItem)
{ // adds item to current transaction
StoreItem.GetPrice();
// this probably isnt correct....
}
This means that the ScanItem function takes one argument of type StoreItem. In C++ you can specify just the type and make the compiler happy. But if you intend to use the argument, you must give it a name. For example:
void Register::ScanItem(StoreItem item)
{
std::cout << item.GetItemName() << " costs " << item.GetPrice() << std::endl;
}

To be able to call a member function of the object you're passing as the parameter, you need to name the parameter, not just its type.
I suspect you want something like
void Register::ScanItem(StoreItem item)
{
total += item.GetPrice();
}

Related

Not showing output after creating nodes?

Hey ! i am trying to create a program of hospital management system using doubly linked list in c++.
in this i am using whole class for patient data.
i created a nodes for linked list .
i am using one node to represent one bed in hospital.
but after that when i am trying to print some data manually , nothing is printing in console and program is ending without showing any output
this is my code :
#define max_limit 25;// maximum 50 beds can be there in hospital
using namespace std;
class patient //creating class to store the data of patient
{
public:
int pt_id;
string pt_name; //patient name
string diagnosis; //diagnosis patient have
};
struct bed //each bed in hospital
{
class patient p;
struct bed *prev;
struct bed *next;
};
int main()
{
//creating 3 beds in starting only and giving values.
struct bed *head=(struct bed *)malloc(sizeof(patient));
struct bed *second=(struct bed *)malloc(sizeof(patient));
struct bed *tail=(struct bed *)malloc(sizeof(patient));
head->prev=NULL;
head->p.pt_id=6478;
head->p.pt_name="Jayraj";
head->p.diagnosis="Headaches";
head->next=second;
second->prev=head;
second->p.pt_id=8933;
second->p.pt_name="Mayank";
second->p.diagnosis="Highfever";
second->next=tail;
tail->prev=second;
tail->p.pt_id=1788;
tail->p.pt_name="Jay";
tail->p.diagnosis="Stomacheache";
tail->next=NULL;
cout<<"Size:"<<sizeof(patient);
return 0;
}```
You should check the errors - make sure your environment displays them. There are at least these issues:
When allocating a bed you shouldn't use sizeof(patient), but sizeof(bed).
define should not end with a semi-colon.
As a bed could be empty, you'd better define the p member as a pointer to a patient instance
You're not using C++ syntax:
Use new instead of malloc.
Define constructors and methods
Use nullptr instead of NULL
Use PascalCase for class names
Here is some code for inspiration, but you'll need to add more logic to it for your assignment (e.g. you'll have to verify the limit of beds):
#define max_limit 25 // maximum 25 beds allowed in hospital
using namespace std;
class Patient
{
public:
int pt_id;
string pt_name; //patient name
string diagnosis; //diagnosis patient have
// Constructor:
Patient(int id, string name, string diag) :
pt_id(id), pt_name(name), diagnosis(diag) {}
};
class Bed
{
public:
Patient* p = nullptr;
Bed* prev = nullptr;
Bed* next = nullptr;
// Constructors:
Bed() {};
Bed(Patient* p) : p(p) {};
// Method to ease linking beds
Bed* prepend(Bed* other) {
other->next = this;
this->prev = other;
return other;
};
};
int main()
{
// Use constructor to create patients
Patient *jaray = new Patient(6478, "Jayraj", "Headaches");
Patient *mayank = new Patient(8933, "Mayank", "Highfever");
Patient *jay = new Patient(1788, "Jay", "Stomacheache");
// Use constructor and method to create linked list
Bed *beds = (new Bed(jay))
->prepend(new Bed(mayank))
->prepend(new Bed(jaray));
// Let's output something: the beds with patient names
Bed *bed = beds;
while (bed != nullptr) {
if (bed->p == nullptr) {
cout << "bed without patient\n";
} else {
cout << "bed occupied by " << bed->p->pt_name << "\n";
}
bed = bed->next;
}
return 0;
}

Array returns bad values only first time

So I'm working with Steamworks (leaderboards) and i have some strange issue. When i fire my function to get scores, from debugging i know that it works just fine.However my array after 1st function run always returns default values.After I fire function for the second time everything works perfectly fine. I tried to track down the issue however i failed.
Here is my whole code that i am using in this case:
Struct for stats
USTRUCT(BlueprintType)
struct FScorePackage
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Leaderboard")
FString PlayerName = "working";
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Leaderboard")
int32 Rank = 0;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Leaderboard")
int32 Score = 0;
};
Function that sent request to the steam:
.h
UFUNCTION(BlueprintCallable, Category = "Steam|Leaderboard", meta = (Latent, LatentInfo = "LatentInfo", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
TArray<FScorePackage> DownloadScoresAroundUser(UObject* WorldContextObject, int AboveUser, int BelowUser, struct FLatentActionInfo LatentInfo);
.cpp
TArray<FScorePackage> USteamLeaderboard::DownloadScoresAroundUser(UObject* WorldContextObject, int AboveUser, int BelowUser, struct FLatentActionInfo LatentInfo)
{
if (!m_CurrentLeaderboard)
{
return Scores;
}
if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject))
{
FLatentActionManager& LatentActionManager = World->GetLatentActionManager();
if (LatentActionManager.FindExistingAction<SteamLeaderboardLatentClass>(LatentInfo.CallbackTarget, LatentInfo.UUID) == NULL)
{
// load the specified leaderboard data around the current user
SteamAPICall_t hSteamAPICall = SteamUserStats()->DownloadLeaderboardEntries(m_CurrentLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -AboveUser, BelowUser);
m_callResultDownloadScore.Set(hSteamAPICall, this,&USteamLeaderboard::OnDownloadScore);
LatentActionManager.AddNewAction(LatentInfo.CallbackTarget, LatentInfo.UUID, new SteamLeaderboardLatentClassScores(LatentInfo));
return Scores;
}
return Scores;
}
return Scores;
}
Now callback function from steam:
.h
void OnDownloadScore(LeaderboardScoresDownloaded_t *pResult, bool bIOFailure);
CCallResult <USteamLeaderboard, LeaderboardScoresDownloaded_t> m_callResultDownloadScore;
.cpp
void USteamLeaderboard::OnDownloadScore(LeaderboardScoresDownloaded_t *pCallback, bool bIOFailure)
{
if (!bIOFailure)
{
m_nLeaderboardEntries = __min(pCallback->m_cEntryCount, 30);
for (int index = 0; index < m_nLeaderboardEntries; index++)
{
SteamUserStats()->GetDownloadedLeaderboardEntry(pCallback->m_hSteamLeaderboardEntries, index, &m_leaderboardEntries[index], NULL, 0);
}
TranslateEntries();
scores = true;
}
}
And finally function that write scores in Array:
.h
UFUNCTION(BlueprintCosmetic, Category = "Steam|Leaderboard")
TArray<FScorePackage> TranslateEntries();
.cpp
TArray<FScorePackage> USteamLeaderboard::TranslateEntries()
{
FScorePackage ThisScore;
Scores.Init(ThisScore, 30);
for (int i = 0; i < 30; i++)
{
ThisScore.PlayerName = GetSteamName(m_leaderboardEntries[i].m_steamIDUser);
ThisScore.Rank = m_leaderboardEntries[i].m_nGlobalRank;
ThisScore.Score = m_leaderboardEntries[i].m_nScore;
Arrayas[i] = ThisScore;
}
return Scores;
}
Scores array is just static TArray Scores and scores=true is only for latent check to go on with functions after calling DownloadScoresAroundUser :)
My normal flow with this is:
1.I already have handle for leaderboard.
2.I'm calling DownloadScoresAroundUser.
3.Flow goes to latent which cannot proceed becouse of scores=false.
4.After i got callback from steam OnDownloadScore fires, giving me all needed info(checked if really and it does!).
5.Then i call TranslateEntries to get all scores with names and rank in Array.
6.Then I'm printing whole array (with break package in unreal) and get default values of my struct.
7.After i fire whole cycle again i get proper values.
If any further info is required let me know :)
This is a bit of a guess, but it appears that you have a latency issue. When you make the request to download the scores, this is a time consuming call that does not block. You set up a callback that will be called when the scores are ready, then return the existing empty Scores object.
When you make your second call, enough time has passed for the scores to have download and Scores to be populated, so it returns some scores.
Note that you have a potential race condition, where DownloadScoresAroundUser can access (return) Scores while your callback is populating that vector.
Here's one possible solution. Before the scores have completed loading, DownloadScoresAroundUser returns an empty Score (or possibly one indicating that scores are being loaded). Once the scores have been loaded and Scores populated, it will return those. Also, the callback (besides populating Scores) can in some fashion notify the caller(s) of DownloadScoresAndUser that new scores are available. They can respond to that by calling in again to get the updated scores and refresh the display.
Translateentries copy data from 0 to 30 but only "Callback->m_cEntryCount" are actually initialized. So if it < at 30, the data from "Callback->m_cEntryCount" to 30 may be wrong. Can you print out the value of this variable "in SteamLeaderboard::OnDownloadScore" ?

GNU Radio: How to define a "get_*" method inside a sink block

I'd like to code my own sink block with 1 input port and 0 output ports for GNU Radio in C++. I read and followed the steps described here:
http://gnuradio.org/redmine/projects/gnuradio/wiki/BlocksCodingGuide
http://gnuradio.org/redmine/projects/gnuradio/wiki/OutOfTreeModules
http://gnuradio.org/redmine/projects/gnuradio/wiki/OutOfTreeModulesConfig
http://gnuradio.org/redmine/projects/gnuradio/wiki/Guided_Tutorial_GNU_Radio_in_C++
I'm using
Ubuntu 14.04.3 LTS
Eclipse 4.5.1
CDT 8.8.0.201509131935
GNU Radio 3.7.8
Using gr_modtool I created the new module "jammertrap". Inside it, I created the block "bandpower". This created among others the three files
bandpower.h inside /home/sdr/gnuradio/gr-jammertrap/include/jammertrap/
bandpower_impl.h inside /home/sdr/gnuradio/gr-jammertrap/lib/
bandpower_impl.cc inside /home/sdr/gnuradio/gr-jammertrap/lib/
bandpower.h:
#ifndef INCLUDED_JAMMERTRAP_BANDPOWER_H
#define INCLUDED_JAMMERTRAP_BANDPOWER_H
#include <jammertrap/api.h>
#include <gnuradio/block.h>
namespace gr
{
namespace jammertrap
{
class JAMMERTRAP_API bandpower : virtual public gr::block
{
public:
typedef boost::shared_ptr<bandpower> sptr;
// Return a shared_ptr to a new instance of jammertrap::bandpower.
// To avoid accidental use of raw pointers, jammertrap::bandpower's constructor is in a private implementation class.
// jammertrap::bandpower::make is the public interface for creating new instances.
static sptr make();
};
} // namespace jammertrap
} // namespace gr
#endif /* INCLUDED_JAMMERTRAP_BANDPOWER_H */
bandpower_impl.h:
#ifndef INCLUDED_JAMMERTRAP_BANDPOWER_IMPL_H
#define INCLUDED_JAMMERTRAP_BANDPOWER_IMPL_H
#include <jammertrap/bandpower.h>
namespace gr
{
namespace jammertrap
{
class bandpower_impl : public bandpower
{
private:
double d_bandpower_;
public:
bandpower_impl();
~bandpower_impl();
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
// Where all the action really happens
int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items);
// Returns the calculated RMS Bandpower
double get_bandpower();
};
} // namespace jammertrap
} // namespace gr
#endif /* INCLUDED_JAMMERTRAP_BANDPOWER_IMPL_H */
bandpower_impl.cc:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "bandpower_impl.h"
namespace gr
{
namespace jammertrap
{
bandpower::sptr
bandpower::make()
{
return gnuradio::get_initial_sptr (new bandpower_impl());
}
// The private constructor
bandpower_impl::bandpower_impl() : gr::block("bandpower", gr::io_signature::make(1, 1, sizeof(gr_complex)), gr::io_signature::make(0, 0, 0))
{
d_bandpower_ = 0;
}
// Our virtual destructor
bandpower_impl::~bandpower_impl()
{}
void bandpower_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
{
// ninput_items_required[0] = noutput_items;
}
int bandpower_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items)
{
const gr_complex *in = (const gr_complex *) input_items[0];
d_bandpower_ = 0;
for(int i = 0; i < noutput_items; i++)
{
d_bandpower_ += (in[i].real() * in[i].real()) + (in[i].imag() * in[i].imag());
}
d_bandpower_ = sqrt(d_bandpower_ / noutput_items);
// Tell runtime system how many input items we consumed on each input stream.
consume_each (noutput_items);
// Tell runtime system how many output items we produced
return noutput_items;
}
double bandpower_impl::get_bandpower()
{
return d_bandpower_;
}
} /* namespace jammertrap */
} /* namespace gr */
To make and install this new block, I entered the following commands inside /home/sdr/gnuradio/gr-jammertrap/build:
cmake ../
make
make test // Result: "test_jammertrap" and "qa_bandpower" passed successful
sudo make install
This sink block "bandpower" should receive items of type gr_complex, compute the average received power and store this value inside the private member "d_bandpower_".
Additional I defined the method "get_bandpower()" to get the stored value.
Inside another program, I created a flowgraph class with the two blocks
osmosdr::source:sptr osmosdr_source_;
gr::jammertrap::bandpower::sptr bandpower_measurement_;
and instanced them with
osmosdr_source_ = osmosdr::source::make(std::string());
bandpower_measurement_ = gr::jammertrap::bandpower::make();
After starting the flowgraph, I want to read the calculated bandpower by calling get_bandpower() but Eclipse shows no method "bandpower_measurement_->get_bandpower()"
What have I forgotten to write inside bandpower.h, bandpower_impl.h or bandpower_impl.cc?
The public API of the normal OOT layout is in the bandpower.h, so you must add a
virtual double get_bandpower() = 0;
in that file.
Then, you overload/implement that, like you do, in the _impl.cc/_impl.h.
By the way, I slightly object the math behind your implementation: as noutput_items, ie. the number of input items available, changes depending on buffer fillage / runtime behaviour, your "averaging length" is not constant, which means that if your flow graph runs fast, your buffers will usually be full, and your averaging length high, whilst in a "trickle" situation, the length will be much smaller (down to noutput_items==1, in extreme cases). Hence, the variance of your power estimator will depend on computational aspects.
That's not a good thing. Better work with a constant number of items you average about. In your case, you can use set_output_multiple (because a sink is also a sync block, this also affects the input multiples) to guarantee you always get a multiple of a fixed number.
Other than that, there's already blocks that can do what you want:
Probe Avg Mag²: has a method level() which does the same as your get_bandpower (aside from the √(.) )
Complex to Mag ⟶ Decimating FIR Filter ⟶ Probe Signal: does the √(Re²+Im²), before passing it on to a filter with 123 (that was just my arbitrary fixed length) taps of 1/length, and decimating it to one value every average. Result get send to the Signal Probe, which has a signal() method, which does what your get_bandpower does. CPU load of this is relatively small -- it's really just the magnitude finding for every sample, and then 123 real multiplications + 123 real additions per 123 samples,in the filter, all SIMD increased, so basically, less than 1 FMAC per sample.
Complex to Mag ⟶ Moving Average ⟶ Probe Signal: Names say it all. Nothing magical here.

QMetaObject finding class name in list of pointers

I have a RegistrationList class that has a function which is supposed to itterate over a list of Registration pointers and then return the total fees of a specific registration type passed to the function as a QString. When I call this function from my gui implimentation class it always returns 0 even though I can see that there are registration pointers in the Registration list class. Any idea what i'm doing wrong? i'm guessing it has something to do with my use of QMetaObject but not sure. The first function below is the RegistrationList function and the second is the slot in my gui class.
my Code:
double RegistrationList::totalFees(QString t) {
double total = 0.00;
for (int i = 0; i < attendeeList.size(); ++i) {
if (attendeeList.at(i)->metaObject()->className() == t)
total += attendeeList.at(i)->calculateFee();
}
void MainWindow::totalFees_clicked() {
if (ui->rdbGuest->isChecked()) {
double total = m_rList.totalFees("GuestRegistration");
QMessageBox::information(this, "Total guest registration fees", QString("Total guest registration fees: R %1").arg(total), QMessageBox::Ok);
}
else if(ui->rdbStandard->isChecked()) {
double total = m_rList.totalFees("StandardRegistration");
QMessageBox::information(this, "Total standard registration fees", QString("Total standard registration fees: R%1").arg(total), QMessageBox::Ok);
}
else if (ui->rdbStudent->isChecked()) {
double total = m_rList.totalFees("StudentRegistration");
QMessageBox::information(this, "Total student registration fees", QString("Total student registration fees: R%1").arg(total), QMessageBox::Ok);
}
}
Add DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII to your project file, recompile your code, and fix all the bugs.
Hint: your className comparison with t doesn't do what you think it does. You're comparing pointers, where you should be comparing strings. Rewrite the test as one of the following:
QString::fromLatin1(attendeeList.at(i)->metaObject()->className()) == t, or
!strcmp(attendeeList.at(i)->metaObject()->className(), t.toLatin1()).
This operation should really be a member of the Registration class (if attendeeList contains values of type Registration*):
class Registration : public QObject {
...
public:
bool is(const QString & className) const {
return QString::fromLatin1(metaObject()->className()) == t;
}
...
};
Your totalFees should be a const method, and then you don't need all the at() verbosity: the operator[] will do what you wish, then. You should also pass strings you don't need copies of by reference, not value. The use of iterators lets you get rid of the explicit indexing altogether:
double RegistrationList::totalFees(const QString & t) const {
double total = 0.0;
for (auto it = attendeeList.begin(); it != attendeeList.end(); ++it)
if ((*it)->is(t)) total += (*it)->calculateFee();
return total;
}
If your compiler supports range-for, you should use that instead. It's not the '00s anymore.
double RegistrationList::totalFees(const QString & t) const {
double total = 0.00;
for (auto attendee : attendeeList)
if (attendee->is(t)) total += attendee->calculateFee();
return total;
}
If you wish, you could also use std::accumulate (see this answer):
double RegistrationList::totalFees(const QString & t) const {
return std::accumulate(attendeeList.begin(), attendeeList.end(), 0.0,
[t](Registration* attendee) -> double {
return attendee->is(t) ? attendee->calculateFee() : 0.0;
});
}
Finally, you should never use floating point types to deal with money. Use a proper class to wrap an integer type to represent the lowest monetary unit you wish to deal with.

Coding State Machine in C++

I'm attempting to code a state machine based on a gumball machine. I have a interface class of a basic state, while I have specific states that use this interface. I have four states, no_quarter, has_quarter, sold, and sold_out states. I also have a gumball machine class that handles these states and depending on which state my machine is in, it will go that class and do the needed action. Here is my code that is having the problem, I'll post my functions also.
Gumball_Machine.h
class Gumball_Machine
{
private:
int gumball_count;
State *current_state;
No_Quarter_State *nqs;
Has_Quarter_State *hqs;
Sold_State *ss;
Sold_Out_State *sos;
public:
Gumball_Machine(int inventory)
{
gumball_count = inventory;
nqs = new No_Quarter_State(this);
hqs = new Has_Quarter_State(this);
ss = new Sold_State(this);
sos = new Sold_Out_State(this);
if (gumball_count == 0)
set_state(sos);
else
set_state(nqs);
}
void insert_quarter()
{
current_state->insert_quarter();
}
void eject_quarter()
{
current_state->eject_quarter();
}
void turn_crank()
{
current_state->turn_crank();
}
void dispense()
{
current_state->dispense();
}
void set_state(State *new_state)
{
current_state = new_state;
}
State *get_no_quarter_state()
{
return nqs;
}
State *get_has_quarter_state()
{
return hqs;
}
State *get_sold_state()
{
return ss;
}
State *get_sold_out_state()
{
return sos;
}
No_Quarter_State.h
#ifndef NO_QUARTER_STATE_H_INCLUDED
#define NO_QUARTER_STATE_H_INCLUDED
#include "State.h"
class No_Quarter_State: public State
{
public:
No_Quarter_State(Gumball_Machine *gbm);
void insert_quarter();
void eject_quarter();
void turn_crank();
void dispense();
};
#endif // NO_QUARTER_STATE_H_INCLUDED
No_Quarter_State.cpp
#include "No_Quarter_State.h"
#include "Gumball_Machine.h"
No_Quarter_State::No_Quarter_State(Gumball_Machine *machine)
{
machine = machine;
}
void No_Quarter_State::insert_quarter()
{
cout << "You inserted a quarter.\n";
machine->set_state(machine->get_has_quarter_state());
}
void No_Quarter_State::eject_quarter()
{
cout << "You must insert a quarter before you can eject one.\n";
}
void No_Quarter_State::turn_crank()
{
cout << "You must insert a quarter before you can crank the handle.\n";
}
void No_Quarter_State::dispense()
{
cout << "You need to pay first before you can get a gumball.\n";
}
The line I'm having an issue is in the No_Quarter_State.cpp
machine->set_state(machine->get_has_quarter_state());
This is giving me a run-time error. I've seen examples like this but I'm not completely sure if this is legal in C++. I'm attempting to switch the state of my gumball machine object.
The error I get is a generic not responding error: "test.ext has stopped working". I'm using CodeBlocks to code this.
In the constructor, the presumed member variable machine is hidden by the parameter.
No_Quarter_State::No_Quarter_State(Gumball_Machine *machine)
{
machine = machine;
}
You can fix this by using initializer list syntax instead:Thanks Sneftel and NathanOliver
No_Quarter_State::No_Quarter_State(Gumball_Machine *machine)
: machine(machine)
{
}
However, in regular method functions, you would have to use this-> if you named the method parameter the same as the member variable. A typical style used to avoid that issue is to prepend m_ or append _ to member names.