0

I'm trying to write a program which will read from text files and then output the minimum, maximum and average values. The trouble I am having is ignoring comments in the text files that begin with a hashtag. Here is my working code so far. Can anyone help?

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
  char ch, filename[20];
  FILE *lun;
  int num, min, max, sum, count, first;

  printf("Please enter the  name of file to load:");
  scanf ("%s", filename);
  lun=fopen(filename, "r");
  if ( lun != NULL)
    {
      for ( sum= count= first= 0; fscanf( lun, "%d", &num ) == 1; sum += num, ++count )
        if ( !first ) { min= max= num; first= 1; }
        else if ( num > max ) max= num;
        else if ( num < min ) min= num;
      fclose( lun );

      printf( " Minimum value: %d\n Maximum value: %d\n Average value: %lf\n",
              min, max, sum / (double) count );
    }
  else
    printf( "Unable to read file.\n" );

  return 0;
}
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
rugerz
  • 1
  • 2
  • Do not destroy your question, or remove the code from the question, after you have received help on it. That is not fair to those who have spent time helping you. – Jonathan Leffler May 21 '15 at 14:06

1 Answers1

2

Read the data in lines (use fgets()). If the line contains a #, terminate the string there by replacing the '#' with '\0'. Then scan the line for numbers. See also How to use sscanf() in loops?

And don't forget to check that the file was opened.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char filename[20];

    printf("Please enter the name of file to load: ");
    if (scanf("%19s", filename) != 1)
    {
        fprintf(stderr, "Failed to read file name\n");
        return 1;
    }
    FILE *lun = fopen(filename, "r");
    if (lun == NULL)
    {
        fprintf(stderr, "Failed to open file %s for reading\n", filename);
        return 1;
    }
    char line[4096];
    int min = 0;  // Avoid compilation warnings (may be used uninitialized)
    int max = 0;  // Ditto
    int sum = 0;
    int count = 0;
    while (fgets(line, sizeof(line), lun) != NULL)
    {
        char *hash = strchr(line, '#');
        if (hash != NULL)
            *hash = '\0';
        int pos;
        int num;
        int off = 0;
        while (sscanf(line + off, "%d%n", &num, &pos) == 1)
        {
            if (count == 0)
                min = max = num;
            if (num > max)
                max = num;
            if (num < min)
                min = num;
            sum += num;
            count++;
            off += pos;  // Skip through line
        }
    }
    fclose(lun);

    printf("Minimum value: %d\nMaximum value: %d\nAverage value: %lf\n",
              min, max, sum / (double)count);
    return 0;
}

If your compiler doesn't support C99 or later, you will have to move variable declarations to the start of a block (immediately after a {).


Handling doubles isn't really any harder:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char filename[20];

    printf("Please enter the name of file to load: ");
    if (scanf("%19s", filename) != 1)
    {
        fprintf(stderr, "Failed to read file name\n");
        return 1;
    }
    FILE *lun = fopen(filename, "r");
    if (lun == NULL)
    {
        fprintf(stderr, "Failed to open file %s for reading\n", filename);
        return 1;
    }
    char line[4096];
    double min = 0.0;   // Avoids 'used when uninitialized' warnings
    double max = 0.0;   // Avoids 'used when uninitialized' warnings
    double sum = 0;
    int count = 0;
    while (fgets(line, sizeof(line), lun) != NULL)
    {
        char *hash = strchr(line, '#');
        if (hash != NULL)
            *hash = '\0';
        int pos;
        double num;
        int off = 0;
        while (sscanf(line + off, "%lf%n", &num, &pos) == 1)
        {
            if (count == 0)
                min = max = num;
            if (num > max)
                max = num;
            if (num < min)
                min = num;
            sum += num;
            count++;
            off += pos;  // Skip through line
        }
    }
    fclose(lun);

    printf("Minimum value: %f\nMaximum value: %f\nAverage value: %f\n",
              min, max, sum / count);
    return 0;
}
Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • What do you mean 'after a decimal'? After a decimal point? No; that wasn't part of the specification — you're reading integers, and integers don't contain decimal points (or, at least, they don't in C). If you want to handle that, you either read into `double` variables, and adjust other types accordingly, or you can detect a decimal point via `if (line[off + pos] == '.')` and then skip over digits until you come across a blank, or thereabouts. Up to you. But don't try changing the problem specification part way through — that is unfair to people trying to help you. – Jonathan Leffler May 21 '15 at 06:07
  • OK; if you need to read number that contain a decimal point, then you need to change the types of `min`, `max`, `sum`, `num` to `double`, change the scanning format from `%d` to `%lf`, and you can use `%f` or `%lf` in the printing formats (instead of `%d` again). You don't need the cast in the printing line, either, since `sum` is already a `double`. – Jonathan Leffler May 21 '15 at 06:43
  • (These comments were responses to question comments from the OP. The question was deleted once, then reinstated when some more information was needed — hence the second comment. Then the OP found that questions cannot be deleted after there's an answer with an up-vote.) – Jonathan Leffler May 21 '15 at 14:07