in the following code I have a for loop in my main function. Since a function can't return 2 values, what are some ways I could create a function, or functions, to remove it from my main function. Thanks!
#include <iostream>
#include <cmath>
using namespace std;
int getNumberExercises();
int getScores(int numberOfExercises);
int getPoints(int numberOfExercises);
double roundToTenth(double number);
double calcPercentage(int totalScore, int totalPoints);
void getTotal(int totalScore, int totalPoints, double scorePercentage);
int main() {
int numberOfExercises = 0;
int totalScore = 0;
int totalPoints = 0;
double scorePercentage = 0.0;
numberOfExercises = getNumberExercises();
for (int i = 1; i <= numberOfExercises; i++) {
totalScore += getScores(i);
totalPoints += getPoints(i);
}
scorePercentage = calcPercentage(totalScore, totalPoints);
getTotal(totalScore, totalPoints, scorePercentage);
return 0;
}
int getNumberExercises() {
int numberOfExercises;
cout << "How many exercises to input? ";
cin >> numberOfExercises;
cout << endl;
return numberOfExercises;
}
int getScores(int i) {
int score = 0;
cout << "Score received for exercise " << i << ": ";
cin >> score;
return score;
}
int getPoints(int i) {
int points = 0;
cout << "Total points possible for exercise " << i << ": ";
cin >> points;
cout << endl;
return points;
}
double roundToTenth(double number) {
return floor(number * 100 + 0.5) / 100;
}
double calcPercentage(int totalScore, int totalPoints) {
double scorePercentage = (double) totalScore / totalPoints * 100;
return scorePercentage;
}
void getTotal(int totalScore, int totalPoints, double scorePercentage) {
cout << "Your total is " << totalScore << " out of " << totalPoints << ", or " << roundToTenth(scorePercentage) << "%";
}
Either typedef a std::pair to a descriptive name, or create your own type to hold the things you want to return:
using ScorePointPair = std::pair<int, int>; // C++11
typedef std::pair<int, int> ScorePointPair; // pre C++11
Or
struct ScorePointPair
{
int score;
int points;
};
Then simply return this from your function (by value):
ScorePointPair fun()
{
// Loop etc...
return {score, points};
};
I would recommend the custom type (struct/class) approach, as this tends to be more maintainable.
To return multiple values use pass by pointer:
void modify(int *val1, int *val2)
{
*val1 = 46;
*val2 = 100;
}
In caller:
int a, b;
modify(&a, &b);
Now a will be 46, and b will be 100. This is because the address is copied, rather than the actual variable, which is what happens in pass by value.
So if you want to find the number of occurences of tabs and commas in a file:
void findtabcomma(const char *fn, int *ncomma, int *ntab)
{
FILE *fp;
int c;
if (fp = fopen(fn, "r")) {
while ((c = getc(fp)) != EOF) {
if (c == '\t')
++(*ntab);
if (c == ',')
++(*ncomma);
}
fclose(fp);
}
}
You can use the function like this:
int c, t;
findtabcomma(filenam, &c, &t);
printf("Commas: %d\nTabs: %d", c, t);
And in C++, you can use reference variables. So the findtabcomma function could be rewritten as:
void findtabcomma(const char *fn, int &ncomma, int &ntab)
{
FILE *fp;
int c;
if (fp = fopen(fn, "r")) {
while ((c = getc(fp)) != EOF) {
if (c == '\t')
++ntab;
if (c == ',')
++ncomma;
}
fclose(fp);
}
}
And used like this:
int c, t;
findtabcomma(filenam, c, t);
printf("Commas: %d\nTabs: %d", c, t);
Notice how there are no more *s and &s with C++ references.
You can create a function that either returns an array of type int of size 2 such as
int* functionName(arg1, arg2)
array[0] = totalScore;
array[1] = totalPoints;
return array;
or you could pass in the values by reference by doing something like
void functionName(&arg1, &arg2)
What passing by reference does is it passes the ADDRESS of the variable and then modifies the variable directly instead of creating a copy and passing it into the function.
You can use reference in the argument list to return data
int fun(); can be coded as void fun(int& )
Related
I got a task in which I receive babies' firstname and weight in kilogram in a character array (for example: Johnny, 2 kg). I must store them in an array that can hold maximum 1000 elements and must be a struct type, storing the baby's firstname and weight.
Every actions must be done in functions - however, when I tried to get the name until the comma, str.copy() didn't work for me. Its specific problem was something with the last parameter, the position. Could someone help me out with that? Also, I'm kinda new to C++ and imagining how to separately, in two functions ask in the char arrays until empty line and do the copying in the other... if someone could help me out, I'd be grateful for that ^^'
Thanks for the help in advance!
#include<iostream>
#include<string>
#define M 1000
struct baby{
std::string baby_name;
float weight;
};
int readIn(baby* baby_datapair, int max);
// int maxWeight(baby* baby_datapair);
// int minWeight(baby* baby_datapair);
// void descendingOrder(baby* baby_datapair, int num);
int main(){
baby baby_array[M];
int n = readIn(baby_array, M);
return 0;
}
int readIn(baby* baby_datapair, int max){
int n = 0;
char name[12];
while (n < max){
std::cout << "Baby" << n+1 << "'s datas (Nickname, weight in kg): ";
std::getline(std::cin, name);
//~ std::cin.ignore(1);
if (neve == ""){
std::cout << "Wrong input!\n";
break;
}else{
std::size_t pos = name.find(',');
std::size_t until = name.copy(baby_datapair[n].baby_name, 0, pos);
}
n++;
}
return n;
}
// int maxWeight(baby* baby_datapair){
// }
// int minWeight(baby* baby_datapair){
// }
// void descendingOrder(baby* baby_datapair, int num){
// }
You must use std::string name; instead of char name[12]; as std::getline 's parameter. BTW, It make better for memory management. After input data, check pos value for valid value.
#include<iostream>
#include<string>
#define M 1000
struct baby {
std::string baby_name;
float weight;
};
int readIn(baby* baby_datapair, int max);
// int maxWeight(baby* baby_datapair);
// int minWeight(baby* baby_datapair);
// void descendingOrder(baby* baby_datapair, int num);
int main() {
baby baby_array[M];
int n = readIn(baby_array, M);
return 0;
}
int readIn(baby* baby_datapair, int max) {
int n = 0;
//char name[12];
std::string name;
while (n < max) {
std::cout << "Baby" << n + 1 << "'s datas (Nickname, weight in kg): ";
std::getline(std::cin, name);
//~ std::cin.ignore(1);
if (name == "") {
std::cout << "Wrong input!\n";
break;
}
else {
std::size_t pos = name.find(',');
if (pos <= 0) {
std::cout << "Invalid input structure!\n";
continue;
}
//std::size_t until = name.copy(baby_datapair[n].baby_name, 0, pos);
baby_datapair[n].baby_name = name.substr(0, pos);
baby_datapair[n].weight =(float)atof(name.substr(pos+1).c_str());
//std::cout << std::endl;
//std::cout << baby_datapair[n].baby_name;
//std::cout << ", " << baby_datapair[n].weight;
}
n++;
}
return n;
}
// int maxWeight(baby* baby_datapair){
// }
// int minWeight(baby* baby_datapair){
// }
// void descendingOrder(baby* baby_datapair, int num){
// }
You are taking it the wrong size. You should not try to copy to, but just copy from. BTW, name must be a std::string for you program to compile, and you should check for possible end of file. So a minally fixed version could be:
std::string name;
while (n < max) {
std::cout << "Baby" << n + 1 << "'s datas (Nickname, weight in kg): ";
std::getline(std::cin, name);
//~ std::cin.ignore(1);
if ((! std::cin) || name == "") {
std::cout << "Wrong input!\n";
break;
}
else {
std::size_t pos = name.find(',');
baby_datapair[n].baby_name = std::string(name.c_str(), pos);
baby_datapair[n].weight = strtof(name.c_str() + pos + 1, nullptr);
}
But using a std::stringstream would be more idiomatic in C++. Above code is rather C-ish...
I am writing a very simple game simulator (does not use classes). From the main() function, I successfully access one of my functions, but another function call throws the error: 'No matching function for call to simGame'.
Any ideas why this is happening?
Code:
...
float rollDice() {
default_random_engine randomGenerator(time(NULL));
uniform_real_distribution<float> rollDice(0.0f, 1.0f);
float roll = rollDice(randomGenerator);
return roll;
}
string simGame(string p1, string p2, int p1Health, int p2Health, int p1Attack, int p2Attack) {
// Game State
bool gameOver = false;
float attack = rollDice();
int pl1 = 0;
int pl2 = 1;
int turn = pl1;
int defenderHealth = p2Health;
int attackerAttack = p1Attack;
while ((p1Health > 0) && (p2Health > 0)) {
if (attack > 0.3) {
defenderHealth -= attackerAttack;
}
turn = -turn + 1;
if (turn == 0) {
defenderHealth = p2Health;
attackerAttack = p1Attack;
} else {
defenderHealth = p1Health;
attackerAttack = p2Attack;
}
}
turn = -turn + 1;
if (turn == 0) {
return p1;
} else {
return p2;
}
return 0;
}
int setHealth(int botNum, int botHealth) {
int totalHealth = botNum * botHealth;
return totalHealth;
}
int main() {
// bot types
int drWhosAndCompanions;
int ricksAndMortys;
// Attributes
int rmHealth = 10;
int dcHealth = 15;
int rmAttack = 15;
int dcAttack = 10;
int totalRMHealth;
int totalDocHealth;
cout << "How many Ricks and Mortys?" << endl;
cin >> ricksAndMortys;
cout << "How many Dr Whos and Companions?" << endl;
cin >> drWhosAndCompanions;
// Starting Vals
totalRMHealth = setHealth(ricksAndMortys, rmHealth);
totalDocHealth = setHealth(drWhosAndCompanions, dcHealth);
cout << "You have chosen " << ricksAndMortys << " Ricks and Mortys and " << drWhosAndCompanions << " Dr. Whos and Companions.\n";
string res;
res = simGame(ricksAndMortys, drWhosAndCompanions, rmHealth, dcHealth, rmAttack, dcAttack);
return 0;
}
Its simple
Your function definition has this prototype
simGame(string, string, int, int, int, int);
But you are passing
simGame(ricksAndMortys, drWhosAndCompanions, rmHealth, dcHealth, rmAttack, dcAttack);
In which ricksAndMortys and deWhosAndCompanions are int type
So change their data type to string
In main function
// bot types
int drWhosAndCompanions;
int ricksAndMortys;
Should be
// bot types
string drWhosAndCompanions;
string ricksAndMortys;
I have included both my definition of the Question class and its implementation, the first is a header file and the second a cpp file.
I put comments in to show where the problem is. For some reason under the constructor I can cout the questionText just fine but when I try to do this under the getQuestionText function it just outputs an empty string? Any help would be most appreciated!! Thanks!
#include <string>
#include <vector>
#include <iostream>
using namespace std;
#ifndef QUESTION_H
#define QUESTION_H
class Question{
public:
Question(int thePointValue, int theChapterNumber, \
string theQuestionText);
int getPointValue() const;
int getChapterNumber() const;
string getQuestionText() const;
virtual void writeQuestion(ostream& outfile) const;
virtual void writeKey(ostream& outfile) const;
private:
int pointValue;
int chapterNumber;
string questionText;
void writePointValue(ostream& outfile) const;
};
#endif
#include "Question.h"
Question::Question(int thePointValue, int theChapterNumber, \
string theQuestionText)
{
pointValue = thePointValue;
chapterNumber = theChapterNumber;
questionText = theQuestionText;
//HERE THIS WORKS PERFECTLY
cout << questionText << endl;
}
int Question::getPointValue() const
{
return pointValue;
}
int Question::getChapterNumber() const
{
return chapterNumber;
}
string Question::getQuestionText() const
{
//THIS IS THE PROBLEM. HERE IT OUPUTS AN EMPTY STRING NO MATTER WHAT!
cout << questionText << endl;
return questionText;
}
void Question::writeQuestion(ostream& outfile) const
{
writePointValue(outfile);
outfile << questionText << endl;
}
void Question::writeKey(ostream& outfile) const
{
writePointValue(outfile);
outfile << endl;
}
void Question::writePointValue(ostream& outfile) const
{
string pt_noun;
if (pointValue == 1)
pt_noun = "point";
else
pt_noun = "points";
outfile << "(" << pointValue << " " << pt_noun << ") ";
}
vector<Question *> QuestionsList(string filename, int min, int max)
{
vector<Question *> QuestionList;
string line;
vector<string> text;
ifstream in_file;
in_file.open(filename.c_str());
while (getline(in_file, line))
{
text.push_back(line);
}
string type;
for(int i = 0; i < text.size(); i ++)
{
int num = text[i].find('#');
type = text[i].substr(0, num);
if (type == "multiple")
{
MultipleChoiceQuestion myq = matchup(text[i]);
MultipleChoiceQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
if (type == "short")
{
ShortAnswerQuestion myq = SAmatchup(text[i]);
ShortAnswerQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
if (type == "long")
{
LongAnswerQuestion myq = LAmatchup(text[i]);
LongAnswerQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
if (type == "code")
{
CodeQuestion myq = CODEmatchup(text[i]);
CodeQuestion* myptr = &myq;
if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
{
QuestionList.push_back(myptr);
}
}
cout << QuestionList[QuestionList.size()-1]->getQuestionText() << endl;
}
for (int i = 0; i < QuestionList.size(); i ++)
{
int numm = QuestionList.size();
cout << QuestionList[numm-1]->getQuestionText() << endl;
}
return QuestionList;
}
then when i call this in main the code breaks
vector<Question *> list = QuestionsList(pool_filename, min_chapter, max_chapter);
cout << list[0]->getQuestionText() << endl;
You are declaring, multiple times in your code, local objects and storing their pointer into the QuestionList vector (returned by the function) which, at the end of the function block, will contains dangling pointers.
MultipleChoiceQuestion myq = matchup(text[i]); // < local object
MultipleChoiceQuestion* myptr = &myq; // < pointer to local object
QuestionList.push_back(myptr); // < push back into vector
At this point you can either use dynamic memory allocation (I suggest you not to do that unless you are absolutely forced, and even in that case use one of the smart pointers provided by the standard library) or store the objects directly inside the vector.
This question already has answers here:
Calling a function in main
(4 answers)
Closed 4 years ago.
Okay, I think I fixed most of this, but it doesn't like me passing the constants I think. Any help would be greatly appreciated, thank you.
also, with the !inputFile part, I'm not sure how to pull off a return (EXIT_FAILURE) like my teacher suggested..
Also, as to your suggestion with only using one part of the array, would that still allow me to use the whole thing in the function?
The program is supposed to take a file like this:
ex:
NOT 11010001
and it's supposed to read the command as a string, read the binary in as an array, then perform the command on the binary.
The code here is only main function, just don't want to send a wall of it all at once, if this looks okay, then I will happily add the rest. Also, the void Operate () function pretty much calls all of the other functions in one way or another... I'm not sure if that's what's causing it or what. The print table only cout's a table to put all of the info on.
and they headers are wonky for me on here, so just assume those are right.
/* ========================================================================== */
/* Prototypes */
int Power (int, int);
int ReadFile (ifstream inputFile);
void Operate (const int, ifstream&, string, int, int, int);
void CommandNot (const int, int, int);
void CommandAnd (const int, int, int, int);
void CommandOr (const int, int, int, int);
int CommandConvert (const int, int, int);
void CommandLshift (const int, int, int, int);
void PrintTable ();
void PrintOperand (const int &, int);
int main ()
{
//Constants
const int BIT_SIZE = 8;
//Variables
string fileName = "binaryData.txt";
int operandOne [BIT_SIZE];
int operandTwo [BIT_SIZE];
int operandResult [BIT_SIZE];
ifstream inputFile;
PrintTable ();
Operate (BIT_SIZE, inputFile, fileName, operandOne[BIT_SIZE], operandTwo[BIT_SIZE], operandResult[BIT_SIZE]);
return 0;
}
void PrintTable ()
{
cout << "=================================================" << endl;
cout << "= Eight Bit Binary Number Manipulator =" << endl;
cout << "=================================================" << endl << endl;
cout << setw(14) << "COMMAND" << "Operand #1" << "Operand #2" << "Shift" << "Result" << endl;
cout << "----------------------------------------------------------------------" << endl;
}
void Operate (const int BIT_SIZE, ifstream& inputFile, string fileName, int operandOne[], int operandTwo[], int operandResult[])
{
//Variables
int count, shift;
char myChar;
string command;
const int SIZE = BIT_SIZE; //rename constant
inputFile.open (fileName);
if ( !inputFile ) //Check if file opened sucessfully
{
cout << "Error: Data file could not be opened" << endl;
}
while (inputFile) //Read file, and apply commands
{
inputFile >> command;
cout << command << endl;
for ( count = 0; count < SIZE; count++ )
{
inputFile >> myChar;
operandOne[count] = myChar - '0';
}
if (command == "NOT")
{
CommandNot (BIT_SIZE, operandOne[BIT_SIZE], operandResult[BIT_SIZE]);
PrintOperand (BIT_SIZE, operandResult[BIT_SIZE]);
}
else if (command == "AND")
{
count = 0;
for ( count = 0; count < SIZE; count++ )
{
inputFile >> myChar;
operandTwo[count] = myChar - '0';
}
CommandAnd (BIT_SIZE, operandOne[BIT_SIZE], operandTwo[BIT_SIZE], operandResult[BIT_SIZE]);
PrintOperand (BIT_SIZE, operandResult[BIT_SIZE]);
}
else if (command == "OR")
{
count = 0;
for ( count = 0; count < SIZE; count++ )
{
inputFile >> myChar;
operandTwo[count] = myChar - '0';
}
CommandOr (BIT_SIZE, operandOne[BIT_SIZE], operandTwo[BIT_SIZE], operandResult[BIT_SIZE]);
PrintOperand (BIT_SIZE, operandResult[BIT_SIZE]);
}
else if (command == "CONVERT")
{
CommandConvert (BIT_SIZE, operandOne[BIT_SIZE], operandResult[BIT_SIZE]);
PrintOperand (BIT_SIZE, operandResult[BIT_SIZE]);
}
else if (command == "LSHIFT")
{
inputFile >> shift;
CommandLshift (BIT_SIZE, operandOne[BIT_SIZE], operandResult[BIT_SIZE], shift);
PrintOperand (BIT_SIZE, operandResult[BIT_SIZE]);
}
else
{
command = "INVALID";
PrintOperand (BIT_SIZE, operandOne[BIT_SIZE]);
cout << "--- ERROR! Invalid Command ---";
}
}
inputFile.clear();
inputFile.close();
return ;
}
void CommandNot (const int BIT_SIZE, int operandOne[], int operandResult[])
{
int count;
const int SIZE = BIT_SIZE;
for ( count = 0; count < SIZE; count++ )
{
if (operandOne[count] == 0)
{
operandResult[count] = 1;
}
else
{
operandResult[count] = 0;
}
}
}
void CommandAnd (const int BIT_SIZE, int operandOne[], int operandTwo[], int operandResult[])
{
int count;
const int SIZE = BIT_SIZE;
for ( count = 0; count < SIZE; count++ )
{
if ((operandOne[count] == 1) && (operandTwo[count] == 1))
{
operandResult[count] = 1;
}
else
{
operandResult[count] = 0;
}
}
}
void CommandOr (const int BIT_SIZE, int operandOne[], int operandTwo[], int operandResult[])
{
int count;
const int SIZE = BIT_SIZE;
for ( count = 0; count < SIZE; count++ )
{
if ((operandOne[count] == 0) && (operandTwo[count] == 0))
{
operandResult[count] = 0;
}
else
{
operandResult[count] = 1;
}
}
}
int CommandConvert (const int BIT_SIZE, int operandOne[])
{
int count;
const int SIZE = BIT_SIZE;
int baseTenResult = 0;
int place;
for ( count = 0; count < SIZE; count++ )
{
place = SIZE - (count + 1);
if (operandOne[count] == 1)
{
baseTenResult = baseTenResult + Power (2, place);
}
else
{
continue;
}
}
return baseTenResult;
}
void CommandLshift (const int BIT_SIZE, int operandOne[], int operandResult[], int shift)
{
int count;
const int SIZE = BIT_SIZE;
int shiftStart = SIZE - shift;
for ( count = 0; count < SIZE-shift; count++ )
{
operandResult[count] = operandOne[count + shift];
}
for ( count = SIZE - shift; count < SIZE; count++ )
{
operandResult[count] = 0;
}
}
int Power (int base, int power)
{
int count;
int result = 1;
for ( count = 0; count < power; count++ )
{
result = result * base;
}
return result;
}
void PrintOperand (const int BIT_SIZE, int operandResult[])
{
int count;
const int SIZE = BIT_SIZE;
for ( count = 0; count < SIZE; count++ )
{
cout << operandResult[count];
}
}
You need to call the functions from main. You can't do this by sort-of redeclaring them:
void PrintTable();
void Operate (const int BIT_SIZE, ifstream& inputFile, string fileName, int operandOne[], int operandTwo[], int operandResult[]);
Instead, you need to call them:
PrintTable();
Operate(BITSIZE,inputFile,fileName,operandOne,operandTwo,operandResult);
Note, however that there is another problem: Operate requires three integer arguments at the end, but you seem to try to use integer arrays as arguments. You'll need to select one element of each array and submit only that as argument.
(EDIT) A few things have changed in your question, and I don't understand enough to tell what the best overall structure for your data and functions should be, but if you are dealing with integer arrays and you'd like to pass an entire array to a function, you can do it in this way (I've simplified it to a function that takes only one array of integers. Of course you can have more than one function argument):
#include <iostream>
const int SIZE = 3;
/* This is a simpified version of 'operate'. It
takes one argument, which is an array of integers. */
void operate(int a[])
{
/* The only thing I do is to iterate through
all elements of the array and print them. */
int i = 0;
while (i < SIZE) {
std::cout << a[i] << std::endl;
++i;
}
/* IMPORTANT: The length of the array is defined by a
global constant SIZE. Alternatively, you can pass
along the size of the array as a separate argument
to the function. */
}
int main()
{
/* Main program. Here is our array: */
int my_array[SIZE] = { 1,2,3 };
/* And here we call our function: */
operate(my_array);
return 0;
}
However, all of this is a bit complicated and not really as conventient as you could have it in C++ (as opposed to C). In all likelihood, you'll be much better of not using arrays at all, and replacing them with std::vector. Best check on cppreference for examples of how to use it (also click on some of the member functions, such as the constructor and push_back to get specific code examples.)
So its a Friday, Ive been working this app and my head is about to explode. I can't find the problem anywhere!!! I am a beginner coder so I am hoping the gods of stackoverflow can guide me in the right direction or provide some feedback!! :]
This console app is just a simple parking time ticket. The code complies fine with no errors. But my math is all messed up!
Here is a sample result: With time entered as 3:50 and exit 5:29 with vehicle as T.
TIME-IN -858993460:858993460
TIME-OUT -858933460:-858993460
PARKING TIME 0:-858993460
TOTAL CHARGE -214748352.00
And here is my code
#include <iostream> //used for cout/cin
#include <iomanip> //used to manipulate data
void getData(int* ehour, int* emin, int* exhour, int* exmin);
void rate(int exhour, int exmin, int ehour, int emin, int* thour, int* tmin, int* round);
void charge(char* vehic, float* rate1, float* rate2, int ehour);
void result(int exhour, int exmin, int ehour, int emin, int thour, float rate1, float rate2, int round, float total);
int main(void)
{
char vehic;
int ehour;
int emin;
int exhour;
int exmin;
int thour;
int tmin;
int round;
float rate1;
float rate2;
float total;
getData(&ehour, &emin, &exhour, &exmin);
rate(exhour, exmin, ehour, emin, &thour, &tmin, &round);
charge(&vehic, &rate1, &rate2, ehour);
total= rate1 + rate2;
result( exhour, exmin, ehour, emin, thour, rate1, rate2, round, total);
return 0;
}
void getData(int* ehour, int* emin, int* exhour, int* exmin)
{
char v;
printf("Enter C for car, B for bus, T for truck: ");
scanf("%c", &v);
printf("\nHour vehicle entered 0-24: ");
scanf("%d", &ehour);
printf("\nMinute vehicle entered 0-60: ");
scanf("%d", &emin);
printf("\nHour vehicle exited 0-24: ");
scanf("%d", &exhour);
printf("\nMinute vehicle exited 0-60: ");
scanf("%d", &exmin);
return;
}
void rate(int exhour, int exmin, int ehour, int emin, int* thour, int* tmin, int* round)
{
if(emin < exmin)
{
emin= emin + 60;
exhour= exhour - 1;
}
*thour = ehour - exhour;
*tmin = emin - exmin;
if ((*tmin > 0 && *tmin <= 60))
{
*thour = *thour + 1;
*round = *tmin * 0;
}
return;
}
void charge(char* vehic, float* rate1, float* rate2, int ehour)
{
switch (*vehic)
{
case 'c': if (ehour <= 3)
{
*rate1 = 0.00;
if (ehour > 3)
*rate2 = 1.25 * (ehour - 3);
}
break;
case 'b': if (ehour <= 2)
{
*rate1 = 2.00 * ehour;
if (ehour > 2)
*rate2 = 2.50 * (ehour - 2);
}
break;
case 't': if (ehour <= 1)
{
*rate1 = 3.75 * ehour;
if (ehour > 1)
*rate2 = 4.50 * (ehour - 1);
}
break;
}
return;
}
void result(int exhour, int exmin, int ehour, int emin, int thour, float rate1, float rate2, int round, float total)
{
printf("\n\t\t PARKING LOT CHARGE \t\t\n");
printf("\nType of vehicle: Car or Bus or Truck");
printf("\nTIME-IN\t\t %d:%d", ehour, emin);
printf("\nTIME-OUT\t\t %d:%d", exhour, exmin);
printf("\n\t\t\t --------");
printf("\nPARKING TIME\t\t %d:%d", thour, round);
printf("\n\t\t\t --------");
total= rate1 + rate2;
printf("\nTOTAL CHARGE\t\t %4.2f\n\n", total);
return;
}
I am sorry this is alot of code! I am just so puzzled!!! Are my ints not formatted correctly? Is the math wrong?
char v;
printf("Enter C for car, B for bus, T for truck: ");
scanf("%c", &v);
printf("\nHour vehicle entered 0-24: ");
scanf("%d", ehour);
printf("\nMinute vehicle entered 0-60: ");
scanf("%d", emin);
printf("\nHour vehicle exited 0-24: ");
scanf("%d", exhour);
printf("\nMinute vehicle exited 0-60: ");
scanf("%d", exmin);
You took the address of the parameters, which were already pointers.
As a general finger exercise, here's what you could do in more typical C++ style:
/////////////////////////////////////
// timepoint classes (booking.hpp)
struct timepoint
{
int hour, minute;
timepoint normalized() const;
int totalMinutes () const;
int roundedHours () const;
timepoint operator- (timepoint const& rhs) const;
};
struct booking_t
{
char vehicle;
timepoint enter, exit;
timepoint parked() const { return exit - enter; }
};
/////////////////////////////////////
// main program (main.cpp)
booking_t inputData();
void displayBill(booking_t const& booking);
int main(void)
{
auto booking = inputData();
displayBill(booking);
}
/////////////////////////////////////
// timepoint methods (booking.cpp)
timepoint timepoint::normalized() const
{
timepoint tmp { (hour + minute/60) % 24, minute % 60 };
while (tmp.minute < 0) tmp.hour--, tmp.minute+=60;
while (tmp.hour < 0) tmp.hour+=24;
return tmp;
}
int timepoint::roundedHours() const
{
return (totalMinutes()-1) / 60 + 1; // TODO check rounding logic
}
int timepoint::totalMinutes() const
{
return hour*60 + minute;
}
timepoint timepoint::operator-(timepoint const& rhs) const
{
return timepoint { 0, totalMinutes() - rhs.totalMinutes() } .normalized();
}
#include <iostream> //used for cout/cin
timepoint getTime(std::string label)
{
int hour, minute;
std::cout << "\nHour " << label << " 0-24: ";
std::cin >> hour;
std::cout << "\nMinute " << label << " 0-60: ";
std::cin >> minute;
return { hour, minute };
}
/////////////////////////////////////
// global functions - input
booking_t inputData()
{
std::cout << "Enter C for car, B for bus, T for truck: ";
char v;
std::cin >> v;
auto entered = getTime("vehicle entered");
auto exited = getTime("vehicle exited");
return { v, entered.normalized(), exited.normalized() };
}
/////////////////////////////////////
// calculation + billing
#include <sstream>
#include <iomanip> //used to manipulate data
#include <map>
static std::ostream& operator <<(std::ostream& os, timepoint const& tp)
{
std::ostringstream oss;
oss << std::setw(2) << std::setfill('0') << tp.hour << ':'
<< std::setw(2) << std::setfill('0') << tp.minute;
return os << oss.str();
}
std::pair<float,float> charge(booking_t const& booking)
{
struct tariff_t { int threshold; float rate1, rate2; };
const static auto tariffs = std::map<char, tariff_t> {
{ 'c', { 3, 0 , 1.25 } },
{ 'b', { 2, 2. , 2.5 } },
{ 't', { 1, 3.75, 4.5 } } ,
};
auto& tariff = tariffs.at(std::tolower(booking.vehicle));
auto parked = booking.parked().roundedHours();
return std::make_pair(
tariff.rate1 * std::min(tariff.threshold, parked) ,
tariff.rate2 * std::max(0, parked - tariff.threshold));
}
void displayBill(booking_t const& booking)
{
std::cout << "\n\n PARKING LOT CHARGE\n";
std::cout << "Type of vehicle: Car or Bus or Truck\n";
std::cout << "TIME-IN " << booking.enter << "\n";
std::cout << "TIME-OUT " << booking.exit << "\n";
std::cout << " " << "--------\n";
std::cout << "PARKING TIME " << booking.parked() << "\n";
std::cout << " ROUNDED " << booking.parked().roundedHours() << "\n";
std::cout << " " << "--------\n";
auto rates = charge(booking);
float total = rates.first + rates.second;
std::cout << "TOTAL CHARGE " << std::fixed << std::setw(7) << std::setprecision(2) << total << "\n\n";
}
I can't find much redeeming about your original code, so this isn't an answer per se, but perhaps you might find it interesting how I would write code for your problem in "pure C++":
#include <string>
#include <iostream>
#include <sstream>
bool parse_time(std::string const & s, int & t)
{
int h, m;
char c;
std::istringstream iss(s);
if (iss >> h >> c >> m >> std::ws && c == ':' && iss.get() == EOF)
{
t = 60 * h + m;
return true;
}
return false;
}
int main()
{
int t_in, t_out;
std::string line;
if (!(std::cout << "Enter arrival time: " &&
std::getline(std::cin, line) &&
parse_time(line, t_in) &&
std::cout << "Enter departure time: " &&
std::getline(std::cin, line) &&
parse_time(line, t_out)))
{
std::cerr << "Input error! Aborting.\n";
return 0;
}
std::cout << "You spent " << t_out - t_in << " minutes.\n";
}
Here's a typical session:
Enter arrival time: 5:14
Enter departure time: 8:41
You spent 207 minutes.
One thing I noticed — You pass &ehour and friends, which is a pointer to pointer to your scanf call (you can start by removing & from scanf calls when ehour is int*).
Take out the & in scanf! They are already pointers!
The other error in your code is that the variable vehic never gets a value. It looks like you meant to give it a value in getData but messed that up somehow.
Rule 1: Declare variables near to where you first use them. And initialize all variables when you create them:
int main(void)
{
int ehour = 0;
int emin = 0;
int exhour = 0;
int exmin = 0;
getData(&ehour, &emin, &exhour, &exmin);
int thour = 0;
int tmin = 0;
int round = 0;
rate(exhour, exmin, ehour, emin, &thour, &tmin, &round);
char vehic = 0;
float rate1 = 0;
float rate2 = 0;
charge(&vehic, &rate1, &rate2, ehour);
float total = 0;
total= rate1 + rate2;
result( exhour, exmin, ehour, emin, thour, rate1, rate2, round, total);
return 0;
}
Now see that float total? Move the declaration and initialization of the variable to the same line:
float total = rate1 + rate2;
Rule 2: Don't use pointers if you don't need to. If you have an integer you want to pass both into and out of a function, make the parameter a reference parameter like this:
void getData(int& ehour, int& emin, int& exhour, int& exmin)
In main:
getData(ehour, emin, exhour, exmin);
In getData:
void getData(int& ehour, int& emin, int& exhour, int& exmin)
{
char v;
printf("Enter C for car, B for bus, T for truck: ");
scanf("%c", &v);
printf("\nHour vehicle entered 0-24: ");
scanf("%d", &ehour);
printf("\nMinute vehicle entered 0-60: ");
scanf("%d", &emin);
printf("\nHour vehicle exited 0-24: ");
scanf("%d", &exhour);
printf("\nMinute vehicle exited 0-60: ");
scanf("%d", &exmin);
return;
}
Now, I spotted your first screwup. You where reading not to the integers, but to the pointers to the integers. Now that I have made them references (think "aliases" or for the variables passed in), the & operator gets a pointer to the integer, not a pointer to the pointer to the integer!
The next thing you want to do is not to use scanf. Scanf is hard to use. Why use something hard to use?
Step 3: Your program should help you debug it.
When you read something from input, repeat it back out to make sure you read it right. Ie, after you call getData, the very next thing you should do is repeat out what you read. Eventually when your code is solid you can remove that "repeat it back", but when developing a program this kind of feedback is essential.
See Kerrek SB for better ways to read instead of using scanf.