Having Trouble Counting and Summing Integers from Text File - c

Sorry for being such a novice.
For this question I used C language, and the libraries stdlio.h and stdlib.h.
Question
So a question is asking me to:
Open a text file named 'numbers.txt' in read mode. This text file
has 6 integers in it.
Read the 6 integers from that text file using a loop.
Calculate and display the total and average of those 6 integers.
The text file 'numbers.txt' holds the integers: 5, 10, 15, 20, 25.
Here's my code:
FILE *n;
n = fopen("numbers.txt", "r");
int a, num, sum = 0;
float avg;
for (a = 0; a < 6; a++) {
fscanf(n, "%d", &num);
sum = sum + num;
}
avg = sum / (a - 1);
printf("Sum = %d\nAverage = %.2f\n\n", sum, avg);
fclose(n);
Another variation of the question is that I need to use a while loop to read the integers in the text file.
Here's my code for that:
FILE *n;
n = fopen("numbers.txt", "r");
int a = 0, num, sum = 0;
float avg;
while (fscanf(n, "%d", &num) != EOF) {
fscanf(n, "%d", &num);
sum = sum + num;
a++;
}
avg = sum / a;
printf("Sum = %d\nAverage = %.2f\n\n", sum, avg);
fclose(n);
Problem
When I run each of the above programs, I expect this output:
Sum = 75
Average = 15.00
However I get this instead (for the first code):
Sum = 100
Average 20.00
And this (for the second code):
Sum = 55
Average = 18.00
How am I able to get the correct output from both of these programs?
Again I apologise for how basic this question is. Nonetheless, any help would be appreciated.

In the first one, you tried to read one-to many numbers, but since there were only 5 numbers, the last number was added twice to your sum, so you ended up adding an extra 25 to the sum to get 100.
In the second code, after reading the last number, the end of the file was reached, so your code did not get the opportunity to add the last read number, so you missed adding 25 to your sum.
You were much closer with your first code, just change the for-loop to only iterate 5 times

Here is my observation,
Case 2 : The problem is here in below two line of code
while (fscanf(n, "%d", &num) != EOF) { /* this is fine, scanf() stored read int into num */
fscanf(n, "%d", &num); /* this is not needed as overwrites previous num, just remove it */
/* some code */
}
Also this
avg = sum / a;
doesn't get you expected result as sum/a results in integer but you are assigning it to avg which is float. One way to overcome this is to do typecasting like below
avg = (float)(sum / a);
Sample code :
int main(void) {
FILE *n;
n = fopen("numbers.txt", "r"); /* always do error handling to make more robust code */
if(n == 0) {
#TODO error handling */
}
int a = 0, num, sum = 0;
float avg;
while (fscanf(n,"%d", &num) != EOF) {
//fscanf(n, "%d", &num);// remove this
sum = sum + num;
a++;
}
avg = (float)(sum / a);// typecast it
printf("Sum = %d\nAverage = %.2f\n\n", sum, avg);
fclose(n);
return 0;
}
Case 1 : Here
for (a = 0; a < 6; a++)
rotating loop fixed number of times may not be a problem for now but it creates issue when you don't know in advance how many integer number file having. so better rotate loop until EOF. For e.g
for (a = 0; ; a++) {
if(fscanf(n, "%d", &num) == 1) /* compare with return value */
sum = sum + num;
else
break;
}

Related

How can I average these numbers correctly in C?

I wrote some code that reads numbers from another file and it's supposed to input the numbers from the file and output the average. The numbers I input are (1,2,3,4,5,6,7,8,9,10). But the average it's giving me is 2,4,6,8.10.
How do I correct this?
Code:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *myFile;
myFile = fopen("numbers.txt", "r");
int numberArray[10];
int i;
int sum = 0;
int n = 0;
int avg = 0;
if (myFile == NULL){
printf("Error Reading File\n");
exit (0);
}
for (i = 0; i < 10; i++){
fscanf(myFile, "%d,", &numberArray[i] );
}
for (i = 0; i < 10; i++){
sum += n;
i++;
avg = (sum / i);
printf("Average is: %d\n\n", numberArray[i]);
}
fclose(myFile);
return 0;
}
"...The numbers I input are (1,2,3,4,5,6,7,8,9,10) Instead of the average its giving me 2,4,6,8.10. How do I correct this?..."
Focusing on only the final loop, a few items to consider that will address this issue, and a few others:
Depending on values of numerator and divisor the average might not be exactly correct due to integer division rounding error. if this is an issue for you, the first code snippet addresses it. If not, the following snippets address only the skipping array elements...
As covered, the following code segment in the original post increments i twice, once in the for() loop, then later in the i++ statement. The following addresses each of these, also corrects assignment statements, all with with comments...
float sum = 0.0;//to avoid integer division rounding error, use a floating point type
float ave = 0.0;
for (i = 0; i < 10; i++){
//sum += n;//n does not represent the values strore
sum += (float)numberArray[i];
//i++;//not needed, i is incremented in for loop
avg = (sum/i);
printf("Average is: %f\n\n", ave);
// ^ changed from d to f,
// and numberArray[i] to ave
}
Note, if the effects of integer division are acceptable for your purposes, then use the following:
int sum = 0;
int ave = 0;
for (i = 0; i < 10; i++){
sum += numberArray[i];
avg = (sum/i);
printf("Average is: %d\n\n", ave);
}
And, if outputting only the final result is required (rather than all of the intermediate values), move the last two statements to just after the for loop:
for (i = 0; i < 10; i++){
sum += numberArray[i];
}
avg = (sum/i);
printf("Average is: %d\n\n", ave);
"Is it possible to place the given average back into the file? "
The original statement: myFile = fopen("numbers.txt", "r"); opened the file for read only. But placing the resulting average back into the file requires reopening the file for append and using fputs():
...
fclose(myFile);
//add the following...
char sAve[20] = {0};
myFile = fopen("numbers.txt", "a");
if(myFile)
{
sprintf(sAve, "\nAverage is: %f0.6", ave)
fputs(sAve, myFile);
fclose(myFile);
}
return 0;
}
In this for loop, you increment i twice, once inside the for()-statement, once at i++.
for (i = 0; i < 10; i++){
sum += n;
i++;
avg = (sum/ i);
printf("Average is: %d\n\n", numberArray[i]);
}
If I understand correctly, the second increment should be removed. Also your intended output is not quite clear to me. If this does not solve it, maybe specify your question.
If you just want the average of all the numbers first add them all together:
for(i=0; i<10; i++){
sum+=numberArray[i];
}
Then divide by the number of elements
avg = sum/10;
Then you can printout the average:
printf("Average is: %d\n", avg);
I think this is what your code intends to do.

For loop "<" vs "<=" print format issues in program

I am learning C on my own with a book and I cannot for the life of me figure out how to solve this exercise. I'm obviously looking at it in the wrong way or something. Here is an explanation below.
Listed below are some functions and the main function at the bottom. This program is compiled to generate a certain number of random numbers and determine the min and the max of the random numbers. If you copy and paste this code, you will see how it works. Anyways, an exercise asks me to go to the function "prn_random_numbers()" and change the for loop from "for (i = 1; i < k; ++i)" to for (i = 2; i <= k; ++i). This causes the first line format to print incorrectly. The exercise is to further modify the program in the body of the for loop to get the output to be formatted correctly.
To sum it up, the "prn_random_numbers()" function is written to print out 5 random numbers before moving to the next line. Hence the" i % 5" if statement. Now, for some reason, when you make the slight adjustment to the for loop, as the exercise asks above, it causes the first line to only print 4 numbers before moving to the next line. I have tried a number of things, including trying to force it to print the 5th number, but it only duplicated one of the random numbers. I even tried "i % 4" to see if it would print 4 numbers for each row, but it only prints 3 numbers for the first row instead of 4! So it always prints one less number on the first line than it is supposed to. I have n clue why it is doing that and the book does not give an exercise. Do you have any idea?
Bear with me if you think this is a stupid question. I am just learning on my own and I want to make sure I have a good foundation and understand everything as I learn it, before moving forward. I appreciate any help or advice!
prn_random_numbers(k) /* print k random numbers */
int k;
{
int i, r, smallest, biggest;
r = smallest = biggest = rand();
printf("\n%12d", r);
for (i = 1; i < k; ++i)
{
if (i % 5 == 0)
printf("\n");
r = rand();
smallest = min(r, smallest);
biggest = max(r, biggest);
printf("%12d", r);
}
printf("\n\n%d random numbers printed.\n", k);
printf("Minimum:%12d\nMaximum:%12d\n", smallest, biggest);
}
int main()
{
int n;
printf("Some random numbers are to be printed.\n");
printf("How many would you like to see? ");
scanf("%d", &n);
while (n < 1)
{
printf("ERROR! Please enter a positive integer.\n");
printf("How many would you like to see? ");
scanf("%d", &n);
}
prn_random_numbers(n);
return (EXIT_SUCCESS);
}
the following proposed code:
properly initializes the random number generator
cleanly compiles
properly checks for and handles errors
performs the desired functionality
avoids having to list instructions twice
follows the axiom: Only one statement per line and (at most) one variable declaration per statement.
does not use undefined functions like: max() and min()
and now the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void prn_random_numbers(int k)
{
int count = 1;
int r;
int smallest;
int biggest;
r = smallest = biggest = rand();
printf("\n%12d", r);
for ( int i = 2; i <= k; i++, count++)
{
if (count % 5 == 0)
{
count = 0;
printf("\n");
}
r = rand();
smallest = (r < smallest)? r : smallest;
biggest = (r > biggest)? r : biggest;
printf("%12d", r);
}
printf("\n\n%d random numbers printed.\n", k);
printf("Minimum:%12d\nMaximum:%12d\n", smallest, biggest);
}
int main( void )
{
int n;
srand( (unsigned)time( NULL ) );
do
{
printf("Please enter a positive integer, greater than 0.\n");
printf("How many would you like to see? ");
if( scanf("%d", &n) != 1 )
{
fprintf( stderr, "scanf for number of random numbers failed\n" );
exit( EXIT_FAILURE );
}
} while( n < 1 );
prn_random_numbers(n);
// in modern C, if the returned value from `main()` is 0 then no `return 0;` statement needed
}
a typical run, no input problems is:
Please enter a positive integer, greater than 0.
How many would you like to see? 20
98697066 2110217332 1247184349 421403769 1643589269
1440322693 985220171 1915371488 1920726601 1637143133
2070012356 541419813 1708523311 1237437366 1058236022
926434075 1422865093 2113527574 626328197 1618571881
20 random numbers printed.
Minimum: 98697066
Maximum: 2113527574
Try to use a debugger to solve your problem, it's easy to use and really helpfull :)
SOLUTION:
Your i variable don't count the number of numbers because it is initialize at 1 (in the for statement), so you need to declare a new variable to count properly.
If you have still a problem:
void prn_random_numbers(int k)
{
int count = 1;
int i, r, smallest, biggest;
r = smallest = biggest = rand();
printf("\n%12d", r);
for (i = 2; i <= k; i++, count++) {
if (count % 5 == 0) {
count = 0;
printf("\n");
}
r = rand();
smallest = min(r, smallest);
biggest = max(r, biggest);
printf("%12d", r);
}
printf("\n\n%d random numbers printed.\n", k);
printf("Minimum:%12d\nMaximum:%12d\n", smallest, biggest);
}

Calculating the average of user inputs in c

disclaimer: I'm new to programming
I'm working on this problem
so far ive written this which takes user inputs and calculates an average based on them
#include <stdio.h>
int main()
{
int n, i;
float num[100], sum = 0.0, average;
for(i = 0; i < n; ++i)
{
printf("%d. Enter number: ", i+1);
scanf("%f", &num[i]);
sum += num[i];
}
average = sum / n;
printf("Average = %.2f", average);
return 0;
}
I'd like the user to enter -1 to indicate that they are done entering data; I can't figure out how to do that. so if possible can someone explain or give me an idea as to how to do it
Thank you!
#include <stdio.h>
int main()
{
int i = 0;
float num[100], sum = 0.0, average;
float x = 0.0;
while(1) {
printf("%d. Enter number: ", i+1);
scanf("%f", &x);
if(x == -1)
break;
num[i] = x;
sum += num[i];
i++;
}
average = sum / i;
printf("\n Average = %.2f", average);
return 0;
}
There is no need for the array num[] if you don't want the data to be used later.
Hope this will help.!!
You just need the average. No need to store all the entered numbers for that.
You just need the number inputs before the -1 stored in a variable, say count which is incremented upon each iteration of the loop and a variable like sum to hold the sum of all numbers entered so far.
In your program, you have not initialised n before using it. n has only garbage whose value in indeterminate.
You don't even need the average variable for that. You can just print out sum/count while printing the average.
Do
int count=0;
float num, sum = 0;
while(scanf("%f", &num)==1 && num!=-1)
{
count++;
sum += num;
}
to stop reading at -1.
There is no need to declare an array to store entered numbers. All you need is to check whether next entered number is equal to -1 and if not then to add it to the sum.
Pay attention to that according to the assignment the user has to enter integer numbers. The average can be calculated as an integer number or as a float number.
The program can look the following way
#include <stdio.h>
int main( void )
{
unsigned int n = 0;
unsigned long long int sum = 0;
printf("Enter a sequence of positive numbers (-1 - exit): ");
for (unsigned int num; scanf("%u", &num) == 1 && num != -1; )
{
++n;
sum += num;
}
if (n)
{
printf("\nAverage = %llu\n", sum / n);
}
else
{
puts("You did not eneter a number. Try next time.");
}
return 0;
}
The program output might look like
Enter a sequence of positive numbers (-1 - exit): 1 2 3 4 5 6 7 8 9 10 -1
Average = 5
If you need to calculate the average as a float number then just declare the variable sum as having the type double and use the corresponding format specifier in the printf statement to output the average.

Addition of Float Values is incorrect

Requirements for this task are as follows:
Read floating point values from stdin, each separated by a newline, and terminated by EOF.
The input values are in the range [-100,000 to +100,000].
The input will contain at least one floating-point value.
The input may contain blank lines: these should be ignored.
Apart from possible blank lines, the input is otherwise well-formed.
At EOF, output:
the smallest value seen
the largest value seen
the arithmetic mean of all the values seen
all accurate to two decimal places.
The output values must be separated by a single space character and followed by a newline character.
Examples:
Input:
7
5.6
6
Output:
5.60 7.00 6.20
Input:
11
Output:
11.00 11.00 11.00
In my code when I input 7, 5.6, and 6, my output is 5.60 7.00 5.77.
I know where the issue is but not sure how to fix it. My total variable says its value at EOF is 17.322826 which is definitely not correct.
#include <stdio.h>
int main() {
int i = 0;
float big = 0;
float small = 1000000;
float total;
float div = 0;
while (i == 0) {
float a = 0;
float flag = scanf("%f", &a);
if (flag == EOF) {
printf("%.2f %.2f %.2f %f %f\n", small, big, total / div, total, div);
break;
}
if (a > big) {
big = a;
}
if (a < small) {
small = a;
}
div++;
total = total + a;
}
return 0;
}
You forgot to initialize total to 0.
Further notes:
the classic C idiom for an infinite loop is for (;;) { ... }.
flag should be defined as an int
you should stop the loop when flag != 1 instead of just flag == EOF. An invalid input will cause the program to loop endlessly. You can actually drop this variable completely.
initializing big to 0 and small to 1000000 is incorrect: what if all values are negative? what if they are all very large?
Here is a corrected version:
#include <stdio.h>
int main(void) {
float a, big, small, total;
int div;
if (scanf("%f", &a) != 1)
return 1;
big = small = total = a;
div = 1;
while (scanf("%f", &a) == 1) {
if (big < a) {
big = a;
}
if (small > a) {
small = a;
}
div++;
total += a;
}
printf("%.2f %.2f %.2f\n", small, big, total / div);
return 0;
}

Organizing file output problems

I am working on a program to organize a list of numbers from a file and output these numbers in a easier to read format. Such as a file called Counting.txt containing the numbers:
11
1 1 2 3 4 4 4 4 5 5 7
and I want it to output:
1x2 2x1 3x1 4x4 5x2 7x1
The formula for output being vXc, where v is the number and c is the number of times it occurs. But my current program only outputs it as:
1x1 2x1 3x1 4x1 4x1 4x1 4x1 5x1 5x1 7x1
I believe there is a small error in my for loop that doesn't allow me to change my c variable, or the number indicating how many times the actual number occurs. Can anyone help?
My code:
#include <stdio.h>
int main () {
FILE* file = fopen("counting.txt", "r");
int total_num, count = 1, num, num2, i;
if (file == NULL) {
printf("Did not find counting.txt file.\n");
}
fscanf(file, "%d", &total_num);
fscanf(file, "%d", &num);
for (i = 1; i < total_num; i++) {
fscanf(file, "%d", &num);
if (num2 == num) {
count = count + 1;
} else {
printf("%dX%d ", num, count);
count = 1;
}
}
return 0;
}
In the loop you read into num instead of num2. So in general num2 is undefined. You also need at the end of each loop's iteration to assign to num the value of num2.
Also when you print the number of repetitions you should refer to the old value and not the current one, since you don't know if the current number will be followed by other equal numbers.
So you could change your loop to:
for (i=1; i< total_num; i++) {
fscanf(file, "%d", &num2);
if (num2 == num) {
count = count + 1;
}
else {
printf("%dX%d ", num, count);
count = 1;
}
num = num2;
}
printf("%dX%d ", num, count);

Resources