sscanf在格式相同的输入上失败

时间:2014-12-04 19:46:46

标签: c io scanf

我坐在这里有一点神秘感。我有一个包含230行数据的文件,由换行符分隔为6个块。每个非空行的格式相同,但sscanf函数失败了一半。

这里有一些失败的代码:

void extract_data(const size_t match_count, FILE *league_file, match *matches) {
  int thousands, hundreds, i, current_round = 1, current_match = 0, scanned_items;
  char buffer[BUFFERSIZE];
  match temp_match;
  rewind(league_file);

  for (i = 0; fgets(buffer, BUFFERSIZE, league_file) != NULL; i++) {
    /* printf("read: %s\n", buffer); */
    scanned_items = sscanf(buffer, "%s %i/%i %i.%i %s - %s %i - %i %i.%i",
               temp_match.weekday, &temp_match.day, &temp_match.month,
               &temp_match.hour, &temp_match.minute,
               temp_match.home_team, temp_match.away_team,
               &temp_match.home_score, &temp_match.away_score,
               &thousands, &hundreds);
    temp_match.spectator_count = (thousands * 1000) + hundreds;
    temp_match.year =  temp_match.month >= JUL ? 2013 : 2014;
    temp_match.round = current_round;

    if (scanned_items != -1) /* for debugging purposes */
      printf("%3i round %2i %s %02i/%02i %02i.%02i %3s - %3s %i - %i %i\n",
         i + 1, current_round,
         temp_match.weekday, temp_match.day, temp_match.month,
         temp_match.hour, temp_match.minute,
         temp_match.home_team, temp_match.away_team,
         temp_match.home_score, temp_match.away_score,
         temp_match.spectator_count);

    /* if everything was successfully read, copy the temp onto the output array */
    if(scanned_items == 11) {
      matches[current_match] = temp_match;
      current_match++;
    }
    else if (scanned_items == -1) { /* if empty line is met */
      current_round++;
      printf("%3i\n", i + 1);
    }
    else { /* report how many items were successfully scanned */
      printf("    scanned items: %i\n", scanned_items);
    }
  }
}

以下是该文件的摘录:

Fre     19/07 18.30     AGF - FCM      0 - 2     9.364   
Lor     20/07 17.00     VFF - RFC      2 - 2     4.771   
Son     21/07 14.00     OB - SDR       1 - 1     7.114   
Son     21/07 17.00     BIF - FCV      1 - 1     18.770  
Son     21/07 19.00     AAB - FCK      2 - 1     7.062   
Man     22/07 19.00     EFB - FCN      4 - 0     7.594   

Fre     26/07 18.30     FCN - VFF      1 - 1     5.067  
Lor     27/07 17.00     FCV - AGF      0 - 2     3.859   
Son     28/07 14.00     RFC - OB       1 - 1     4.852   
Son     28/07 17.00     SDR - BIF      1 - 0     5.700   
Son     28/07 19.00     FCM - FCK      1 - 0     8.759   
Man     29/07 19.00     EFB - AAB      1 - 2     9.517   

Fre     02/08 18.30     FCM - SDR      2 - 1     5.145  
Lor     03/08 17.00     AGF - FCN      2 - 1     6.997   
Son     04/08 14.00     OB - VFF       4 - 2     7.889   
Son     04/08 17.00     FCK - RFC      1 - 3     12.956  
Son     04/08 19.00     BIF - EFB      0 - 2     14.771  
Man     05/08 19.00     FCV - AAB      2 - 1     4.688  

并且这里打印到控制台的调试输出(第一个数字是用于与文件交叉引用的行号):

  1 round  1 Fre 19/07 18.30 AGF - FCM 0 - 2 9364
  2 round  1 Lor 20/07 17.00 VFF - RFC 2 - 2 4771
  3 round  1 Son 21/07 14.00  OB - SDR 1 - 1 7114
  4 round  1 Son 21/07 17.00 BIF - FCV 1 - 1 18770
  5 round  1 Son 21/07 19.00 AAB - FCK 2 - 1 7050
  6 round  1 Man 22/07 19.00 EFB - FCN 4 - 0 7594
  7
  8 round  2 Fre 26/07 18.30 FCN - VFF 1 - 1 5055
  9 round  2 Lor 27/07 17.00 FCV - AGF 0 - 2 3859
 10 round  2 Son 28/07 14.00 RFC -  OB 1 - 1 4852
 11 round  2 Son 28/07 17.00 SDR - BIF 1 - 0 5700
 12 round  2 Son 28/07 19.00 FCM - FCK 1 - 0 8759
 13 round  2 Man 29/07 19.00 EFB - AAB 1 - 2 9517
 14
 15 round  3 Fre 02/00 08.00 EFB - AAB 1 - 2 9517
    scanned items: 4
 16 round  3 Lor 03/00 08.00 EFB - AAB 1 - 2 9517
    scanned items: 4
 17 round  3 Son 04/00 08.00 EFB - AAB 1 - 2 9517
    scanned items: 4
 18 round  3 Son 04/00 08.00 EFB - AAB 1 - 2 9517
    scanned items: 4
 19 round  3 Son 04/00 08.00 EFB - AAB 1 - 2 9517
    scanned items: 4
 20 round  3 Man 05/00 08.00 EFB - AAB 1 - 2 9517
    scanned items: 4
 21

尽管所有内容的格式都相同,但它仍然以某种方式设法失败。这是为什么?我该如何解决?

1 个答案:

答案 0 :(得分:1)

使用%i说明符,前面带零的数字'0'将被扫描为八进制值。前面带有0x的值将被扫描为十六进制。其他值扫描为十进制 对于01到07,八进制和十进制值是相同的。所以那些扫描没有问题。
扫描08时,扫描零,然后拒绝8而不是八进制字符 零被分配给.month成员 下一次扫描是使用%i的另一个整数。这次'8'被自己扫描为小数8并分配给.hour成员 格式表明接下来要扫描的是'。'但是'8'后面的字符是一个空格,扫描四个项目后sscanf表示失败 当十进制值有可能在零之前时,使用%d说明符可消除%i说明符的歧义。