简体   繁体   中英

In C, how do I read a file, and store only the doubles - ignoring text before?

I need to read in a file that contains text, and then a double for that text. It is simply to get the mean and standard deviation for the set of numbers, so the text that comes before is irrelevant. For example, my input file looks a little like:

preface 7.0000
chapter_1 9.0000
chapter_2 12.0000
chapter_3 10.0000

etc..

In this case, it is finding the mean and std dev for the chapters of a book. I have the section of code below, but I'm not quite sure how to "ignore" the text, and only grab the doubles. At the moment this code prints out zeros and only exits the loop when it exceeds the array limit, which I set as a constant to 20 at the beginning of the program.

FILE *ifp;
char *mode = "r";
ifp = fopen("table.txt", mode); 

double values[array_limit];
int i;
double sample;

if (ifp==NULL)
{
  printf("cannot read file \n");
}

else
{
i = 0;

do
{
   fscanf(ifp, "%lf", &sample);  

   if (!feof(ifp))
   {
      values[i] = sample;
      printf("%.4lf \n", values[i]);
      i++;
      if (i>=array_limit)   //prevents program from trying read past array size limit//
        {
           printf("No more space\n");
           break;
        }
   }

   else
   {
              printf("read complete\n");
              printf("lines = %d\n", i);
   }

  }while (!feof(ifp));
  fclose(ifp);
}

I think you could use fscanf(ifp, "%*[^ ] %lf", &sample) for reading from your file. The * says to ignore that particular match, the [] specifices a list of characters to match and the ^ indicates to match all characters except those in [] .

Or possibly (a bit simpler) fscanf(ifp, "%*s %lf", &sample) .

You have two major problems -- you're using feof which is pretty much always wrong , and you're not checking the return value of fscanf , which it what tells you whether you got a value or not (or whether you got to the eof).

So what you want is something like

while ((found = fscanf(ifp, "%lf", &values[i])) != EOF) {  /* loop until eof */
    if (found) {
        /* got a value, so count it */
        if (++i >= ARRAY_LIMIT) {
            printf("no more space\n");
            break;
        }
    } else {
        /* something other than a value on input, so skip over it */
        fscanf(ifp, "%*c%*[^-+.0-9]");
    }
}

When reading in from a file, it's often best to use fgets to read one line at a time, then extract the parts you are interested in using sscanf :

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

#define ARRAY_LIMIT 10
#define LINE_LENGTH 128

int main()
{
    double values[ARRAY_LIMIT];
    int i, count = 0;
    double sample;

    FILE *ifp = fopen("table.txt", "r");
    if (ifp==NULL)
    {
        printf("cannot read file \n");
        return 1;
    }

    char buff[LINE_LENGTH];
    while (fgets(buff, LINE_LENGTH, ifp) != NULL) 
    {
        if (sscanf(buff, "%*s %lf", &sample) != 1) break;
        values[count++] = sample;
        if (count == ARRAY_LIMIT) {
            printf("No more space\n");
            break;
        }
    }    
    fclose(ifp);

    for (i = 0; i < count; ++i) {
        printf("%d: %f\n", i, values[i]);
    }

    return 0;
}

fgets returns NULL if it encounters the end of the file, or if a read error has occurred. Otherwise, it reads one line of the file into the character buffer buff .

The asterisk %*s in the sscanf means that the first part of the line is discarded. The second part is written to the variable sample . I am checking the return value of sscanf , which indicates how many values have been read successfully.

The loop breaks when the end of the file is reached or the count reaches the size of the array.

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