简体   繁体   中英

Code in C to find largest and smallest numbers from text file

I am attempting to write a program that takes a user's inputted text file and returns the largest number, smallest number, average of the numbers and the standard deviation of the numbers. The text file that we input is formatted as such (with the first number being "N", or the total number of numbers, and the second row the list of all the numbers):

5

4.34 23.4 18.92 -78.3 17.9

So far, this is my code

int main(int argc, char*argv[])
{
    double average, num = 0, min = 0, max = 0, sum = 0, N, std_dev, sum_sqs;
    FILE * pFile;
    pFile = fopen("argv[1]", "r");
    fscanf(pFile, "%lf", &N);

    while(!feof(pFile))
    {
            fscanf(pFile, "%d", &num);
            if (num < min)
                    min = num;
            if (num > max)
                    max = num;
            sum += num;
            sum_sqs += (num*num);
    }
    average = sum/N;
    std_dev = sqrt((sum_sqs/N)-(average*average));

    printf("Smallest: %.2lf\n", min);
    printf("Largest: %.2lf\n", max);
    printf("Average: %.2lf\n)", average);
    printf("Standard deviation: %.3lf\n", std_dev);
return(0);
}

Currently, the compiler does not let me get past an error about an undefined reference to sqrt and i cannot figure out what's wrong. Thank you in advance to everybody who takes the time to respond! I really appreciate any help, I am still getting the hang of C. If my code is not doing what I intend it to do please dont hesitate to correct me!

Updated the messy part to below. Still not sure what exactly im doing with the rest though haha pFile = fopen(argv[1], "r"); fscanf(pFile, "%lf", &N);

    if (fscanf(pFile, "%lf", &N) == 1)
    {
            for (int i = 0; i < N; i++)
            {
            if (fscanf(pFile, "%lf", &num) == 1)
                    if (num < min)
                            min = num;
                    if (num > max)
                            max = num;
                    sum += num;
                    sum_sqs += (num*num);
    }
    average = sum/N;
    std_dev = sqrt((sum_sqs/N)-(average*average));

Analysis

There is a wealth of problems in these few lines:

pFile = fopen("argv[1]", "r");
fscanf(pFile, "%lf", &N);

while(!feof(pFile))
{
        fscanf(pFile, "%d", &num);
  1. You probably wanted to open the file designated by argv[1] , not a file called argv[1] . Remove the quotes.
  2. You didn't check that you were passed an argument.
  3. You don't check that fopen() succeeded, so you probably crashed in your first fscanf() .
  4. You don't check that fscanf() succeeded. It is also odd to read what should probably be an integer value into a double , but the notation used will work.
  5. You should not use feof() like that, especially if …
  6. You don't check that the second fscanf() succeeded, and it won't work properly (but might not report the problem) because …
  7. You are trying to read integers ( %d ) into a double .

So, you should have written:

if (argc <= 1)
    …report error and exit…(or use pFile = stdin)…
FILE *pFile = fopen(argv[1], "r");
if (pFile == 0)
    …report error and exit…
if (fscanf(pFile, "%lf", &N) == 1)
{
    for (int i = 0; i < N; i++)
    {
        if (fscanf(pFile, "%lF", &num) != 1)
            …report error, close file, and exit…
        …as before…more or less…subject to fixing any as yet undiagnosed errors…
    }
}
fclose(pFile);

Incidentally, you forgot to set sum_sqs to zero before you started adding to it, so you won't know what value you got. Also, if all the numbers are negative, you'll report that the maximum is 0; if all the numbers are positive, you'll report that the minimum is 0. Fixing that is a tad fiddly, but you could use if (i == 0 || num < min) min = num; etc.


Linking Problem

Your linking problem (undefined reference to sqrt() ) indicates that you are running on a system where you need to link the maths library; that is usually -lm on the end of the linking command line.


Synthesis

#include <stdio.h>
#include <math.h>

int main(int argc, char*argv[])
{
    double average, num = 0, min = 0, max = 0, sum = 0, N, std_dev, sum_sqs = 0.0;

    if (argc <= 1)
    {
        fprintf(stderr, "Usage: %s file\n", argv[0]);
        return 1;
    }

    FILE *pFile = fopen(argv[1], "r");
    if (pFile == 0)
    {
        fprintf(stderr, "%s: failed to open file %s\n", argv[0], argv[1]);
        return 1;
    }
    if (fscanf(pFile, "%lf", &N) == 1)
    {
        for (int i = 0; i < N; i++)
        {
            if (fscanf(pFile, "%lF", &num) != 1)
            {
                fprintf(stderr, "%s: failed to read number\n", argv[0]);
                return 1;
            }

            if (num < min || i == 0)
                min = num;
            if (num > max || i == 0)
                max = num;
            sum += num;
            sum_sqs += (num*num);
        }
    }

    fclose(pFile);
    average = sum/N;
    std_dev = sqrt((sum_sqs/N)-(average*average));

    printf("Smallest: %7.2lf\n", min);
    printf("Largest: %7.2lf\n", max);
    printf("Average: %7.2lf\n", average);
    printf("Standard deviation: %7.3lf\n", std_dev);
    return(0);
}

Results

Given data file data :

5    
4.34 23.4 18.92 -78.3 17.9

The result of running the program is:

Smallest:  -78.30
Largest:   23.40
Average:   -2.75
Standard deviation:  38.309

Those values mostly look plausible; my calculation of the standard deviation came to 42.83 (using a different tool altogether). The difference is between the sample standard deviation and the population standard deviation (a factor of √1.25) — so your value is OK as you calculated it.

# Count    = 5
# Sum(x1)  = -1.374000e+01
# Sum(x2)  =  7.375662e+03
# Mean     = -2.748000e+00
# Std Dev  =  4.283078e+01
# Variance =  1.834476e+03
# Min      = -7.830000e+01
# Max      =  2.340000e+01

So, the code works for me. What result are you getting?

If you want the sqrt function, you need to add

#include <math.h>

to the top of your C file.

  • if you want to read a float with scanf , you should be using the %f format specifier, not %d (which will read an integer).
  • In your fopen call, remove the quotes around argv[1] , otherwise it'll look for a file with that name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM