Related
I am trying to make a loop where I enter 30 or less student's GPA and get: the average gpa, highest and lowest gpa, adjusted average, see if a specific gpa was entered and display the contents of the array. But when I run the code I have, I can only enter one gpa...
#include <stdio.h>
#include <stdlib.h>
#define GPA_COUNT 30
main(){
int gpa [GPA_COUNT];
int total = 0, i;
double average;
for(i = 0; i < GPA_COUNT; i++){
printf("Enter student %i's GPA: \n", i + 1);
scanf("%i", &gpa[i]);
}
for(i = 0; i < GPA_COUNT; i++){
total += gpa[i];
if(gpa[i] > 2.0){
printf("You need to study harder! \n");
}
else if(gpa[i] < 3.5){
printf("Nice work! \n");
}
}
average = (double)total / GPA_COUNT;
printf("The average GPA is: %.2lf \n", average);
system("pause");
}
I would like to be able to enter the rest of the gpa's.
As Antii Haapala says in his comment, your problem is that you've initialized gpa as an integer, and are using printf to scan in an integer -- but are actually entering a double.
To fix it, you simply need to expect a double instead:
double gpa [GPA_COUNT];
// -- snip --
scanf("%lf", &gpa[i]);
I'm assuming you're a student, so here are a couple of other notes to help you improve your code:
Take a look at your conditional when checking the student's GPA (what happens if a student scores a 1.0? A 4.0?)
You can remove the \n from this line (printf("Enter student %i's GPA: \n" i + 1);) to have the inputs on the same line.
Consider what will happen if someone throws garbage input at your program -- sanitizing user inputs is important! A safer, but still simple, method would be to read the user input as a string, and then attempt to convert the input with something like strtod.
I've been trying to figure this out the last few days, but no luck. The objective is to find the sum, average, minimum, and maximum grades and display them.
Here is my code, everything except minimum, maximum and grade input seem to work
// Includes printf and scanf functions
#include <stdio.h>
int main(void) {
unsigned int counter; // number of grade to be entered next
int grade; // grade value
int total; // sum of grades entered by user
float average; // average of grades
int maxi; // Max grade
int mini; // min grade
int i;
int max;
int min;
maxi = 1;
mini = 1;
printf("Enter number of grades: "); // User enters number of grades
scanf("%d", &counter); // Countss number of grades
//scanf("%d%d", &min, &max);
for (i = 1; i <= counter; i++) {
printf("Enter grade %d: ", i); // User enters grade
scanf("%d", &grade); // Counts grades
//scanf("%d",&counter);
if (grade < 0 || grade > 100) {
printf("Please enter a number between 0 and 100!\n"); // Lets user know if input is invalid
i--;
break;
}
else {
total = total + grade;
average = (float)total / counter; // NOTE: integer division, not decimal
}
}
max = (grade < maxi) ? maxi : grade;
min = (grade > mini) ? mini : grade;
printf("Class average is: %.3f\n", average); // Displays average
printf("Your maximum grade is %d\n", max); // Displays Max
printf("Your minimum grade is %d\n", min); // Displays minimum
printf("Sum: %d\n", total); // Displays total
}
Output:
Enter number of grades: 2
5
7
Enter grade 1: 4
Enter grade 2: 3
Class average is: 3.500
Your maximum grade is 3
Your minimum grade is 1
Sum: 7
For some reason when I start the program, I have to enter a few numbers, in this case 5 & 7 before it prompts me to "Enter grade" then from there it calculates everything. Also, it seems that the Maximum is always the last grade that I enter and shows 1 as the minimum when no where in the input is 1. I am supposed to use a conditional operator for the max/min, I tried looking it up and reading the book, but they just use letters like a,b,c, etc. Which just confused me so I'm not sure if I did it wrong.
Could that be what is messing everything up? If it isn't what am I doing wrong?
Another thing is I'm thinking I need a While loop if I want to make the counter have an input from 1-100, is that right?
Edit: just realized I had to remove the scanf for max and min. Taht's why I had to inptu 2 nubmers first
There are two major problems, as I see it
The variable total is not initialized, so the first occurrence of total = total + grade; would invoke undefined behaviour.
You have to initialize it explicitly to 0.
The same variable grade is used for holding the repeated input. After the loop, grade will only hold the last input value.
You need to either use an array for storing inputs and comparison, or, compare and update the min and max as you go, inside the loop.
For future references, please seperate your code in different functions or add comments, since analyzing an unfamiliar code always takes much time.
min: Your problem here lies, that you're initializing your min value with 1. That value is most of the time below your input grades. If you want to initialize it, you should use a high number.
For example:
#include <limits.h>
int min = INT_MAX;
max: Your "grade" will be always the last typed grade, which you scanned. That's not what you want. It would be good, to save all values, which you get as input in an array or a list.
Also your codesnippet at the end
max = (grade<maxi) ? maxi : grade;
min = (grade>mini) ? mini : grade;
will just compare one grade. You need to compare all values, which you entered.
You could just put them in the for-loop.
gradeinput: You need to temporarily save your inputs in a datastructure like an array/list to use them in your program.
int x[counter];
for (i = 1; i <= counter; i++) {
printf("Enter grade %d: ", i);
x[i]=scanf("%d", &grade);
}
.. have to enter a few numbers, in this case 5 & 7 before it prompts me to "Enter grade"
This happens because OP's stdout is buffered and not one character at a time.
To insure output is seen before the scanf(), use fflush().
See What are the rules of automatic flushing stdout buffer in C?
printf("Enter number of grades: ");
fflush(stdout); // add
scanf("%d", &counter);
Rather than set the min = 1, set to a great value
maxi = 1;
mini = 1;
maxi = 0;
mini = 100;
// or
maxi = INT_MIN;
mini = INT_MAX;
Move the test for min/max in the loop to test each value and fold maxi, max into the same variable.
if (max > grade) max = grade;
if (min < grade) min = grade;
The first total + grade is a problem as total is uninitialized.
// int total; // sum of grades entered by user
int total = 0; // sum of grades entered by user
Unnecessary to calculate average each time though the loop. Sufficient to do so afterward.
Style: After the break; the else is not needed.
Good that code tests user input range. Yet the i-- is incorrect. If code is to break, just break. If code it to try again, the i-- makes sense, but then code should continue.
The comment // NOTE: integer division, not decimal is incorrect as (float) total / counter is FP division.
if (grade < 0 || grade > 100) {
printf("Please enter a number between 0 and 100!\n");
i--;
continue;
}
total = total + grade;
} // end for
average = (float) total / counter;
In general, casting should be avoided.
Advanced issue: Consider the situation if later on code was improved to handle a wider range of integers and used higher precision FP math.
The 1st form causes total to become a float (this could lose precision) and perhaps use float to calculate the quotient, even if average was a double. Of course the (float) cast could be edited to (double) as part of the upgrade, but that is a common failure about updates. Types may be changed, but their affected object uses are not fully vetted.
The 2nd form below causes total to become the same type as average and use the matching math for the type. Reduced changed needed as the types change. This form is also easier to review as one does not need to go back and check the FP type of average to see if a cast to float, double or even long double was needed.
average = (float) total / counter;
// or
average = total;
average /= counter;
For some reason when I start the program, I have to enter a few numbers, in this case 5 & 7 before it prompts me to "Enter grade"
You have two scanf before "Enter grade"
scanf("%d", &counter);
scanf("%d%d", &min, &max);
#include <stdio.h>
int main(void) {
int counter; // number of grade to be entered next
int grade; // grade value
int total=0; // sum of grades entered by user
float average; // average of grades
int i;
int max;
int min;
printf("Enter number of grades: "); // User enters number of grades
scanf("%d", &counter); // Countss number of grades
for (i = 1; i <= counter; i++) {
printf("Enter grade %d: ", i); // User enters grade
scanf("%d", &grade); // Counts grades
if (grade < 0 || grade > 100) {
printf("Please enter a number between 0 and 100!\n"); // Lets user know if input is invalid
i--;
} else {
if(i==1){
max = grade;
min = grade;
}
else{
max = (grade < max) ? max : grade;
min = (grade > min) ? min : grade;
}
total = total + grade;
average = (float) total / counter; // NOTE: integer division, not decimal
}
}
printf("Class average is: %.3f\n", average); // Displays average
printf("Your maximum grade is %d\n", max); // Displays Max
printf("Your minimum grade is %d\n", min); // Displays minimum
printf("Sum: %d\n", total); // Displays total
}
I've edited your Code as there were some mistakes. First, you were not initialising the total, which may make it take some garbage value. The second one is no need of using break as you are reducing the value of i.The third one is that you are updating the min and max outside the for loop, where the value of grade will be the last entered grade. And maxi and mini are not at all needed. The code was running perfectly without waiting for dummy values. Cheers!
I'm in school learning C. (I am not asking for anyone to write this for me).
Assignment
This program will calculate the miles per gallon MPG for you for three tanks of gas after you have entered the gallons used and miles driven.
I can get my program to start a loop, but I can't figure out how to make it end the loop after 3 runs and give me the Average MPG in 3 tanks. Running the program give me the average, but will keep asking forever.
#include <stdio.h>
int main(void) {
int miles;
float gallons = -1, mg, overall = 0, avg = 0;
while(gallons != 0) {
printf("Enter the gallons used: ");
scanf("%f", &gallons);
if (gallons == 0) {
printf("\n\n The overall miles/gallon was: %f\n", overall/avg);
exit(0);
}
printf("Enter miles driven: ");
scanf("%d", &miles);
mg = miles/gallons;
printf("The miles/gallon for this tank was : %f\n", mg);
overall += miles;
avg += gallons;
}
return 0;
}
Try this small changes. Use an iterator to get average of 3 tanks.
Modify like
i=0;
while(i < 3) {
i++;
#include <stdio.h>
int main(void) {
int miles, **i=0;**
float gallons = -1, mg, overall = 0, avg = 0;
**while(i < 3)** {
printf("Enter the gallons used: ");
scanf("%f", &gallons);
if (gallons == 0) {
printf("\n\n The overall miles/gallon was: %f\n", overall/avg);
exit(0);
}
printf("Enter miles driven: ");
scanf("%d", &miles);
mg = miles/gallons;
printf("The miles/gallon for this tank was : %f\n", mg);
overall += miles;
avg += gallons;
**i++;**
}
return 0;
}
Sorry: I did not see how is gallons being assigned/initialized in your code, I saw float galons and while (gallons != 0) and then thought that gallons was at some point the result of a computation.
This answer is still useful in my opinion.
Don't use float values to check conditions, floats are not accurate because their machine representation cannot be, so gallons != 0 will probably hardly ever be true, use int instead and your loop control will work correctly. Only use float for the average value.
But in fact, because your specific problem can be solved with a for loop, you should use
for (int i = 0 ; i < 3 ; ++i)
instead, that way you know that it will only loop 3 times.
SIDE NOTE: learn more about scanf() and why you MUST check the value that it retuns in programs like yours.
Your program, as written, does not stop at 3 tanks. It will continuously ask for tanks until you answer 0 to the number of gallons used.
To make it read at most three tanks, replace while (gallons != 0) with for (int i = 0; i < 3; i++). That will make the main loop run three times only.
But then it won't print the overall average. It will simply quit after running three times. The code that shows the overall average is inside that if test that checks if you typed 0 gallons. Remove that if test and move the printf statement which shows the overall average near the end of the program, right before the return statement. This way it will run after the for loop runs 3 times.
float gallons = -1;
It doesn't make any sense;
And you need to notice one thing that is
while(gallons!=0){
//code
}
You are asking the user to enter the value if gallons to input and your not changing it's value so this value will always be true in while and loop will go infinite.
If you need to run the loop three times then you can do it by using variable.
`
int i=3;
while(i>0){//code
i--;
}
Here I have edited your program ;
#include <stdio.h>
int main(void) {
int miles,i=3;
float gallons, mg, overall = 0, avg = 0;
while(i>0) {
printf("Enter the gallons used: ");
scanf("%f", &gallons);
if (gallons == 0) {
printf("\n\n The overall miles/gallon was: %f\n", overall/avg);
exit(0);
}
printf("Enter miles driven: ");
scanf("%d", &miles);
mg = miles/gallons;
printf("The miles/gallon for this tank was : %f\n", mg);
overall += miles;
avg += gallons;i--;
}
return 0;
}
`
I want to write a C program to read an array, calculate the sum of all individual entries, the average, the minimum grade, the maximum grade, and print all of those values. Is this an effective method of sorting? I'm attempting to sort the data values by min and max comparing it as they are input. My compiler also throws a declaration error with all of the float values.
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
float main()
int i;
float grades[10];
float grade;
float sum;
float avg;
float count;
float max;
float min;
{
max =0;
min=0;
printf("Enter your grades (Type <0 and >100 to quit): ");
scanf("%f", &grade);
sum=0;
i=0;
while(grades>0 && i<10)
{grades[i]= grade;
i++;
if(i<10)
{printf("Enter grade, (Type <0 or >100 to quit): ");
scanf("%f", &grade); }}
for (i=0; i < 10; i++)
{if (grades[i] > max)
{
max=grades[i];
}
else if (grades[i] < min)
{
min = grades[i];
}}
count=i;
for(i=0; i<count; i++)
{printf("Grade %d is %f \n", i+1, grades[i]);}
grade=0;
for(i=0;i<count; i++)
{sum= sum + grades[i];}
if(count>0)
{avg=sum/count;}
else
{avg=0;}
printf("The average of the %f grades is %f \n",count, avg);
printf("The Minimum Grade is %f",min);
printf("The Maximum Grade is %f", max);
printf("Count is %f ", count);
printf("Sum is %f", sum);
printf("Average is %f", avg);
}
The very refided code for solving your problem is
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#define GRADE_ARRAY_LEN 10
int main()
{
int i = 0;
double grades[GRADE_ARRAY_LEN];
double grade;
double max;
double min;
while(i<GRADE_ARRAY_LEN)
{
printf("Enter grade, (Type <0 or >100 to quit): ");
if(scanf("%lf", &grade) != 1)
{
printf("The value entered could not be converted to double. Please enter another value.\n");
scanf("%s");
continue;
}
if(grade < 0.0 || grade > 100.0)
{
return 1;
}
else
{
if(i == 0)
{
max = grade;
min = grade;
}
else
{
if(grade > max)
{
max = grade;
}
if(grade < min)
{
min = grade;
}
}
grades[i]= grade;
i++;
}
}
double sum = 0;
for(i=0; i<GRADE_ARRAY_LEN; i++)
{
printf("Grade %d is %lg \n", i+1, grades[i]);
sum+=grades[i];
}
double avg = sum/GRADE_ARRAY_LEN;
printf("The average of the %d grades is %g \n", GRADE_ARRAY_LEN, avg);
printf("The Minimum Grade is %lg\n",min);
printf("The Maximum Grade is %lg\n", max);
printf("Number of grades is %d\n", GRADE_ARRAY_LEN);
printf("Sum is %lg\n", sum);
printf("Average is %lg\n", avg);
return 0;
}
I may have missed something, but i checked it and it works.
The - How it works is a bit long.
First of all the amount of grades you want to enter is fixed and defined in #define GRADE_ARRAY_LEN 10 which lets you easily change the number of grades you want to enter.
Then the programm reads input and checks if the input is double or can be converted to double. This check is simple if(scanf("%lf", &grade) != 1). scanf() returns the number of arguments successfully filled, the format "%lf" means that you want your input argument to be filled as double. So scanf("%lf", &grade) will return only return a value which equals to 1, if you entered a value that can be converted to double.
Now if the input IS NOT double or double or can be converted to double the program askes you to enter an input which is double or can be converted to double. scanf("%s"); is actully needed because when scanf("%lf", &grade) fails there is a newline char left in the input stream, which you have to actually read. If you don't, next scanf("%lf", &grade) will actually take it as an input, and fail again, thus creating an infinite loop.
After the input is successfully filled, it means you have your value of grade. The program checks what value was entered, and exits if the value is smaller than 0 or greater than 100. I did this because printf actually outputs, that the program will exit if the value is smaller than 0 or greater than 100.
If the value of grade is between 0 and 100, then the program checks if it is the first value that was scanned with this if(i == 0). Where i is the number of successfully scanned values. If i == 0 than no values were scanned yet, so max and min must be initialized with this value for max and min to work correctly., because all other values have to be checked against the first value. If i != 0, then the value is checked against max an min, and they are modified in case of need.
After min and max are checked the value is FINALLY added to our array of values and the number of successfully scanned values is increased.
i++;grades[i]= grade;
i++;
NOTE!!!: all the operations above are commited in one single loop, while(i<GRADE_ARRAY_LEN). This ensures that you enter the correct amount of values and get the correct max and min values. You do not actually need extra loops to get correct min and max values.
After the loop, the sum of grades is counted. After that, the avg of grades is counted.
NOTE!!!: You do not need any checks here because the loop ensures that you enter correct amount of elemets.
In the end the results are printed to a command line.
I'll try to point out the main parts that i edited.
First: variable declarations must be inside the brakets of main() and main must return an int, which means your code had this:
float main()
int i;
float grades[10];
float grade;
float sum;
float avg;
float count;
float max;
float min;
{
but it must be like this
int main()
{
int i = 0;
double grades[GRADE_ARRAY_LEN];
double grade;
double max;
double min;
Second: Your code did not check if scanf("%lf", &grade) successfully filled grade. That is wrong because you can actually enter any combination of characters and numbers in command line, but the only correct input is when you enter a number, that can be converted to double. That means you have to check what scanf returns.
Third: max = 0; and min = 0; is not the correct way to initialize max and min values. min=0; is incorrect, because in case of only positive grades, grade will never be smaller than min, thus min will be always 0. The correct way is to initialize min value is with the first correctly read grade from input, so if there is a smaller value is entered, then min can be changed accordinly. The max=0; is incorrect because in case of only negative grades, grade will never be greater than max, thus max will be always 0. The correct way is to initialize max value is with the first correctly read grade from input, so if there is a greater value is entered, then max can be changed accordinly.
Third: As i said above, you do not actually need a separate loop to find max and min values. It can be done inside the loop where data is read. It is not really nececcary, but it's a good practice to do everything you can inside one loop.
Fourth: It is a good practice to define lenght of arrays with fixed length before main function using #define. Quote: "The #define creates a macro, which is the association of an identifier or parameterized identifier with a token string. After the macro is defined, the compiler can substitute the token string for each occurrence of the identifier in the source file.". That basically means that you add #define GRADE_ARRAY_LEN 10, as shown in code above, before main, and then instead of using 10 as the number of iterations, and number of array elements like double grades[10]; while(i<10); for(i=0;i<10;i++)
you actually use double grades[GRADE_ARRAY_LEN]; while(i<GRADE_ARRAY_LEN); for(i=0;i<GRADE_ARRAY_LEN;i++). The compiler will automaticly substitute GRADE_ARRAY_LEN for 10; Thsi enables you to change 10 for any other number you want (positive of course) only in one place, instead of changing it in several places;
Fifth: printf("Enter grade, (Type <0 or >100 to quit): ") outputs that if you type a value <0 or >100 the program should exit. Considering the input values were not checked at all, this is not happening.
Sixth: while(grades>0 && i<10) is wrong, because grades is an Array, and you can not compare an array to a single number.
Now on to what i actually did to the code to make it work:
1) Moved the var declarations and changed the return value of main
2) Implemented a check for successfull filling of grade by scanf("%lf", &grade).
3) Implemented a program exit in case if input is <0 or >100;. This means the program will actuallly exit if you enter a number smaller than 0 and greater than 100
4) Implemented a #define GRADE_ARRAY_LEN 10 to use as a length of grade array
5) Re-made the loop so it will ask to enter correct input data GRADE_ARRAY_LEN times. Now the program won't continue unless you enter correct input data exactly GRADE_ARRAY_LEN times.
6) Moved the finding of min and max values to the while loop. As said above, you do not actually need a separate loop to find them. Also modified the initialization of min and max
7) Due to changes above, made some changes in the end.
7.1) Changed a little the way sum is counted
Was:
for(i=0;i<count; i++)
{sum= sum + grades[i];}
Now:
double sum = 0;
for(i=0; i<GRADE_ARRAY_LEN; i++)
{
printf("Grade %d is %lg \n", i+1, grades[i]);
sum+=grades[i];
}
7.2) Removed unnecessary check upon calculating avg
Was:
if(count>0)
{avg=sum/count;}
else
{avg=0;}
Now:
double avg = sum/GRADE_ARRAY_LEN;
8) Changed all float values to double. The amount of bytes float allocates for a var is actually dependant on system architecture, where double is actually an Quote: "IEEE 754 double-precision binary floating-point format: binary64".
9) Due to changes above, changed format of the input data from %f to %lf, Changed format of output data from %f to %lg. Now both can work with double.
Replacing this:
double min;
while(i<GRADE_ARRAY_LEN)
{
.......
printf("The value entered could not be converted to double. Please enter another value.\n");
scanf("%s");
With this:
double min;
char c;
while(i<GRADE_ARRAY_LEN)
{
.......
printf("The value entered could not be converted to double. Please enter another value.\n");
scanf("%s", &c);
Should fix the scanf error. The second error is probably because you forgot to copy the closing braket - "}" of main at the very end. What i mean is that you probably have this at the very end:
printf("Average is %lg\n", avg);
return 0;
But!!! it shold be like this
printf("Average is %lg\n", avg);
return 0;
} // !!!!
I am very much a beginner to programming in C so please help out here. I am trying to write a program that loops asking the user to enter a number, if the number is positive it adds it to the total, and if it is negative it ends the program and displays the average, lowest input, and highest input. Unfortunately no matter what I change with the low and high things I keep getting 'nan' for the low, and whatever the negative number for the high.. please help!
#include<stdio.h>
int main(void)
{
float input;
float total;
float low;
float high;
float average;
int count=0;
printf("\n\nPlease enter a positive number to continue or a negative number");
printf(" to stop: ");
scanf("%f", &input);
while (input > 0)
{
count = count + 1;
printf("\nPlease enter a positive number to continue or a negative");
printf(" number to stop: ");
scanf("%f", &input);
total = total + input;
if ( low < input )
{
( low = input );
}
else
{
( low = low );
}
}
if (input < high)
{
(high = input);
}
else
{
(high = high);
}
average = total / count;
printf("\n\n\nCount=%d",count);
printf("\n\n\nTotal=%f",total);
printf("\nThe average of all values entered is %f\n", average);
printf("\nThe low value entered: %f\n", low);
printf("\nThe highest value entered: %f\n", high);
return 0;
}
After compiling it with gcc and testing it with the numbers 1, 5, 4, then -1 I get the following output
Count=3
Total=8.000000
The average of all values entered is 2.666667
The low value entered: nan
The highest value entered: -1.000000
You have fallen victim to garbage values - a common mistake for beginners. Specifically, its happening in these lines -
float total;
float low;
float high;
float average;
When you write that, the system assigns the variables a memory location. The computer though, is not infinite, so it just uses a memory location that used to be used by something else, but is no longer being used. Most of the time though, the 'something else' doesnt clean up after itself (because it would take a lot of time), so the information that was there is left there, such as fdaba7e23f. This is totally meaningless to us, so we call it a garbage value.
You can fix this by initializing the variables, like so -
float total=0;
float low;
float high;
float average=0;
Note that you will have to add some extra logic for the low variable. Here is one way to do it -
printf("\n\nPlease enter a positive number to continue or a negative number");
printf(" to stop: ");
scanf("%f", &input);
low=input;
high=input;
while (input > 0)
....
....
As you can see, I just copied your code and added two lines after the first scanf.
For one thing, I don't know if you have noticed it, your count and total are all screwed up.
Please change the order of execution, apart from the initialization answer given by #Drgin
int total = input;
while (input > 0)
{
printf("\nPlease enter a positive number to continue or a negative");
printf(" number to stop: ");
scanf("%f", &input);
count = count + 1;
total = total + input;