(C++) Simple issue to do with structs and function parameters - c++

Struct Problem 1.cpp
// Struct Problem 1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "structs.h"
double calculateEarnings(Advertising aDay);
void displayEarnings(int questionInstance, Advertising aDay);
void mainQuestions();
int _tmain(int argc, _TCHAR* argv[])
{
mainQuestions();
return 0;
}
double calculateEarnings(Advertising aDay)
{
std::cout << aDay.usersClicked; //debug
return aDay.totalAdsShown * aDay.usersClicked * aDay.averagePerAd;
}
void takeInData(int questionInstance, Advertising aDay)
{
if (questionInstance == 0)
{
std::cin >> aDay.totalAdsShown;
}
else
if (questionInstance == 1)
{
std::cin >> aDay.usersClicked;
}
else
if (questionInstance == 2)
{
std::cin >> aDay.averagePerAd;
}
std::cin;
}
void mainQuestions()
{
static Advertising aToday;
aToday.totalAdsShown = 0;
aToday.usersClicked = 0.00;
aToday.averagePerAd = 00.00;
std::cout << "Welcome! Please input the advertising data for today." << "\n";
std::cout << "How many ads were shown today?" << "\n";
takeInData(0, aToday);
std::cout << "What percentage of users clicked our ads? (decimal form)" << "\n";
takeInData(1, aToday);
std::cout << "What were the average earnings per ad? (ex: 5.15)" << "\n";
takeInData(2, aToday);
structs.h
#ifndef STRUCTS_H
#define STRUCTS_H
typedef double percentage;
typedef double USD;
struct Advertising
{
int totalAdsShown;
percentage usersClicked;
USD averagePerAd;
};
#endif
Basically, the data is not saved when called by 'cin'. I added a line to print the aDay.usersClicked value and it prints to 0. I am learning c++, so the problem is very basic. I appreciate all tips!
Thank you

Change this:
void takeInData(int questionInstance, Advertising aDay)
into this:
void takeInData(int questionInstance, Advertising& aDay)
and it will work. The reason is that in your version, the paramater aDay is passed-by-value; i.e. a copy of the argument is passed to the function. So anything that takeInData() does to its version of aDay is done in the copy. After takeInData() returns, the copy (and the information therein) is lost.
In the edited version, a reference to aDay is passed to the function. Now it will reference the variable that was passed, i.e. the variable in main(). Now all things takeInData() does, are stored in the value that is actually declared in main().

Related

Undefined identifier and unresolved external errors C++ Visual Studio 2022 [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 11 months ago.
This is basically two errors in one, that seem to come from the same thing. If I define my functions in my main.cpp file, and forward declare them at the top of the file, it doesn't give me any errors and everything runs smoothly.
When trying to declutter and move things into seperate .cpp files, it starts to give me linker errors and saying things are undefined even though I am using appropriate header files. The code is shown below:
main.cpp
#include "io.h"
#include <iostream>
#include <map>
class exchangeRates;
void menu();
int main()
{
menu();
return EXIT_SUCCESS;
}
// class storing exchange rates
class exchangeRates
{
public: // Access specifier
// Data Members
std::map<std::string, double> usd = {
{"GBP", 1.2},
{"EUR", 0.7},
};
std::map<std::string, double> gbp = {
{"USD", 0.9},
{"EUR", 1.4},
};
};
// menu function
void menu()
{
// get reference currency code from user
std::string refCurrency{ obtainCodeFromUser() };
// create 'rates' instance of 'exchangeRates' class
exchangeRates rates{};
// print the exchange values for that currency
if (refCurrency == "USD")
{
printExchangeValues(rates.usd, refCurrency);
}
else if (refCurrency == "GBP")
{
printExchangeValues(rates.gbp, refCurrency);
}
else
{
std::cout << "\nInvalid currency code. Example: USD, GBP, EUR etc.\n\n";
menu();
}
}
io.h
#ifndef IO_H
#define IO_H
#include <iostream>
#include <map>
std::string obtainCodeFromUser();
double obtainAmountFromUser();
template<typename Map>
void printExchangeValues(Map& valuedCurrencies, std::string refCurrency);
#endif
io.cpp
#include "io.h"
#include <iostream>
#include <map>
// io functions for currency converter
std::string obtainCodeFromUser()
{
// obatin reference currency code from user
std::cout << "Enter currency code for reference currency (case-sensitive): ";
std::cin.clear();
std::string refCurrency{};
std::cin >> refCurrency;
std::cin.ignore(INT_MAX, '\n');
return refCurrency;
}
double obtainAmountFromUser()
{
// obtain amount of currency to be converted from user
std::cout << "Enter amount of currency to convert: ";
std::cin.clear();
double amount{};
std::cin >> amount;
std::cin.ignore(INT_MAX, '\n');
return amount;
}
template<typename Map>
void printExchangeValues(Map& valuedCurrencies, std::string refCurrency)
{
// obtain amount of currency to be converted
double amount{ obtainAmountFromUser() };
std::cout << refCurrency << " " << amount << " is worth:\n";
for (auto& item : valuedCurrencies) {
std::cout << item.first << ": " << amount * item.second << '\n';
}
}
I am still a beginner with C++ so some parts have been copied from other open-source programs, and I know there are probably plenty of places to improve my code, but I'm mainly interested in why it just won't compile. The examples I followed when learning how to use header files worked fine and I don't believe I've done anything different here.
It says the identifiers "obtainCodeFromUser" and "printExchangeValues" are undefined.
The linker error it gives is LNK2019 'unresolved external symbol ...' and it seems to be relating to the printExchangeValues function.
Any help is massively appreciated!
The issue mentioned by WhozCraig is very useful, I hope you will read it carefully. Regarding your question, after I modified some code, the program can run correctly. The error is caused by the template. Since you are a beginner and the program is not very complicated, the following code is more convenient for you to understand:
main.cpp
#include "io.h"
#include <iostream>
#include <map>
// class storing exchange rates
class exchangeRates
{
public: // Access specifier
// Data Members
std::map<std::string, double> usd = {
{"GBP", 1.2},
{"EUR", 0.7},
};
std::map<std::string, double> gbp = {
{"USD", 0.9},
{"EUR", 1.4},
};
};
template<typename Map>
void printExchangeValues(Map& valuedCurrencies, std::string refCurrency)
{
// obtain amount of currency to be converted
double amount{ obtainAmountFromUser() };
std::cout << refCurrency << " " << amount << " is worth:\n";
for (auto& item : valuedCurrencies) {
std::cout << item.first << ": " << amount * item.second << '\n';
}
}
// menu function
void menu()
{
// get reference currency code from user
std::string refCurrency{ obtainCodeFromUser() };
// create 'rates' instance of 'exchangeRates' class
exchangeRates rates{};
// print the exchange values for that currency
if (refCurrency == "USD")
{
printExchangeValues(rates.usd, refCurrency);
}
else if (refCurrency == "GBP")
{
printExchangeValues(rates.gbp, refCurrency);
}
else
{
std::cout << "\nInvalid currency code. Example: USD, GBP, EUR etc.\n\n";
menu();
}
}
int main()
{
menu();
return EXIT_SUCCESS;
}
io.h
#ifndef IO_H
#define IO_H
#include <iostream>
#include <map>
std::string obtainCodeFromUser();
double obtainAmountFromUser();
#endif
io.cpp
#include "io.h"
#include <iostream>
#include <map>
// io functions for currency converter
std::string obtainCodeFromUser()
{
// obatin reference currency code from user
std::cout << "Enter currency code for reference currency (case-sensitive): ";
std::cin.clear();
std::string refCurrency{};
std::cin >> refCurrency;
std::cin.ignore(INT_MAX, '\n');
return refCurrency;
}
double obtainAmountFromUser()
{
// obtain amount of currency to be converted from user
std::cout << "Enter amount of currency to convert: ";
std::cin.clear();
double amount{};
std::cin >> amount;
std::cin.ignore(INT_MAX, '\n');
return amount;
}

Reference to List of Objects invalid in Constructor

I am working on some code to make a wallet to hold different currencies and this is my first time programming in c++ as a c programmer. Every time I make a new currency I want to add it to the list of valid Currencies that my wallet will be able to hold. To do this I make a currency class with a list that I want to add to every time a new currency is spawned. The error I get is error: no matching function for call to ‘std::__cxx11::list<Currency>::push_back(Currency*) CurrencyList.push_back(this);"\
Currency.h looks like:
#ifndef CURRENCY_H
#define CURRENCY_H
#include <string>
#include <list>
class Currency {
public:
//Instances of class
int id;
float max;
float left_over;
std::string coinName;
//Methods
float buyFrom(float amount);
float sellBack(float amount);
//constructor
Currency();
};
extern std::list<Currency> CurrencyList; //global list
#endif
Currency.c looks like
#include "currency.h"
#include <iostream>
Currency::Currency() {
Currency::id = 0;
std::cout << "Input name :" << std::endl;
std::cin >> Currency::coinName;
std::cout << "Input max :" << std::endl;
std::cin >> Currency::max;
Currency::left_over = Currency::max - 0;
CurrencyList.push_back(this);
}
float Currency::buyFrom(float amount) {
Currency::left_over-=amount;
std::cout << "Currency just lost :" << amount << "remaining is : " << Currency::left_over << std::endl;
}
float Currency::sellBack(float amount) {
Currency::left_over -= amount;
std::cout << "Currency just gained : " << amount << " remaining is : " << Currency::left_over << std::endl;;
}
The main is quiet simple it is only meant to spawn an object to test, that looks something like this.
Main.cpp
#include <iostream>
#include "wallet.h"
#include "currency.h"
int main(){
std::cout << "Hello World" << std::endl;
Currency currencyTest;
currencyTest.buyFrom(200.3);
}
Note that this is a pointer, but your list holds actual objects, not pointers.
So just dereference the pointer and you should be fine:
CurrencyList.push_back(*this);

How do I get my constructor and functions to work so my main() is able to display both the string and int data?

I am learning about functions and classes, and wrote my own code. I used the constructor to just initialize the variables. I have a function that is supposed to get the info I initialized with the constructor and allow me to display it. However, it doesn't want to work. I am not really sure what I am doing wrong. My error code says that I have unresolved externals because of my "void" function. I thought my function was not returning anything but rather just displaying the input it got from the initialization of the constructor.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class Berries {
string Nameofberries;
int Price;
public:
Berries (string N,int B)
{
Nameofberries = N;
Price = B;
}
void GetBerryInfo(const Berries& B)
{
cout << B.Nameofberries << endl;
cout << B.Price << endl;
}
};
void GetBerryInfo (const Berries& B);
int main ()
{
Berries Berryinfo1( "Raspberries", 7);
cout << GetBerryInfo;
system("pause");
return 0;
}
There are several mistakes.
void GetBerryInfo(const Berries& B)
{
cout << B.Nameofberries << endl;
cout << B.Price << endl;
}
should be
void GetBerryInfo()
{
cout << Nameofberries << endl;
cout << Price << endl;
}
==================================================================
void GetBerryInfo (const Berries& B);
should be removed.
==================================================================
cout << GetBerryInfo;
should be
Berryinfo1.GetBerryInfo();
==================================================================
All computer langauges are fussy, you have to get the details right, as well as understand the concepts.
This will do what you wanted:
# include <iostream>
# include <iomanip>
# include <string>
using namespace std;
class Berries {
string Nameofberries;
int Price;
public:
Berries (string N,int B)
{
Nameofberries = N;
Price = B;
}
void GetBerryInfo()
{
cout << Nameofberries << endl;
cout << Price << endl;
}
};
int main ()
{
Berries Berryinfo1( "Raspberries", 7);
Berryinfo1.GetBerryInfo();
system("pause");
return 0;
}
A couple of points on your mistakes:
GetBerryInfo() was declared inside the class. You don't need to re-declare it in the global scope. That 2nd declaration should be removed.
To be invoked, functions (like GetBerryInfo) must have () at the end of them like so: GetBerryInfo().
There is no point for GetBerryInfo() to take Berries as a paremeter. It is a member function that is part of the class Berries. It has access to all data members of a Berries instance already.
You don't need to use cout here: cout << GetBerryInfo; because the function body already sends the data members to cout. This function returns void so it doesn't make sense to send this to cout anyway.

Error with uninitialized variables and returns

I'm having some problems with my program which I do not understand.
On line 72, I get the error: "error C4700: uninitialized local variable 'sumInEuros' used" however surely it is initialized as I am using it to store a calculation?
Also on line 66 I get "error C4716: 'showPriceInEuros': must return a value" - why must this return a value? the function is simply meant to output a message to the console.
I'm using VS13 and it's c++.
Any help would be very much appreciated, because I am stuck!
Thanks!
#include <iostream> //for cin >> and cout <<
#include <cassert> //for assert
#include <iomanip> //for endl
#include <Windows.h>
using namespace std;
void processAPrice();
int getPriceInPounds();
int convertPriceIntoEuros(int pounds);
int showPriceInEuros(int pounds, int euros);
int calculateSum(int euros);
void produceFinalData(int sum, int numberOfPrices);
int main()
{
char answer('Y');
int numberOfPrices(0);
while (answer = 'Y')
{
processAPrice();
numberOfPrices++;
cout << "Continue? (Y/N)";
cin >> answer;
}
if (numberOfPrices > 0)
//produceFinalData(sum, numberOfPrices);
system("PAUSE"); //hold the screen until a key is pressed
return(0);
}
void processAPrice() //
{
int pounds = getPriceInPounds();
int euros = convertPriceIntoEuros(pounds);
int sum = showPriceInEuros(pounds, euros);
calculateSum(euros);
}
int getPriceInPounds() //
{
int priceInPounds;
cout << "Enter a price (in Pounds): /234";
cin >> priceInPounds;
return priceInPounds;
}
int convertPriceIntoEuros(int priceInPounds) //
{
const int conversionRate(0.82);
return priceInPounds / conversionRate;
}
int showPriceInEuros(int pounds, int euros) //
{
SetConsoleOutputCP(1252);
cout << "The Euro value of /234" << pounds << "is: \u20AC" << euros;
}
int calculateSum(int euros) //
{
int sumInEuros;
sumInEuros = (sumInEuros + euros);
return sumInEuros;
}
void produceFinalData(int sum, int numberOfPrices) //
{
SetConsoleOutputCP(1252);
cout << "The total sum is: \u20AC" << sum;
cout << "The average is: \u20AC" << (sum/numberOfPrices);
}
Well, the showPriceInEuros function is not returning the int it promises to return in its signature. That's the error.
If the function is not supposed to return a value, you should declare its return type as void:
void showPriceInEuros(int pounds, int euros);
//^^
and then:
void showPriceInEuros(int pounds, int euros) {
SetConsoleOutputCP(1252);
cout << "The Euro value of /234" << pounds << "is: \u20AC" << euros;
}
of course.
surely it is initialized as I am using it to store a calculation?
The calculation is based on the variable's uninitialised value:
sumInEuros = (sumInEuros + euros);
^^^^^^^^^^ not initialised
Perhaps you could declare it static, so that its value is preserved between calls to the function, in order to calculate the sum of all the values you pass to the function. Usually, it would be better to use a class to manage persistent data like this, with member functions to update and access it.
why must this return a value?
Because you say it does:
int showPriceInEuros(int pounds, int euros)
^^^
If it shouldn't return a value, change the return type to void.
You do not initialize sumInEuros in this function. You store a result in it - that's true but to calculate the result you are using the uninitialized value.
int calculateSum(int euros) //
{
int sumInEuros;
sumInEuros = (sumInEuros + euros);
return sumInEuros;
}
Answering the question from below:
I would probably create a class PriceCalculator which has all the functions of your algorithm plus the internal state:
class PriceCalculator {
int m_sumInEuros;
public:
PriceCalculator()
: m_sumInEuros(0) { }
void processAPrice(int price);
int getSumInEuros() const { return m_sumInEuros; }
private:
void updateSum(int priceInEuros);
};
From your main function you should create an object of this type and give it the prices you want to sum. Do not do any console input from your class.
int main()
{
PriceCalculator calc;
char answer('Y');
int numberOfPrices(0);
while (answer = 'Y')
{
int priceInPounds;
cout << "Enter a price (in Pounds): /234";
cin >> priceInPounds;
calc.processAPrice(priceInPounds);
numberOfPrices++;
cout << "Continue? (Y/N)";
cin >> answer;
}
...
You might want to think about adding the numberOfPrices to your calculator class as well. At the end you will do all the operations in your class but the user input and console output outside your class. Your class can be tested automatically this way and is completely independent from the user interface.

multiple return statement in c++

I have tried to complete a C++ exercise where you have to complete function definitions for a 'Golf' function and devise a program based on this however, I am having a problem with one of the functions.
Part of the goal of the function, wants you to return 1 if the user has entered a name for the golf player, and return 0 if no name is entered.
I am experiencing some difficulty with this, as when I run the program, I am always getting 1 returned to the main.
Underneath I have listed what I have done so far for each file:
golf.h
#ifndef GOLF_H
#define GOLF_H
const int Len = 40;
struct golf {
char fullname[Len];
int handicap;
};
void setgolf(golf &g, const char *name, int hc);
int setgolf(golf &g);
void handicap(golf &g, int hc);
void showgolf(const golf &g);
#endif /* GOLF_H */
golf.cpp
#include "golf.h"
#include "iostream"
void setgolf(golf &g, const char *name, int hc) {
strcpy(g.fullname, name);
g.handicap = hc;
}
int setgolf(golf &g) {
std::cout << "Golfer's name:";
std::cin.getline(g.fullname, Len);
if (std::cin.get() == '\0')
return 0;
std::cout << "Golfer's handicap: ";
std::cin >> g.handicap;
return 1;
}
void handicap(golf &g, int hc) {
g.handicap = hc;
std::cout << g.fullname << "'s new handicap is:" << g.handicap;
}
void showgolf(const golf &g) {
std::cout << "Player's Name:" << g.fullname << std::endl;
std::cout << "Player's handicapped:" << g.handicap << std::endl;
}
main.cpp
#include <cstdlib>
#include <iostream>
#include "golf.h"
using namespace std;
int main(int argc, char** argv) {
int retuVal = 0;
golf ann;
setgolf(ann, "Ann Birdfree", 24);
showgolf(ann);
cout << "\n";
golf peter;
retuVal = setgolf(peter);
cout<<"return value is:"<<retuVal<<endl;
cout << "\nGolf details reset in new handicap\n";
handicap(peter, 5);
cout << "\nDetails reprinted";
showgolf(peter);
return 0;
}
Please let me know, what it is that I have done wrong, so that I can return 0 instead of returning 1 all of the time.
Thanks Jis.
In the function setgolf remove the following code:
if (std::cin.get() == '\0')
return 0;
and instead write...
if(strlen(g.fullname)==0)
return 0;
This is because when the user doesn't want to enter a name he just hits the enter key. This makes the string empty, since getline fills the character array until it is completely filled or it sees a newline character in the stream. So, if we just check its length, whether its greater than 0, then its enough. for furthur reference about getline see here
The probability of cin.get() returning '\0' is almost 0.
(If cin is connected to a terminal, it can only happen if the
user enters a control-#.) Maybe you want to return 0 if the user
enters an empty string?