Read a line from file in C and extract the number of input

后端 未结 3 1648
感情败类
感情败类 2021-01-25 09:12

I have a file input.dat. In this file, there are 3 lines:

1 2 3
5 7 10 12
8 9 14 13 15 17

I am going to read one of the three li

3条回答
  •  说谎
    说谎 (楼主)
    2021-01-25 09:31

    You were thinking along the right path with your use of sscanf(), the only piece of the puzzle you were missing is how to apply an offset to line so that you read the next value in the line with your next call to sscanf(). You do that by keeping track of the number of characters consumed on each call to sscanf() using the "%n" conversion (it does not add to your conversion count returned by sscanf()) For example reading lines from the open file-stream fp, you could do:

    #define MAXC  1024      /* if you need a constant, #define one (or more) */
    ...
        char line[MAXC] = "";   /* buffer to hold each line */
        ...
        while (fgets (line, MAXC, fp)) {    /* reach each line in file */
            int offset = 0,                 /* offset in line for next sscanf() read */
                nchr = 0,                   /* number of char consumed by last read */
                val,                        /* integer value read with sscanf() */
                nval = 0;                   /* number of values read in line */
            /* conververt each integer at line + offset, saving no. of chars consumed */
            while (sscanf (line + offset, "%d%n", &val, &nchr) == 1) {
                printf (" %d", val);        /* output value read */
                offset += nchr;             /* update offset with no. chars consumend */
                nval++;                     /* increment value count */
            }
            printf ("  -  %d values\n", nval);  /* output no. values in line */
        }
    

    (Note: strtol() provides better error reporting than sscanf() on a failed conversion)

    If you put it together with an example that reads from the filename provided as the first argument to the program (or reads from stdin by default if no argument is given), you could do:

    #include 
    
    #define MAXC  1024      /* if you need a constant, #define one (or more) */
    
    int main (int argc, char **argv) {
    
        char line[MAXC] = "";   /* buffer to hold each line */
        /* use filename provided as 1st argument (stdin by default) */
        FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
    
        if (!fp) {  /* validate file open for reading */
            perror ("file open failed");
            return 1;
        }
    
        while (fgets (line, MAXC, fp)) {    /* reach each line in file */
            int offset = 0,                 /* offset in line for next sscanf() read */
                nchr = 0,                   /* number of char consumed by last read */
                val,                        /* integer value read with sscanf() */
                nval = 0;                   /* number of values read in line */
            /* conververt each integer at line + offset, saving no. of chars consumed */
            while (sscanf (line + offset, "%d%n", &val, &nchr) == 1) {
                printf (" %d", val);        /* output value read */
                offset += nchr;             /* update offset with no. chars consumend */
                nval++;                     /* increment value count */
            }
            printf ("  -  %d values\n", nval);  /* output no. values in line */
        }
    
        if (fp != stdin)                    /* close file if not stdin */
            fclose (fp);
    }
    

    Example Use/Output

    With the data you show in the filename dat/nvals.txt you would get:

    $ ./bin/fgetsnvals dat/nvals.txt
     1 2 3  -  3 values
     5 7 10 12  -  4 values
     8 9 14 13 15 17  -  6 values
    

    Look things over and let me know if you have further questions.

提交回复
热议问题