Related
I'm currently learning about functions in C++ and am currently working on a homework assignment with functions being the main thing.
Currently, I'm trying to make a grade calculator with every operation of the process being split into a function of its own.
Here's the code:
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
using namespace std;
void getHWGrades(int homeworks[], int size)
{
cout << "\nEnter the grades, out of 100 points, for the 9 homeworks you completed." << endl;
cout << "Note that Homework 10 is given to you for free, but is the same grade \nas homework 9.\n" << endl;
for (int i = 0; i < 9; i++)
{
cout << "Homework " << i + 1 << ": ";
cin >> homeworks[i];
while (homeworks[i] > 100 || homeworks[i] < 0)
{
cout << "Invalid grade, input homework grade again: ";
cin >> homeworks[i];
}
}
homeworks[9] = homeworks[8];
cout << "Homework 10: " << homeworks[9];
}
double quizAverage()
{
double quizPts;
cout << "Input your in class quiz average: ";
cin >> quizPts;
return quizPts;
}
double labAverage()
{
double labPts;
cout << "Input your lab average: ";
cin >> labPts;
return labPts;
}
double teamProject()
{
double teamPts;
cout << "Input your team project grade: ";
cin >> teamPts;
return teamPts;
}
int exam1()
{
int exam1Pts;
cout << "Input your exam1 grade: ";
cin >> exam1Pts;
return exam1Pts;
}
int exam2()
{
int exam2Pts;
cout << "Input your exam2 grade: ";
cin >> exam2Pts;
return exam2Pts;
}
double hwAverage(int homeworks[], int size)
{
double total = 0;
double homeworkAverage = 0;
for (int i = 0; i < size; i++)
{
total = total + homeworks[i];
}
homeworkAverage = (total*1.0) / 10;
return homeworkAverage;
}
double currentPoints(double& quizPts, double& labPts, double& teamPts, double& homeworkAverage, int& exam1Pts, int& exam2Pts)
{
double totalPts = ((quizPts / 100.0) * 10) + ((labPts / 100.0) * 10) + ((teamPts / 100.0) * 15) + ((homeworkAverage / 100.0) * 20) + ((exam1Pts / 100.0) * 10) + ((exam2Pts / 100.0) * 15);
cout << "\nYour current points (out of the 80 total available), stand at: " << totalPts;
return totalPts;
}
double currentAverage(double& totalPts)
{
double availableAverage = totalPts*(100.0 / 80);
cout << "\nYour current average is: " << availableAverage;
return availableAverage;
}
int main()
{
// keep the console from closing in visual studio
char charer;
double totalPts;
double quizPts, labPts, teamPts, homeworkAverage;
int exam1Pts, exam2Pts;
const int ARRAY_SIZE = 10;
int hwArray[ARRAY_SIZE];
getHWGrades(hwArray, ARRAY_SIZE);
quizAverage();
labAverage();
teamProject();
exam1();
exam2();
currentPoints(quizPts, labPts, teamPts, homeworkAverage, exam1Pts, exam2Pts);
currentAverage(totalPts);
cin >> charer;
}
My issue, which I believe lies in the functions currentPoints and currentAverage, is that when I run this totalPts outputs as -5.09078e+61 and as a follow up result with the currentAverage function, availableAverage outputs as -1.157e+62.
I'm sure that the issue has to do with how I'm passing the values from function to function (which I doubt I'm doing correctly).
How would I go about fixing this issue?
Thank you in advance.
You need to store the return value from currentPoints() function, like this.
totalPts = currentPoints(quizPts, labPts, teamPts, homeworkAverage, exam1Pts, exam2Pts);
currentAverage(totalPts);
Reason is, you declared "totalPts" as local variable in currentPoints().
"Local variables has function scope only, it is undefined to main function".
Do this for all other
functions(quizAverage,labAverage,teamProject,exam1,exam2, hwAverage,currentAverage)
I hope, this will solve the issue !!!
The problem is not about functions, it's about variables.
Let's take quizPts for instance:
In the main method, you declare this variable, but then you don't do anything with it before sending it to currentPoints. Therefore it has an undefined value when you do so (undefined often looks like random in C).
The other variable quizPts you use in quizAverage have the same name but is not the same for the compiler.
Try in your main:
quizPts = quizAverage();
You asked
How would I go about fixing this issue?
And the answer is "Use the debugging tool with "watches" window open in your favorite IDE".
It's always very difficult to find an error simply by re-reading the code, but in the debugger you can see all the values of your variables at each moment of time. Specifically, in this example, you would realize that your variables have garbage values from the very beginning (are not initialized), and this value never changes.
Using this approach you could find the reason yourself in time less than necessary to write this SO question. I hope this will help you to save your time in future.
The problem is you use the variables such as quizPts and labPts without storing any value in them. In your case, you have to store the return value of the function to the corresponding variable before using it. For example, do the same as the following statement:
quizPts = quizAverage();
BIG EDIT: I added in and it now detects string inputs :)!
if (false == isdigit(grade[0])
edit: The problem: can not determine if I put in a string instead of a float or int.
I've been looking all through this website and there's many posting about checking string input. Here is my take on trying to combine everything I learned, and as you can see, It's not doing what I want it to do.
Such inputs and what happens:
user input: "1.2" : can tell it's a float
user input: "1" : can tell it's a int
user input: "a": ERROR : think's it's a float. This is the problem. If I enter in 'a' I need the program to recognize that a string was inputted and this calling in certain functions.
Some guidance would be much appreciated:
#include "assessGrade.h"
int main(void)
{
int finalGrade = 0;
int gradeHolder = 0;
int numberGrade[5] = { 0,0,0,0,0 };
double doubleGrade = 0;
//my beloved bool's
bool floatGrade = false;
bool intGrade = false;
bool stringGrade = false;
//======================================//
// Getting the input from user //
// Also check for stringfloat/int type //
//======================================//
std::string grade;
std::getline(std::cin, grade);
std::stringstream stream(grade);
if (false == isdigit(grade[0]))
{
//it's not a digit
cout << "STRING: " << grade << endl;
stringGrade = true;
}
else if(!(stream >> gradeHolder) || grade.find('.') != std::string::npos)
{
//its a float!
cout << "FLOAT: " << grade << endl;
floatGrade = true;
}
else
{
//it's a int!
cout << "INTEGER: " << grade << endl;
intGrade = true;
}
//======================================//
// Parsing the input //
//======================================//
if (intGrade == true)
{
//do int stuff here
}
else if (floatGrade == true)
{
//do float stuff here
//doubleGrade = grade;
}
else
{
//do string stuff here
}
return 0;
}
It's far from easy to determine exactly what a "float value" would be. Is +1.0E-02 a float variable? It's got a letter in it!
You almost got the decent solution. Use std::stringstream to see if you can extract an integer or float value. You will need to .clear() it, if the first attempt fails.
I used function overload to check if an input number is integer or float. However I get this following error:
error: call of overloaded 'retNr(double)' is ambiguous|
#include <iostream>
using namespace std;
void retNr(int x)
{
cout << "The entered number is an integer. " << endl;
}
void retNr(float x)
{
cout << "The entered number is a float. " << endl;
}
int main()
{
cout << "Please enter a number: " << endl;
cin >> nr;
retNr(nr);
return 0;
}
Read from cin into a string and then check the string for the presence of a decimal point. If there is a decimal point, call atof() on the string to convert it to a float, otherwise call atoi() to convert it to an integer.
Make some small change in:
void retNr(double x)
{
cout << "The entered number is a double. " << endl;
}
Remember to declare your nr variable.
double d = 1.0;
int i = 1;
retNr(d);
retNr(i);
You will have to initialize nr first.
Then you can use integer read & check it with a float if there is dot, ie ch=='.'
Thus, your program will be like this:
#include <iostream>
using namespace std;
int main()
{
int nr = 0; char ch;
cout << "Please enter a number: " << endl;
cin >> nr;
cin.get(ch);
if(ch=='.')
{
cout << "The entered number is a float. " << endl;
}
else
{
cout << "The entered number is an integer. " << endl;
}
return 0;
}
It's not too clear what you're asking for. If you really want
to know whether a number is an integer or not, then use modf
on it:
bool
isInt( double d )
{
double dummy;
return modf( d, &dummy ) == 0.0;
}
If you're reading a number, then read it as a double, and then
use the above.
If you want to trigger off the format of the input (i.e.
"10.0" will be treated as a floating point, even though it is
an integer), then read the input as a string, then try to
convert it to int; if this eats all of the input, then it was
entered as an int (no decimal or exponent), otherwise, try the
same thing treating it as a double:
std::string entry;
std::cin >> entry;
char const* end;
long i = strtol( entry.c_str(), &end, 10 );
if ( *end == '\0' ) {
// entry was entered in integral format...
} else {
double d = strtod( entry.c_str(), &end );
if ( *end == '\0' ) {
// entry was entered in floating point format...
} else {
// entry wasn't a number...
}
}
I'd advise against this, however; it will only confuse your
users if 0 isn't 0.0.
You may use abs() function for this issue.
#include<stdio.h>
#include<math.h>
int main()
{
double input;
scanf("%lf",&input);
int absulate = abs(input);
printf( (input==absulate)? "It is integer\n" : "It is float");
return 0;
}
float num = 7;
int n = (int)num;
float n1 = (float)n;
if(num == n1)
{
cout << "Integer\n";
}
else
{
cout << "Not Integer\n";
}
The question is wrong in its essence: A number it is not a float or an integer, but could be represented as a float or as an integer ( of course certain representation has some limitations )
So if I wrote '10' why should I say this is an integer? Could be a float too! Just if I want to use it as a float I would represent it as a float.
I am writing a program for my C++ class and can't seem to figure out what the problem with is with my code. The code compiles but something causes the program to crash after line 16 that I just can't figure out.
#include <iostream>
// Declare Global variables and Prototyping
int const TAX = .07;
float inputStickerPrice();
int main()
{
float totalStickerPrice = 0.0, discount = 0.0, totalPrice = 0.0;
char* pass = "";
// Calculate the total sticker price
while (pass != "n")
{
totalStickerPrice += inputStickerPrice();
std::cout << "Would you like to enter another item? [y/n] ";
std::cin >> pass;
// Pass validation Loop
while (pass != "y" && pass != "n")
{
std::cout << "INVALID INPUT. Please enter y for yes or n for no. ";
std::cin >> pass;
} // End of Pass Loop
} // End of Sticker Price Loop
// Input Discount
while (!(discount >= 0.0 && discount <= 1))
{
std::cout << "Please enter the discount: ";
std::cin >> discount;
// Validate input
if (!(discount >= 0.0 && discount <= 1))
{
std::cout << "INVALID INPUT. Discount must be between 0.0 and 1.0. ";
} // End of validation
} // End of Discount Loop
totalPrice = totalStickerPrice * discount; // Apply Discount to total Sticker Price
std::cout << "The Subtotal is: " << totalPrice << std::endl;
totalPrice *= (1+TAX); // Apply Tax to Subtotal
std::cout << "The Cost after Tax is: " << totalPrice << std::endl;
std::cin.get();
return 0;
}
//**********************
// Input sub program *
//**********************
float inputStickerPrice()
{
using namespace std;
float sticker = 0.0;
cout << "Please input the sticker price of the item: ";
cin >> sticker;
// Validation Loop
while(!(sticker >= 0.0 && sticker <= 9999.99))
{
cout << "INVALID INPUT. Please input a value between 0 and 9999.99: ";
cin >> sticker;
} // End of Validation Loop
return sticker;
} // End of Input Function
char* pass = "";
Here you declared a pointer to a string literal, an array of characters which occupies a region of storage that you're not allowed to modify. Recent compilers that follow C++11 standard are supposed to produce an error for this line, because string literals are not implicitly convertible to char* anymore, but to const char* instead.
When you modify this memory in this line std::cin >> pass; your program has undefined behaviour and all bets are off. A crash is just one of possible outcomes.
Next, you can't compare strings like that:
pass != "y"
pass is a pointer and "y" decays to one. You're not comparing contents of string here, but pointer values that will never be the same.
Forget about pointers until you're ready to tackle them, use std::string class instead. Then comparing strings will be as easy as str1 == str2.
while (pass != "n")
pass is a pointer, so you should use *pass or pass[0] if you want to obain its value.
Besides look at #Borgleader comment
EDIT:
Change char pass*; into std::string pass; - it should fix the issue.
I tried to find the smallest number within 3 inputs. Here is my codes :
int main ()
{
double x = 4.0;
double y = 5.0;
double z = 3.0;
smallest(x,y,z);
cout << smallest << endl;
system("PAUSE");
}
double smallest(double x, double y, double z)
{
double smallest;
if ((x < y)||(x< z)) {
smallest = x;
} else if ((y < z)||(y < x)) {
smallest = y;
} else {
smallest = z;
}
return smallest;
}
However, I keep getting error. It stated that my smallest method in main method with undeclared identifier. This works when using eclipse but not visual studio. Can somebody explain to me why?
Thanks in advance.
Updated portion.
So I tried to do validation for this program. I want to ensure users only enter number and here are my codes :
double x, y, z;
bool correct_input = false;
do{
cout << "Enter first integer : " ;
cin >> x;
if(isdigit(x)){
correct_input = true;
}
}while(!correct_input);
do{
cout << "Enter second integer : ";
cin >> y;
if(isdigit(y)){
correct_input = true;
}
}while(!correct_input);
do{
cout << "Enter third integer : ";
cin >> z;
if(isdigit(z)){
correct_input = true;
}
}while(!correct_input);
cout << "Smallest integer is : " << smallest(x,y,z) << endl;
system("PAUSE");
When I entered alphabet or whatever except numbers, I get debug assertion failed. It does not prompt until user enter correct input. Can somebody help?
First of all, if you wish to use smallest() before it's defined, you need to prototype it. Add the following before main():
double smallest(double x, double y, double z);
Also, you are ignoring the return value of smallest(). Change
smallest(x,y,z);
cout << smallest << endl;
to
double smallest_val = smallest(x,y,z);
cout << smallest_val << endl;
This isn't the question you asked but your function is bugged because you confused || and &&.
Your function should be
double smallest(double x, double y, double z)
{
double smallest;
if (x < y && x < z)
smallest = x;
else if (y < z && y < x)
smallest = y;
else
smallest = z;
return smallest;
}
x is the smallest number if it is less y and it is less than z.
update
First thing to say is that if you want integers then you should be using int not double.
Second thing, isdigit doesn't do what you think it does. You've actually set yourself a very difficult problem. Here's one way to do it
#include <string> // for string class
bool correct_input = false;
do
{
cout << "Enter first integer : " ;
if (cin >> x)
{
correct_input = true;
}
else
{
// cin is in a error state after a failed read so clear it
cin.clear();
// ignore any remaining input to the end of the line
string garbage;
getline(cin, garbage);
}
}
while(!correct_input);
But this doesn't work perfectly. For instance if you enter abc then your program will ask for more input, but if you enter 123abc, then you will get the integer 123 even though 123abc is not a valid number.
If you really want to do this properly (and it is hard) then you must read in a string, check if the string could be converted to a number, if it can then do the conversion, if it can't then ask for more input.
Put this line above your main ;).
double smallest(double x, double y, double z);
You need to declare any function you make. This is called making a function header.
You should declare you function so that the compiler can recognize it.
Put its prototype above main function as this:
double smallest(double, double, double);
int main()
{
//Staff
}
There are two problem, here, one related to how to get the smallest, and the other related to ho get correct input.
For the first problem, let me propose a recursive approach:
// this is trivial
double smallest(double x, double y)
{ return (x<y)? x: y; }
// the smalles of three is the smallest between the smallest of two and the third
double smallest(double x, double y, double z)
{ return smallest(smallest(x,y),z); }
For the second problem, you have the same problem for each of the variables, so let's make a function for it:
#include <iostream>
#include <limits>
#include <string>
double read(std::istream& s, std::ostream& o, const std::string& message)
{
for(;;) //stay here until kiked out
{
double d=0.; //just a safe value - no particular meaning
o << message << std::endl; // prompt the request
bool good(s >> d); //read a double and keep the state
if(!good) s.clear(); //if we failed to read, clean the stream state
//in any case, discard everything unread until the return.
s.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if(good) return d; //if reading succeeded, return.
//overwise loop back
}
}
This is based on the fact the std::cin have a state that is set to "bad" is the input cannot be read in the given variable.
We just read, and, if it fails, redo again and again.
But fist we have to clear the state, so thet the input can be unlocked.
Independently og good an bad reading, we have then to discard everuthing "extra" that can be typed in the line (think to 123asdf: we successfully read 123, but we have to discard abc)
The the reading was successful we just return it, otherwise we loop over and over until we get it.
The program itself, at this point will reduce to:
int main()
{
double x = read(std::cin, std::cout, "Enter first value");
double y = read(std::cin, std::cout, "Enter second value");
double z = read(std::cin, std::cout, "Enter third value");
std::cout << "the smallest numer is: " << smallest(x,y,z) << std::endl;
return 0;
}
that can run this way:
Enter first value
7
Enter second value
5.2yyyy
Enter third value
sf3
Enter third value
455
the smallest numer is: 5.2
A more advanced technique can be transform the function into a manipulator class, like this:
class read_value
{
public:
read_value(double& d, const std::string& prompt_, std::ostream& out_ = std::cout)
:z(d), prompt(prompt_), outstream(out_)
{}
friend std::istream& operator>>(std::istream& s, const read_value& a)
{
for(;;)
{
a.outstream << a.prompt << std::endl; // prompt the request
bool good(s >> a.z); //read a double and keep the state
if(!good) s.clear(); //if we failed to read, cleanr the stream state
//in any case, discard everything unread until the return.
s.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if(good) return s; //if reading succeeded, return.
//overwise loop back
}
}
private:
double& z;
std::string prompt;
std::ostream& outstream;
};
letting the program a more idiomatic form:
int main()
{
double x,y,z;
std::cin >>
read_value(x,"Enter first value") >>
read_value(y,"Enter second value") >>
read_value(z,"Enter third value");
std::cout << "the smallest numer is: " << smallest(x,y,z) << std::endl;
return 0;
}
Another point can be the fact the user can loop forever by never typing a good sequence.
We can fix a maximum attempt limit introducing a counter in the for loop, and setting the input to "failed" if the loop terminates without returning:
friend std::istream& operator>>(std::istream& s, const read_value& a)
{
for(int i=0; i<10; ++i)
{
... //same as before
}
return s; //s will be returned in failed state
}
And then checking in the main program:
int main()
{
double x,y,z;
std::cin >>
read_value(x,"Enter first value") >>
read_value(y,"Enter second value") >>
read_value(z,"Enter third value");
if(!std::cin)
{
std::cout << "bad input." << std::endl;
return -1; //report as "program failed"
}
std::cout << "the smallest numer is: " << smallest(x,y,z) << std::endl;
return 0; //succeeded
}
.