Scan a random number of floats until new line in C

前端 未结 1 779
囚心锁ツ
囚心锁ツ 2021-01-27 02:18

I am trying to read from a file with this text inside:

f 502 601 596 465 464
f 597 599 600 598
f 602 591 596 601
f 588 565 5

1条回答
  •  南方客
    南方客 (楼主)
    2021-01-27 02:46

    Since you have an upper bound to the number of floats, use that, but do not hard-code the 13.

    Scan the file twice to determine the number of lines.

    Use fgets() to read each line.

    Use sscanf() or strtod() to read each number. Be sure to perform error checking.

    Untested code follows:

    #include 
    #include 
    #include 
    #include 
    #define faces_N 13
    
    typedef struct faces {
      float p[faces_N];
    } faces_T;
    
    void foo(void) {
      faces_T *eFace = NULL;
      size_t Lines = 0;
    
      FILE *fp;
      fp = fopen("text.txt", "r");
      if (fp == NULL)
        printf("Can't open file");
      else {
        char buff[2*(faces_N*(FLT_DIG + 10) + 1 + 1)];
        while (fgets(buff, sizeof(buff), fp) != NULL)
          Lines++;
        rewind(fp);
        eFace = malloc(Lines * sizeof(*eFace));
        assert(eFace);
    
        for (size_t l = 0; l < Lines; l++) {
          if (fgets(buff, sizeof(buff), fp) != NULL)
            Handle_IOError();
          if (buff[0] != 'f')
            Handle_FormatError();
          size_t f;
          char *p = &buff[1];
    
          for (f = 0; f < faces_N; f++) {
            int n;
            if (sscanf(p, "%f%n", &eFace[l].p[f], &n) != 1)
              break;
            p += n;
          }
          // TBD what to do with other
          for (; f < faces_N; f++) {
            eFace[l].p[f] = 0.0;  // Or maybe NaN or save count in eFace
          }
        }
        fclose(fp);
    
        // do whatever with eFaces;
    
      }
      free(eFaces);
    }
    

    The size of buff is debatable. I like 2x the maximum expected size and would throw an error if the buffer was full.

    The number of char to expect for a float should be able to distinguish all float. Estimating via " -D.DDDDDDffffde-dd", came up 1 (space) + 1 (sign) + 1 (.) + FLT_DIG + 3 (see link) + 4 (exponent). See the link for a discussion about printing precision: width specifier to maintain precision of floating-point value

    0 讨论(0)
提交回复
热议问题