I'm trying to write a c++ program that reads input from a text file and assigns grades using a ten point grading scale then prints the results onscreen.
I think my issue may be with the if else statements in the function deriveGrade, rather than incrementing the enum, they seem to be suming up the increments. Any help would be appreciated, thanks.
#include <iostream>
#include <string>
#include <iomanip>
#include <cmath>
#include <fstream>
using namespace std;
int deriveGrade(double avarage);
enum letter_grade { A, B, C, D, F };
namespace tenPoint
{
letter_grade deriveGrade(double avarage);
char grade;
}
using namespace tenPoint;
int main()
{
string name;
double average;
ifstream inData; // Is the variable for input data from the file.
inData.open("student_status.txt", ios::in);
while (!inData.eof())
{
getline(inData, name);
inData >> average;
inData.ignore();
grade = ::deriveGrade(average);
cout << name << " " << average << " " << char(grade) << endl;
}
inData.close();
return 0;
}
int deriveGrade(double average)
{
if (average >= 90)
{
grade = static_cast<letter_grade>(grade + 65);
}
else if (average >= 80 && average < 90)
{
grade = static_cast<letter_grade>(grade + 1);
}
else if (average >= 70 && average < 80)
{
grade = static_cast<letter_grade>(grade + 2);
}
else if (average >= 60 && average < 70)
{
grade = static_cast<letter_grade>(grade + 3);
}
else if (average <= 50)
{
grade = static_cast<letter_grade>(grade + 4);
}
else
{
cout << "Invalid entry." << endl;
}
return grade;
}
Input from file:
Doe, John K.
93.2
Andrews, Susan S.
84.7
Monroe, Marylin
75.1
Gaston, Arthur C.
62.8
Harpo, Joanie Y.
42.7
Ginger, Fred T.
95.8
Program output:
Doe, John K. 93.2 A
Andrews, Susan S. 84.7 B
Monroe, Marylin 75.1 D
Gaston, Arthur C. 62.8 G
Harpo, Joanie Y. 42.7 K
Ginger, Fred T. 95.8 î
Press any key to continue . . .
Logic of your program is quite strange, but some common remarks can be given without deepening into your task.
Pay attention, that while you use if... else statements one by one like
if (average >= 90)
{
grade = static_cast<letter_grade>(grade + 65);
}
else if (average >= 80 && average < 90)
{
grade = static_cast<letter_grade>(grade + 1);
}
...
there is no need to check average < 90 in the else branch after average >= 90 found false. So at least code can be shorter:
int deriveGrade(double average)
{
if (average >= 90)
{
grade = static_cast<letter_grade>(grade + 65);
}
else if (average >= 80)
{
grade = static_cast<letter_grade>(grade + 1);
}
else if (average >= 70)
{
grade = static_cast<letter_grade>(grade + 2);
}
else if (average >= 60)
{
grade = static_cast<letter_grade>(grade + 3);
}
else if (average <= 50)
{
grade = static_cast<letter_grade>(grade + 4);
}
else // check here! Invalid interval is for values between 50 and 60?
{
cout << "Invalid entry." << endl;
}
return grade;
}
But this is not significant improvement.... much better to make a formula and use single statement with assignment to grade = ...
UPDATE:
And one more comment. If you know the interval of unacceptable values, check it first (before all other calculations):
int deriveGrade(double average)
{
// check the correctness of argument first
if (average > 50 && average < 60)
{
cout << "Invalid entry." << endl; // notification
return grade; // previous value
// also consider returning special value for error case
}
// calculate value for grade
grade = ...
// return updated value
return grade;
}
section "calculate value for grade" is for you, and while writing this part of code keep in mind that:
ternary operation operation is useful for one special case, e.g. grade = (average >= 90)? 65 : floor(100 - average) / 10;
using global values (like grade) in a function is bad practice as well as making logic based on the assumption that initial value of global variable is correct
The reason is because you are adding to your grade variable without clearing it, so the result of previous operations are carried over in deriveGrade.
My advice is to remove the global char grade; in your namespace, use a local variable in your deriveGrade, and a different local variable in your main.
If you look at your function code, grade will only have 65 added to it (to make an ASCII 'A') if your grade is above 90. Every subsequent addition however, pretends that this addition has happened. If you instead make sure that each else if does not rely on previous if or else if code, then your code should be more correct.
char deriveGrade( double average )
if( average > 90.0 )
{
return 'A';
}
else if( average > 80.0 )
{
return 'B';
}
...
This solution removes even the need to use a grade variable in your deriveGrade
An even better alternative that uses the enum you so nicely created is:
enum letter_grade : char
{
A = 'A', B = 'B', C = 'C', D = 'D', F = 'F'
};
Which allows you through a (char)letter_grade to swap between the enum representation and a char (your deriveGrade would then return a letter_grade instead).
Related
I was trying to learn c++ i wanted to find marks using the code the issue is that it is not giving me the correct output and i wanted it to loop if the marks are less i wawnted to repeat it .
This is the code that i wrote
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
void mygrade(int grades)
{
if (grades >= 90)
{
printf("High distinction");
}
else if (grades > 80 < 70)
{
printf("Your Grade is Distinciton");
}
else if (grades > 60 < 70)
{
printf("Credit");
}
else if (grades > 50 < 60)
{
printf("Pass");
}
else if (grades < 50)
{
printf("Fail");
}
else
{
printf("Enter vaild Marks");
}
}
void main()
{
int grades;
printf("Enter your score for this unit\n");
scanf("%d", &grades);
printf("your grade for this unit is: %d ");
}
If you want the program work as you write in the picture, there are three things to do:
You can just use
if (grades >= 90)
// …
else if (grades >=80)
// …
// and so on
since else if statement will be trigger only if all cases above it are not true.
You need to call mygrade() function in the main() function so that it will run.
If you want to repeat the program if the grades are less than 50, then you can use do-while loop.
do
{
//…
}while (grades < 50);
Your mistake is to use comparisons like "(grades > 80 < 70)", which is not allowed in C++. Replace them with the form "((grades > 70) && (grades < 80))"
The answer that I want should be 88.5 but it turns out to be 3.60434e+006. I think there's no problem with my quotient formula. What should I do?
#include <iostream>
using namespace std;
int main()
{
int Grade_one, Grade_two;
int Average = Grade_one+Grade_two;
double average = Average/2;
cout<<"Please input your Grade No.1: ";
cin>>Grade_one;
cout<<"Please input your Grade No.2: ";
cin>>Grade_two;
if (Grade_one == Grade_two){
cout<<"Your Grades are Same."<< endl;
}
if(Grade_one >= 50 && Grade_two >= 50 && Grade_one <= 74 && Grade_two <= 74){
cout<<"Hey! You should focus on your study, your grade is concerningly LOW."<< endl;
}
else if(Grade_one <= 49 && Grade_two <= 49){
cout<<"DUDE! you will fail for sure if you don't study."<< endl;
}
else if(Grade_one >= 75 && Grade_two >= 75 && Grade_one <= 100 && Grade_two <= 100){
cout<<average <<endl;
}
return 0;
}
"result"
Please input your Grade No.1: 88
Please input your Grade No.2: 89
3.60434e+006
Process returned 0 (0x0) execution time : 3.238 s
Press any key to continue.
The answer should be 88.5. How should I fix this?
Grade_one and Grade_two undefined when you first use them. You also need to cast Average to double if you want the result to be double as well.
#include <iostream>
using namespace std;
int main()
{
int Grade_one, Grade_two;
cout<<"Please input your Grade No.1: ";
cin>>Grade_one;
cout<<"Please input your Grade No.2: ";
cin>>Grade_two;
int Average = Grade_one+Grade_two;
double average = (double)Average/2;
if (Grade_one == Grade_two){
cout<<"Your Grades are Same."<< endl;
}
if(Grade_one >= 50 && Grade_two >= 50 && Grade_one <= 74 && Grade_two <= 74){
cout<<"Hey! You should focus on your study, your grade is concerningly LOW."<< endl;
}
else if(Grade_one <= 49 && Grade_two <= 49){
cout<<"DUDE! you will fail for sure if you don't study."<< endl;
}
else if(Grade_one >= 75 && Grade_two >= 75 && Grade_one <= 100 && Grade_two <= 100){
cout<<average <<endl;
}
return 0;
}
int Grade_one, Grade_two;
int Average = Grade_one+Grade_two;
Here, you read uninitialized variables. This is Undefined Behaviour and everything could happen: a crash, trash data, weird behaviour, ...
You need to delay the use of a variable only after you set it to a useful value, e.g.:
int Grade_one, Grade_two;
cout<<"Please input your Grade No.1: ";
cin>>Grade_one;
cout<<"Please input your Grade No.2: ";
cin>>Grade_two;
int Average = Grade_one+Grade_two;
double average = Average/2;
You are calculating average before Grade_one and Grade_two are initialized, that cannot work (it is undefined behavior). If you want to define something now and execute it later thats a function. You can use a lambda expression here. Average is a misnomer, it is a sum, not an average. You are using integer arithmetics for the division, but to get correct result it has to be calculated with floating points. I think you got the conditions for the if right, but the last case is simpler if you just make it an else without the condition. Last but not least, you should initialize variables always:
#include <iostream>
using namespace std;
int main()
{
int Grade_one = 0;
int Grade_two = 0;
auto average = [&](){
int Sum = Grade_one + Grade_two;
return Sum / 2.0;
};
Grade_one = 42;
Grade_two = 12;
if (Grade_one == Grade_two){
cout<<"Your Grades are Same."<< endl;
}
if(Grade_one >= 50 && Grade_two >= 50 && Grade_one <= 74 && Grade_two <= 74){
cout<<"Hey! You should focus on your study, your grade is concerningly LOW."<< endl;
}
else if(Grade_one <= 49 && Grade_two <= 49){
cout<<"DUDE! you will fail for sure if you don't study."<< endl;
}
else {
cout<<average() <<endl;
// ^^ call the lambda
}
return 0;
}
You need to modify your code slightly. Save this piece of universally useful code somewhere (preferably in a header file):
template <class Lam>
class Expr
{
public:
using ResultType = std::remove_reference_t<decltype((std::declval<Lam>())())>;
operator ResultType() { return lam(); }
ResultType value() { return lam(); }
Expr(Lam&& lam) : lam(std::move(lam)) {}
private:
Lam lam;
};
#define EXPR(...) Expr([&](){return (__VA_ARGS__) ;})
When you #include this piece in your program, you can proceed with minimal modifications:
int Grade_one, Grade_two;
auto Average = EXPR(Grade_one+Grade_two); // note the auto
auto average = EXPR(Average/2.0); // and the decimal point
I however strongly recommend exploring the other answers first.
I am currently writing a program for a class involving code for a Grade Point Average calculator with added features. My code was working right up until I added my last line of code for the sum of the grades and subsequent division for the average. I feel like I'm missing something obvious here, but I'm at a loss, currently. Ideally, this program would be accepting input from a user at four separate points, adding the input together, and then dividing it by 4 (as the current number of grades I have code for is 4, but I plan on increasing this amount once I figure out how to solve this issue).
Initially, I was getting errors because I was asking the code to translate a double variable into a char variable and then back into a double variable (error code C4244). I also changed the end of the code to declare the sum of all grades as a separate variable, because including it all in one variable, GPA, resulted in the program outputting a seemingly random number. I since changed my code to flow more evenly, however now when I execute the program, it asks for the initial input for the first grade then skips right over the second, third, and fourth grades.
I'm still extremely new to C++, so I may be over complicating my code, but I'm stumped.
#include <iostream>
using namespace std;
int GPAAndHonorsCalculator;
int main()
{
//Declaring initial values
double A = 4.0;
double B = 3.0;
double C = 2.0;
double D = 1.0;
double F = 0.0;
double GPA = 0.0;
//Created if else statements to handle user input and translation into data for the program to use.
cout << "Please enter your first grade: " << endl;
double gradeOne = 0.0;
cin >> gradeOne;
if (gradeOne == 'A') {
gradeOne = 4.0;
}
else if (gradeOne == 'B') {
gradeOne = 3.0;
}
else if (gradeOne == 'C') {
gradeOne = 2.0;
}
else if (gradeOne == 'D') {
gradeOne = 1.0;
}
else if (gradeOne == 'F') {
gradeOne = 0.0;
}
cout << "Please enter your second grade: " << endl;
double gradeTwo = 0.0;
cin >> gradeTwo;
if (gradeTwo == 'A') {
gradeTwo = 4.0;
}
else if (gradeTwo == 'B') {
gradeTwo = 3.0;
}
else if (gradeTwo == 'C') {
gradeTwo = 2.0;
}
else if (gradeTwo == 'D') {
gradeTwo = 1.0;
}
else if (gradeTwo == 'F') {
gradeTwo = 0.0;
}
cout << "Please enter your third grade: " << endl;
double gradeThree = 0.0;
cin >> gradeThree;
if (gradeThree == 'A') {
gradeThree = 4.0;
}
else if (gradeThree == 'B') {
gradeThree = 3.0;
}
else if (gradeThree == 'C') {
gradeThree = 2.0;
}
else if (gradeThree == 'D') {
gradeThree = 1.0;
}
else if (gradeThree == 'F') {
gradeThree = 0.0;
}
cout << "Please enter your fourth grade: " << endl;
double gradeFour = 0.0;
cin >> gradeFour;
if (gradeFour == 'A') {
gradeFour = 4.0;
}
else if (gradeFour == 'B') {
gradeFour = 3.0;
}
else if (gradeFour == 'C') {
gradeFour = 2.0;
}
else if (gradeFour == 'D') {
gradeFour = 1.0;
}
else if (gradeFour == 'F') {
gradeFour = 0.0;
}
int gradeSum = gradeOne + gradeTwo + gradeThree + gradeFour;
GPA = gradeSum / 4;
cout << GPA;
}
At the suggestion of #LukeH, I cleaned up my code and made a nested while switch statement. Here is part of the working code:
int main() {
//Declaring initial values, as well as initializing a counter for later loop.
int gradeValue = 0;
int gradeCount = 0;
char userGrade = 0;
double GPA = 0.0;
//Creating while loop with switch statement nested inside to handle large amounts of repeating code.
while (gradeCount!= 4) {
cout << "Please enter a grade (A, B, C, D, or F): ";
cin >> userGrade;
switch (userGrade) {
case 'A': {
gradeValue = gradeValue + 4;
++gradeCount;
break;
}
I repeated this process for each grade and it worked a treat!
I commented earlier, but I figured I'd elaborate a bit more if it could help further.
As it seems you have already figured out, you were trying to store a character in a double variable which will either break your code or have some serious unexpected results. Unlike languages like Javascript, variables in C++ have a defined type and cannot change between, say, a double and a string. In your edited code you seemed to have accounted for this and it seems your code is now functioning better.
One important thing to note, especially as it seems you are still learning, is there should be a little internal alarm that goes off in your head as a programmer anytime you are writing blocks of code that are the same or very similar to code you have already written. The saying "DRY" or "Don't Repeat Yourself" is very popular for a reason and can help your code be much easier to read, write, and edit.
For your example, the main function has all of your logic in it and as it gets longer and longer it can be hard to interpret what is happening in the written code. Your code is roughly:
int main() {
//Declaring initial values, as well as initializing a counter for later loop.
int gradeValue = 0;
int gradeCount = 0;
char userGrade = 0;
double GPA = 0.0;
//Creating while loop with switch statement nested inside to handle large amounts of repeating code.
while (gradeCount!= 4) {
cout << "Please enter a grade (A, B, C, D, or F): ";
cin >> userGrade;
switch (userGrade) {
case 'A': {
gradeValue = gradeValue + 4;
++gradeCount;
break;
}
case 'B': {
gradeValue = gradeValue + 3;
++gradeCount;
break;
}
case 'C': {
gradeValue = gradeValue + 2;
++gradeCount;
break;
}
case 'D': {
gradeValue = gradeValue + 1;
++gradeCount;
break;
}
case 'F': {
++gradeCount; // no need to add to value since F=0
break;
}
}
// logic to display GPA
// TODO
If you instead put the user input logic in its own function, your main() will be much cleaner. An added benefit is that if you need to update the logic for getting input (like you did once already!), your main() function doesn't need to change at all.
Your main() would look something like this then:
int main() {
// declare variables
double gradeValue = 0.0;
int gradeCount = 0;
// get input
while(gradeCount < 4) {
gradeValue += getUserGrade(); // add grade to GPA
gradecount++;
}
// logic to display GPA
// TODO
}
Much easier to understand right? In your getUserGrade() function you would just need to have your switch statement logic and return a double value of the grade they input. I left out the logic to display GPA just because this is an assignment and that part is up to you to finish.
With this simpler framework in place, you can easily adjust the code to be able to handle as many grade inputs as the user wants to give. If you just have an option for the user to type "done" or something else significant when they are asked for a grade, you can return a special value that your code in main() can use to know when to stop taking input (-1.0 would work because that would not be a valid GPA). Your main() would look something like this then:
int main() {
// declare variables
double gradeValue = 0.0;
int gradeCount = 0;
// get input
while(true) {
double usrInput = getUserGrade();
if(usrInput == -1.0) break; // exit loop if user is done
gradeValue += usrInput;
gradecount++;
}
// logic to display GPA
// TODO
}
With only changing a few lines of code, you can now have a program that is much more flexible!
Firstly, what are you using the variables A, B,C, D, F for? Secondly you can't use double type variable to store characters. Just use a char variable to get the input grade and set the grade variable accordingly. Also if you plan to add more of these grades, then it will be better for you to either write it in a function and call it again and again(or put the function call in a loop) so that repetition of code is avoided and the code in general looks cleaner.
I was assigned a task to create a Program with the following conditions:
Write a C++ program which accepts amount in rupees as input (integer) within
Range from Rs. 100 to Rs. 100000 and then asks the user for particular currency note
preference and display the total number of Currency Notes of Rs. 500, 100, 50, 20, 10, 5 and 1.
The user can be given a maximum of 200 notes of his preferred choice.
For example: when a user enters a number, Rs. 57477 and enters 50 notes as his preferred
choice, the results would be like this.
Currency Note : Number
500 : 74
100 : 4
50 : 200
20 : 3
10 : 1
5 : 1
1 : 2
I created the above program using Modulo Operator and While Loop.
Part of my code is as Follows:
if (preference == 500)
{
notes500 = rupees/500; //This get all the 500 notes
rupees %= 500; //this will find the remaining rupees after deducting all the 500 notes
while(notes500 > 200) //this loop will make sure the obtained 500 notes are not greater that 200
{
notes500 -=1;
rupees +=500; //this re add all the 500 notes that are not needed back to main amount
}
notes100 = rupees/100; //from here we will get all the 100 notes
rupees %= 100; //from here we will substract the amount of Rs 100 notes obtained
//this process will continue to till it reaches 1 rupee notes
notes50 = rupees/50;
rupees %= 50;
notes20 = rupees/20;
rupees %= 20;
notes10 = rupees/10;
rupees %= 10;
notes5 = rupees/5;
rupees %= 5;
notes1 = rupees;
}
This same logic will continue for other preferences.
Now the following restrictions have been applied on the program:
Use of Loops or Recursions is not allowed.
Arrays are also not allowed.
Program should be made using basic knowledge of C++ (e.g. by using decision control structures, C++ operators, e.t.c.)
Now how am i supposed to create the above program without loops?
Help will be highly appreciated!
Thanks,
This code answers the question "how am i supposed to create the above program without loops?" It is achieved by Meta Programming with templates. The recursion constraint is solved as well because the compiler builds out the iterative code. However, I could not solve the preferred note constraint. I process the preferred denomination first but there are many cases like preferred note 1 and rupees total of 201. Looking forward to see the ultimate solution.
#include <iostream>
template <int denom, typename T>
class VegasCashier {
public:
static T result(T a, T b) {
int leftOver = b;
int dcount = 0;
if (denom == 0) // First time in process the favorite
{
leftOver = b;
dcount = b / a;
leftOver %= a;
// From Pete's Comment
if (dcount > 200) { leftOver += a * (dcount - 200); dcount = 200; }
if (dcount > 0)
std::cout << "\tGive " << dcount << " of Denomination "
<< a << " (Favorite) " << std::endl;
}
else if (b != 0 && a != denom) // c is the favorite
{
leftOver = b;
dcount = b / denom;
leftOver %= denom;
// From Pete's Comment
if (dcount > 200) { leftOver += denom * (dcount - 200); dcount = 200; }
if (dcount > 0)
std::cout << "\tGive " << dcount << " of Denomination "
<< denom << std::endl;
}
if (denom == 0) // Special case for desired denomination
return VegasCashier <500, T>::result(a, leftOver); // Start cashout at highest denom
else if (denom == 500)
return VegasCashier<100, T>::result(a, leftOver);
else if (denom == 100)
return VegasCashier<50, T>::result(a, leftOver);
else if (denom == 50)
return VegasCashier<20, T>::result(a, leftOver);
else if (denom == 20)
return VegasCashier<10, T>::result(a, leftOver);
else if (denom == 10)
return VegasCashier<5, T>::result(a, leftOver);
else if (denom == 5)
return VegasCashier<1, T>::result(a, leftOver);
return dcount;
}
};
// This template stops the implementation
template < typename T>
class VegasCashier<1, T> {
public:
static T result(T a, T b) {
if ( b > 0 )
std::cout << "\tGive " << b << " of Denomination " << 1 << std::endl;
return 0;
}
};
// Starting function
template <int denom, typename T>
inline T CasinoResults(T a, T b)
{
std::cout << "\nCashing out " << b << "..." << std::endl;
return VegasCashier<0, T>::result(a, b);
}
int main()
{
CasinoResults<0>(5, 5006);
CasinoResults<0>(500, 99502);
CasinoResults<0>(500, 7519);
CasinoResults<0>(1, 7509); // Fails the Preferred note constraint
}
variable or field `letterGrade' declared void. This error message is coming up on the last iteration of the function 'letterGrade'. Anyone have an idea why?
#include <string>
#include <iostream>
using namespace std;
void letterGrade (int score, string& scoreLetter);
string scoreLetter;
int main()
{
int score;
char A, B, C, D, F;
cout<<"Enter the grade: ";
cin>> score;
letterGrade (score, scoreLetter);
cout<<"The letter grade is a(n) "<< scoreLetter<<".";
system ("pause");
return 0;
}
void letterGrade (score, scoreLetter)
{
for (score >= 90)
{
scoreLetter = 'A';}
if (score == 100)
{
scoreLetter.insert (1, "+");
}
else if (8<=score% 10 && score% 10 <= 9)
{
scoreLetter.insert (1, "+");
else if (0<=score% 10 && score% 10 <=1)
{
scoreLetter.insert (1, "-");
}
You aren't naming the types on the parameters of the definition of letterGrade.
void letterGrade (score, scoreLetter)
{
//...
In the function definition above, you forgot to specify the types. Mention the types as:
void letterGrade (int score, std::string & scoreLetter)
{ // ^^^this ^^^^^^^^^^^^^this
//...
Don't forget to #include<string>.
Another problem is this:
for (score >= 90)
The form of for should be this:
for(initialization; condition ; increment/decrement/changing-some-value)
Example:
for ( int i = 0 ; i <= score ; i++)
First of all, as the others said - fix the letterGrade definition:
vvv vvvvvvvvvvvv
void letterGrade( int score, std::string& scoreLetter )
After that, fix the for, it should be something like:
for (; score >= 90; --score )
{
//..
}
Also, note that you shadow the global scoreLetter in letterGrade
Are you actually looping in the letterGrade function?
Most homework assignments like this only require an if-then-elseif-else ladder.
I suggest removing the for statement and replacing with an if statement. If you decide you need to loop or repeat, restore the for statement.
A for loop would allow you to traverse a table of scores vs. grade strings:
struct Grade_Score
{
unsigned int grade;
const char * grade_text;
};
const Grade_Score grade_table[] =
{
{100, "A+"},
{90, "A"},
{80, "B"},
{70, "C"},
{60, "D"}
};
const unsigned int NUM_GRADE_ENTRIES =
sizeof(grade_table) / sizeof(grade_table[0]);
std::string Grade_To_Score(unsigned int grade)
{
std::string score = "F";
for (i = 0; i < NUM_GRADE_ENTRIES; ++i)
{
if (grade >= grade_table[i].grade)
{
score = grade_table[i].grade_text;
break;
}
}
return score;
}
A similar search can be performed using the std::lower_bound or std::upper_bound functions.
Edit 1:
I suggest you replace system("pause"); with something more portable like:
cout << "Press Enter to continue\n";
cout.ignore(10000, '\n');
Not all platforms support the pause command.
IIRC for can be written with only the comparison, aka end condition, specified
for (a>b)
for (a=2; a>b)
for (a>b; a++)
Should all work providing we do the missing initialization or iterator elsewhere in the code.