Logic error when averaging several different numbers and outputting the result - c

I'm just beginning C, and I am encountering a logic error when trying to output the average of numbers entered. I will provide the source code of the program below.
// integer_sequence_avg.c
// Inputs a sequence of integers then averages them and outputs the result after the sentinel value "9999" is entered.
#include <stdio.h>
int main(void) {
// initializaiton
int addend = 0;
int sum = 0;
int average;
unsigned int counter;
for (addend; addend != 9999; ++counter) {
printf("%s", "Enter an integer to be averaged. Enter \"9999\" when you want to receive the average: "); // prompt to enter integers to be averaged
scanf("%d", &addend); // scans input into variable to be added to sum
if (addend != 9999) {
sum += addend; // Adds addend to sum
}
}
if (counter != 0) {
average = sum / counter; // Calculates average
printf("\nThe average of the integers added was %d\n\n", average); // Outputs average of numbers entered
} else {
printf("\nNo integers were entered.\n\n"); // Outputs that no integers were entered
}
system("pause");
return 0;
}
logic error screenshot
https://i.stack.imgur.com/Fwwaa.png

counter is incremented without being initialized. This invoked undefined behavior.
counter is incremented even when addend != 9999 is false.
Return values of scanf() should be checked to see if it successfully read things.
Instead of this
unsigned int counter;
for (addend; addend != 9999; ++counter) {
printf("%s", "Enter an integer to be averaged. Enter \"9999\" when you want to receive the average: "); // prompt to enter integers to be averaged
scanf("%d", &addend); // scans input into variable to be added to sum
if (addend != 9999) {
sum += addend; // Adds addend to sum
}
}
Try this:
unsigned int counter = 0;
while ( addend != 9999 ) {
printf("%s", "Enter an integer to be averaged. Enter \"9999\" when you want to receive the average: "); // prompt to enter integers to be averaged
if (scanf("%d", &addend) != 1) break; // scans input into variable to be added to sum
if (addend != 9999) {
sum += addend; // Adds addend to sum
++counter;
}
}

The problem is here:
for (addend; addend != 9999; ++counter) {
where counter is not initialized before using.
The fix: unsigned int counter = 0;
The only thing to address beyond that is that the counter value is being incremented once beyond what it should, giving wrong results.
eg, for these inputs:
4+6+8+9
Average should be 27/4 == 6, but counter == 5 after only 4 entries,
Average is computed as 27/5 == 5
To address this
change average = sum / counter;
to average = sum / (counter - 1);
Beyond that, integer division results in rounding, so unless the numerator contains all of the prime factors of the denominator, the result will invoke integer rounding. If that is a concern, floating point variables should be considered.

Related

Sum and average for n numbers with -1 as exit integer

Hello I have a small problem with my code and I want to understand it. My task is to write a program that take the sum and average for n numbers with while loops or nested while loops with if conditions, when you want to exit the code you should enter -1. The code is down below. The problem I have is that I can't get it to exclude the -1 from the calculation. What am I doing wrong. And it is suppose to be a simple code.
int main(void) {
int count;
float sum, average, number;
sum = 0;
count = 0;
printf("Calculate sum and average (-1 to quit)\n");
while (number!=-1) {
scanf("%f", &number);
sum = sum + number;
count = count + 1;
}
average = sum / count;
printf("Sum=%f", sum);
printf(" Average=%f", average);
}
in the while block, you read the number and then add it to your average calculation, and only then after the iteration repeats you're checking if it's different than -1 to stop the iteration:
there are obviously different ways to solve it:
one way can be to use while(true) and in the while block after you read the number add an if statement to compare it with -1 and break out of the loop
while (true) {
scanf("%f", &number);
if (number == -1) break;
sum = sum + number;
count = count + 1;
}
Reordering the different steps could solve this:
int main(void) {
int count;
float sum, average, number=0.0f;
sum = 0;
count = -1;
printf("Calculate sum and average (-1 to quit)\n");
while (number!=-1) {
sum = sum + number; // first time no effect with 0
count = count + 1; // first time "no effect" counting to 0
scanf("%f", &number); // will not be counted or summed if -1
}
average = sum / count;
printf("Sum=%f", sum);
printf(" Average=%f", average);
}
Think it through with immediatly entered -1:
sum is 0+0, suitable for no numbers being added up
count is -1+1==0, suitable for no numbers
dividing by 0 should be avoided, but that is a separate issue
Think it through with one number:
number is read in with sum==0 and count==0
is not -1, so loop iterates again
sum and count are updated meaningfully
-1 one is entered
loop ends without processing -1
By the way, comparing a float for identity is risky. You would be safer if you could compare more "generously", e.g. while (number>-0.5).
I think you should take the input at the last of the loop as it will get check in the next iteration. And when -1 comes up it will not be added.
#include <stdio.h>
int main(){
int count=0;
float sum=0, average=0, number=0;
printf("Calculate sum and average (-1 to quit)\n");
while(number!=-1){
sum = sum + number;
count = count + 1;
scanf("%f", &number);
}
average = sum / count;
printf("Sum=%f", sum);
printf(" Average=%f", average);
}
Code needs to test number as -1 before including it in the summation. OP's code test almost does this right. OP's code test for -1 before number is even assigned leading to undefined behavior (UB).
float number;
while (number!=-1) { // UB!
Also good to test the return code of scanf() for success.
while (scanf("%f", &number) == 1 && number != -1) {
sum = sum + number;
count = count + 1;
}

Calculating average of pair numbers

Hello I have been working on a program in C that calculates numbers and it gives me back an average. Now I'm having issues implementing code that will ask a user to enter any number of pairs and calculate the average. Below is the code that I been working on. I'm able to change the while (count < 5)to 10 to get more pairs, but my goal is to ask a user to input any PAIR and THEN calculate the average (re iterating).
#include <stdio.h>
int main () {
int count;
double avg, value, weight, sum, sumw;
count = 0;
sum = 0;
sumw = 0;
avg = 0.0;
while (count < 5) {
printf("Enter value and it's weight:");
scanf("%lf %lf", &value, &weight);
if (weight >= 0) {
sumw = sumw + weight;
sum = sum + value * weight;
count = count + 1;
}
else { printf("weight must be positive\n");
}
}
avg = sum / sumw;
printf("average is %lf\n " , avg );
return 0;
}
**Second part ** On this on I'm not too sure how to make it to PAIRS plus calculate avg. ej: 2 1 , 2 4 , 4 4 etc.
#include<stdio.h>
void main()
{
int i,n,Sum=0,numbers;
float Average;
printf("\nPlease Enter How many pairs do you want?\n");
scanf("%d",&n);
printf("\nPlease Enter the elements one by one\n");
for(i=0;i<n;++i)
{
scanf("%d",&numbers);
Sum = Sum +numbers;
}
Average = Sum/n;
printf("\nAverage of the %d Numbers = %.2f",n, Average);
return 0;
}
but my goal is to ask a user to input any PAIR and THEN calculate the
Well, then you need to store the values somewhere. Recommendation: Have a struct for:
typedef struct
{
double value;
double weight;
} Pair;
Then as soon as you have got number of pairs to read from user, create an array of pairs:
Pair* pairs = malloc(number * sizeof(*pairs));
Very important: Every malloc should go with a free to avoid memory leaks. General recommendation: plan the free immediately when or even before mallocing.
Now inside your loop, you can fill the pairs:
scanf("%lf %lf", &pairs[i].value, &pairs[weight].weight);
Analogously, you can then use the pairs in the array in next loop or for whatever other purpose.
Side note:
if (weight >= 0)
{
// ...
}
else
{
// printf("weight must be positive\n");
}
If user gave negative input, you'll be just skipping some values (or or as in loop proposed, still retain the negative values!).
You might instead read inside a nested loop until value is valid. Additionally consider user providing non-numeric input, too! In that case, you couldn't read a double at all. So general rule is: Always check the result of scanf:
if(scanf("%lf %lf", &value, &weight) != 2 || value < 0 || weight < 0)
// ^
// assuming negative value not desired either
{
// user input was invalid!!!
}

Why are my values for sum and count being lost each loop?

I'm getting a consistent divide by zero error, even though each loop should be populating the variables. Code below:
#include <stdio.h>
void calculateAverage()
{
int grade, count, sum;
double average;
sum = 0;
count = 0;
grade = 0;
average = 0.0;
int coolvalue = 0;
while (coolvalue==0)
{
scanf("%d", &grade);
if (grade == -1)
{
sum, sizeof(double);
count, sizeof(double);
average = (sum / count);
printf("%lf", &average);
break;
}
else
{
if ((grade > 100) || (grade < -1))
{
printf("Error, incorrect input.\n");
break;
}
else
{
sum = +grade;
count = count + 1;
return count;
return sum;
}
}
}
coolvalue = 1;
}
int main(void)
{
while (1)
calculateAverage();
while (1) getchar();
return 0;
}
Even while using return, I'm not able to properly increment the value of sum or count.
There are multiple issues in your code.
scanf("%d", &grade); - you don't check the value returned by scanf(). It returns the number of values successfully read. If you enter a string of letters instead of a number, scanf("%d") returns 0 and it does not change the value of grade. Because of this the code will execute the rest of the loop using the previous value of grade. You should restart the loop if the value returned by scanf() is not 1:
if (scanf("%d", &grade) != 1) {
continue;
}
Assuming you enter 10 for grade this block of code executes:
sum = +grade;
count = count + 1;
return count;
return sum;
sum = +grade is the same as sum = grade. The + sign in front of grade doesn't have any effect. It is just the same as 0 + grade.
You want to add the value of grade to sum and it should be sum += grade. This is a shortcut of sum = sum + grade.
return count makes the function complete and return the value of count (which is 1 at this point) to the caller. The caller is the function main() but it doesn't use the return value in any way. Even more, your function is declared as returning void (i.e. nothing) and this renders return count incorrect (and the compiler should warn you about this).
return sum is never executed (the compiler should warn you about it being dead code) because the function completes and the execution is passed back to the caller because of the return count statement above it.
Remove both return statements. They must not stay here.
If you enter -1 for grade, this block of code is executed:
sum, sizeof(double);
count, sizeof(double);
average = (sum / count);
printf("%lf", &average);
break;
sum, sizeof(double) is an expression that does not have any effect; it takes the value of sum then discards it then takes the value of sizeof(double) (which is a constant) and discards it too. The compiler does not even generate code for it.
the same as above for count, sizeof(double);
average = (sum / count);:
the parenthesis are useless;
because both sum and count are integers, sum / count is also an integer (the integral result of sum / count, the remainder is ignored).
you declared average as double; to get a double result you have to cast one of the values to double on the division: average = (double)sum / count;
if you enter -1 as the first value when the program starts, count is 0 when this code is executed and the division fails (division by zero).
printf("%lf", &average); - you want to print the value of average but you print its address in memory. Remove the & operator; it is required by scanf() (to know where to put the read values). It is not required by printf(); the compiler generates code that passes to printf() the values to print.
break; - it passes the execution control after the innermost switch or loop statement (do, while or for). It is correct here and makes the variable coolvalue useless. You can simply remove coolvalue and use while (1) instead.
All in all, your function should look like:
void calculateAverage()
{
int sum = 0;
int count = 0;
int grade = 0;
double average = 0.0;
while (1) {
if (scanf("%d", &grade) != 1) {
// Invalid value (not a number); ignore it
continue;
}
// A value of -1 signals the end of the input
if (grade == -1) {
if (count > 0) {
// Show the average
average = (double)sum / count;
printf("Average: %lf\n", average);
} else {
// Cannot compute the average
puts("You didn't enter any value. Cannot compute the average.\n");
}
// End function
return;
}
if ((grade < -1) || (100 < grade)) {
puts("Error, incorrect input.\n");
// Invalid input, ignore it
continue;
}
sum += grade;
count ++;
}
}
Quite a few corrections need to be made.
The while loop in the calculateAverage() function. That's an infinite loop buddy, because you are not changing the value of that coolValue variable anywhere inside, instead you make it 1 only when it exits the loops, which it never will.
So, use while(1) {...}, and inside it, check for the stopping condition, i.e, if (grade == -1) { ... } and inside it calculate and print the average and return. This will automatically break the while.
You're not checking if the input grade is actually a valid integer or not. Check the value of scanf for that, i.e, use if (scanf("%d", &grade) != 1) { ... }
The expression sum = +grade; is just another way of writing sum = 0+grade which in turn is nothing but sum = grade. Replace this with sum += grade;. This is the right way to write a shorthand for addition.
Two return statements..a very wrong idea. First of all, a function can have just one return(in an obvious way I mean, at once). Secondly, the function calculateAverage() is of return-type void. there's no way how you can return double value from it. So remove these two statements.
I have attached the code below which works. Also do go through the output which I have attached.
CODE:
#include <stdio.h>
void calculateAverage()
{
int grade, count = 0, sum = 0;
double average;
printf("\nenter the grades... enter -1 to terminate the entries\n.");
while (1) {
printf("\nEnter the grade: ");
if (scanf("%d", &grade) != 1) {
printf("\nInvalid characters entered!!!");
continue;
}
else if(((grade > 100) || (grade < -1))) {
printf("\nInvalid grade entered!!!");
continue;
}
else {
if (grade == -1) {
average = sum/count;
printf("\nAverage value of grades: %.3lf",average);
return;
}
else {
sum += grade;
count++;
}
}
}
}
int main(void)
{
calculateAverage();
return 0;
}
OUTPUT:
enter the grades... enter -1 to terminate the entries.
Enter the grade: 50
Enter the grade: 100
Enter the grade: 60
Enter the grade: -1
Average value of grades: 70.000
Perhaps it is better for the function to be of type double instead of void. Although it is not my favorite solution it is close to what you want.
#include <stdio.h>
double calculateAverage(void)
{
double average;
int sum = 0, count=0, grade;
while (1)
{
scanf("%d", &grade);
if ((grade > 100) || (grade < -1))
printf("Error, incorrect input.\n");
else if (grade != -1)
{sum = sum+ grade; count = count + 1;}
else
break;
}
if (count==0)
average=-1.0; //none valid input. Notify the main()
else
average=(double)sum/count;
return average;
}
int main(void)
{
double result;
result= calculateAverage();
if (result!=-1.0)
printf("\n average= %lf",result);
else
printf("No grades to calculate average");
getchar();
return 0;
}

Having Trouble Calculating The Correct Average of 10 Integer Values in C

Hello Stack Community!
I am having trouble calculating the correct average for 10 integers.
The expected output average is supposed to be 140.0 with one integer value recognized as not a positive program by the compiler.
This is what I have compiled, and it recognized the negative integer but the average still comes to 150.0
Just trying to figure out what I am missing here.
Thanks!
#include <stdio.h>
int main ()
{
/* variable definition: */
int count, value, sum;
double avg;
/* Initialize */
count = 0;
sum = 0;
avg = 0.0;
// Loop through to input values
while (count < 10)
{
printf("Enter a positive Integer\n");
scanf("%d", &value);
if (value >= 0) {
sum = sum + value;
count = count + 1;
}
else {
printf("Value must be positive\n");
}
}
// Calculate avg. Need to type cast since two integers will yield an integer
avg = (double) sum/count;
printf("average is %lf\n " , avg );
return 0;
}
Values are: 100 100 100 100 -100 100 200 200 200 200
You want to read exactly 10 positive numbers, with count from 0 to 9.
After reading 100 100 100 100 -100 100 200 200 200 200 the value of count is 9 (because -100 neither added to the sum nor counted), which is less that 10 so the loop is executed one more time.
This time scanf() fails, so value remains unchanged; effectively you are reading another 200.
This is why the sum of the numbers is 1500 and the average 150.
AlexP found the explanation: you must check the return value of scanf(), otherwise, you will silently accept input that is not a number and reuse the last converted value.
Also note that the cast in avg = (double) sum/count; applies to sum and binds stronger than /. It is considered good style to make this more explicit by writing avg = (double)sum / count;
Here is a modified version of your program:
#include <stdio.h>
int main(void) {
/* variable definitions */
int count, value, sum;
double avg;
/* Initializations */
count = 0;
sum = 0;
avg = 0.0;
// Loop through to input values
while (count < 10) {
printf("Enter a positive Integer\n");
if (scanf("%d", &value) != 1) {
break;
}
if (value >= 0) {
sum = sum + value;
count = count + 1;
} else {
printf("Value must be positive\n");
}
}
// Calculate avg.
// Need to type cast to force floating point division instead of integer division
if (count > 0) {
avg = (double)sum / count;
printf("average is %f\n", avg);
}
return 0;
}
If I understand your problem correctly, this is what you want to do :
int last_known_positive_value = 0;
// Loop through to input values
while (count < 10)
{
printf("Enter a positive Integer\n");
scanf("%d", &value);
if (value >= 0) {
sum = sum + value;
last_known_positive_value = value;
}
else {
printf("Value must be positive\n");
sum = sum + last_known_positive_value;
}
count = count + 1;
}
check-answer-here
There are a number of different ways to approach the problem. (1) you can read your values as a string with fgets and then call sscanf and gain the benefit of a NULL return from fgets indicating EOF and a test of the buffer containing only '\n' to indicate a user pressed [Enter] to signal end of input.
(2) you can read the values numerically with scanf and then check for EOF to indicate end of input, or some other predetermined sentinel.
Regardless of which you choose, the approach is basically the same. (a) make a call to the function you are using for input, (b) check the RETURN, and (c) validate the value input is within the required range, and handle the data.
You get the drift, on all input, check the return of your read function and handle any error or EOF condition, then validate the input is within the expected range.
A quick example using your code and reading numeric values with scanf could be something like:
#include <stdio.h>
int main (void) {
/* define/initialize variables */
int count = 0, value = 0, sum = 0;
double avg = 0.0;
while (1) { /* infinite loop to process input */
int rtn;
printf ("Enter a positive Integer ([ctrl+d] to quit): ");
if ((rtn = scanf ("%d", &value)) != 1) {
if (rtn == EOF) { /* always handle user cancellation of input */
putchar ('\n'); /* tidy up with POSIX line ending */
break; /* on to final calculation */
}
}
if (value < 0) /* check out of range */{
printf ("Value must be positive\n");
continue; /* try again */
}
sum = sum + value; /* compute sum */
count = count + 1; /* increment count */
}
/* Calculate avg. (typecast to avoid integer division) */
avg = count > 0 ? (double) sum/count : 0; /* protect div by zero */
printf ("\n (%d/%d) => average: %lf\n", sum, count, avg);
return 0;
}
Example Use/Output
$ ./bin/sumavg < <(echo "100 100 100 100 -100 100 200 200 200 200")
Enter a positive Integer ([ctrl+d] to quit):
<snip>
(1300/9) => average: 144.444444
One common thread running between all complete examples is to always handle a manual EOF generated by the user allowing them to cancel an individual input, or input as a whole (you decide based on your needs). On Linux the manual EOF is generated by [ctrl+d] on windoze [ctrl+z].
Look all answers over and let me know if you have any questions related to the above.
while (count < 10) {
printf("Enter a positive Integer\n");
scanf("%d", &value);
if (value >= 0) {
sum += value;
count++;
}
else {
printf("Value must be positive\n");
count++;
}
}
This will increment "count" even if negative integer is inputted.
Thus you will get the desired average.

Program to compute the average of values: if to test chars

Please, take a look at a program that prompts the user to enter 3 values and computes the average of these values.
I decided to add a test condition that checks if the user has entered a number or a character.
// a program that calculates the average of an array of 3 floating-point values; with for loop
#include <stdio.h>
int main (void)
{
float values[3];
float element;
float sum = 0;
int i;
printf ("Please, enter 3 floating values: \n");
for ( i = 0; i < 3; i++)
{
if (scanf ("%f", &element) == 1)
{
if ( (element >= 'a' && element <= 'z') || (element >= 'A' && element <= 'Z') )
printf ("Sorry, you have entered letters\n");
else if (element <= 0)
printf ("Please, enter positive values\n");
else
values[i] = element;
sum += values[i];
}
}
printf ("The average of 3 values is %.2f\n", sum / 3);
return 0;
}
When I run the program, I get the following problems:
1) it seem to work with positive numbers;
2) when I try to enter negative numbers, the program does print the required statement, but the result is still incremented into i, hence lowering the number of further entries; also, even if the number is negative, the program still comes up with some average nonsense value.
Please, enter 3 floating values:
-75
Please, enter positive values
98
Sorry, you have entered letters
-786.9
Please, enter positive values
The average of 3 values is 2087205705198174400484999168
3) when I test the program with letters, it still returns some average, though a zero one:
Please, enter 3 floating values:
jklj
The average of 3 values is 0.00
I would be grateful for your help!
Your element will never contain letters, since you've declared it as float and scanned it as float. If you wish to know if you were given a letters, you should read a string, test it, and only then convert it to float (comparing element to 'a' is actually comapring it to the ASCII code of 'a' = 97).
About the wrong sum - you forgot the curly braces for your else block. Change it to:
else {
values[i] = element;
sum += values[i];
}
If you want your program to end if negative numbers are entered you can use the return statement or deincrement the value of i for more cases. As for letter it never enters the if block so you can use an else. Try the following:
#include <stdio.h>
int main (void)
{
float values[3];
float element;
float sum = 0;
int i;
printf ("Please, enter 3 floating values: \n");
for ( i = 0; i < 3; i++)
{
if (scanf ("%f", &element) == 1)
{
if (element <= 0)
{
printf ("Please, enter positive values\n");
i--; // or use the return statement
}
else
{
values[i] = element;
sum += values[i];
}
}
else
{
printf("You entered special characters");
return;
}
}
printf ("The average of 3 values is %.2f\n", sum / 3);
return 0;
}

Resources