0

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;
}
lnogueir
  • 1,859
  • 2
  • 10
  • 21
  • 2
    Please [format your code in a readable manner](https://stackoverflow.com/help/formatting). – Marco Bonelli Mar 05 '21 at 16:42
  • Hi Marco, sorry about that. –  Mar 05 '21 at 16:45
  • An array in not necessary. Unless you want to use the input numbers later, you can accumulate the total sum in a variable. Once accumulating all the numbers, you can divide that variable by the amount of numbers you read. – Zois Tasoulas Mar 05 '21 at 16:45
  • Hi zois, I wanted to put the average answer into the file again.. thats why I used an array. What part do I need to edit? I just cant figure this out. –  Mar 05 '21 at 16:47
  • Here `sum += n;`, you have to sum the array elements, not add `n` 10 times. Moreover, you have to close your loop after it. – Damien Mar 05 '21 at 16:47
  • Can you show what your input file look like? Also, depending on values of numerator and divisor the average might not be exactly correct due to integer division rounding error. Is that okay? – ryyker Mar 05 '21 at 17:01
  • _" I wanted to put the average answer into the file again."_... The average can be placed back into the file by re-opening the file in _append_ mode, putting the `ave` value into a string buffer, then used `fputs()` to write into the file. An example of that is in answer below. – ryyker Mar 05 '21 at 18:17
  • Welcome to Stack Overflow! Please don't make more work for other people by vandalizing your posts. By posting on the Stack Exchange network, you've granted a non-revocable right, under the [CC BY-SA 4.0 license](//creativecommons.org/licenses/by-sa/4.0/), for Stack Exchange to distribute that content (i.e. regardless of your future choices). By Stack Exchange policy, the non-vandalized version of the post is the one which is distributed. Thus, any vandalism will be reverted. If you want to know more about deleting a post please see: [How does deleting work?](//meta.stackexchange.com/q/5221) – Sabito stands with Ukraine Mar 05 '21 at 18:23
  • Numerical instability probably isn't an issue with nice numbers like that, but related: [Welford's on-line algorithm](https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford%27s_online_algorithm). – Neil Mar 05 '21 at 19:14

2 Answers2

1

"...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;
}
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • Curious, why `float` vs `double`? – chux - Reinstate Monica Mar 05 '21 at 20:52
  • @chux-ReinstateMonica - no reason. Just needed a non-`int` type to avoid rounding error to support my point. ...But I am guessing you have a reason why double might be an advantage? :) – ryyker Mar 05 '21 at 21:05
  • 1
    Thanks for your insight - that's really what I wanted. I see benefits with `double` as it is more of the default FP type for C given constants are default `double`, `sprintf(sAve, "\nAverage is: %f0.6", ave)` usually promotes `ave` to `double`, and the usual precision and range issues. – chux - Reinstate Monica Mar 05 '21 at 21:09
  • @chux-ReinstateMonica - I guessed that would be the gist of it. Curious, are you aware of a time that you would favor `float` over `double` in C? (other than tight memory constraints in eg an embedded scenario.) – ryyker Mar 05 '21 at 21:14
  • 1
    `float` advantages include half the space with large FP data sets, significantly faster throughput with implementations lacking FP hardware, _sounds_ like the default type and saves typing 1 character. Other downsides include more implicit conversion issues, base standard lib functions name are `double`, with `uint128_t` becoming more common, overflow to infinity possible converting to `float`. Hmmm, ... – chux - Reinstate Monica Mar 05 '21 at 21:39
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.

  • Thanks Markus, That listed the numbers in the file instead of averaging them together. I'm trying to average the numbers in the file and get an answer. –  Mar 05 '21 at 16:51
  • Maybe try averaging the example on paper. On paper you would first add all the numbers together to a total, and then divide the total sum by the number of elements. So try doing the same in your code: remove the **avg = sum/i** inside your loop, as well as the printf. – Markus Schmidt Mar 05 '21 at 16:53
  • Thank you very much for the explanation. Is it possible to place the given average back into the file? –  Mar 05 '21 at 17:06
  • It seems to me, like youre on a Mac-System, so it works a little different, but it should be something using fprintf, maybe check out: https://www.tutorialspoint.com/c_standard_library/c_function_fprintf.htm – Markus Schmidt Mar 05 '21 at 17:11
  • If i would take a guess: **fprintf(myFile, "\nThe Average is:%d", avg);** – Markus Schmidt Mar 05 '21 at 17:12
  • @JoLame Whereabouts in the file do you want to write back the average? Look at the different modes for `fopen` and choose the one you think is most appropriate. That would probably be either `"r+"` or `"a+"`. For `"r+"`, writes will be at the current position in the file. For `"a+"`, writes will always be at the end of the file. – Ian Abbott Mar 05 '21 at 17:15