【问题标题】:sscanf fails on identically formatted inputsscanf 在相同格式的输入上失败
【发布时间】:2014-12-04 19:46:46
【问题描述】:

我坐在这里有点神秘。我有一个包含 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

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

【问题讨论】:

  • 神奇地修复了它!谢谢!

标签: c io scanf


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多