【问题标题】:sscanf() skipping delimiter & widthsscanf() 跳过分隔符和宽度
【发布时间】:2019-04-08 10:18:28
【问题描述】:

我正在为 6502 编写一个汇编程序,并尝试从我准备的文件中读取指令和操作码数据。使用sscanf 存储数据,它只工作了一部分......

文件:

ADC,Im,69,2    
ADC,ZP,65,2
ADC,ZPx,75,2
ADC,Ab,6D,3
ADC,Abx,7D,3
ADC,Aby,79,3
...

这里只是与问题相关的部分代码。 fgets 工作正常。问题行在下面评论。如有需要会上传更多。

代码:

  FILE *fp = ...
  char bf[15];
  char name[3];
  char mode[3];
  char op[2];
  int bytes;

  while (fgets(bf,15,fp)) {
    //below is the problem line
    sscanf(bf, "%3[^,],%3[^,],%2[^,],%d", name, mode, op, &bytes);
  }
  printf("%s,%s,%s,%d\n", name, mode, op, bytes);

输出:

ADCIm,Im,69,2
ADCZP,ZP,65,2
ADCZPx75,ZPx75,75,2
ADCAb,Ab,6D,3
ADCAbx7D,Abx7D,7D,3
...

预计是(就像文件格式一样):

ADC,Im,69,2
ADC,ZP,65,2
ADC,ZPx75,75,2
ADC,Ab,6D,3
ADC,Abx7D,7D,3
...

看起来 op 和 bytes 都可以正常工作,但是 name 和 mode 变量有问题,即使我在参数中包含了宽度和分隔符。

【问题讨论】:

  • 经验教训 -- (1) 所有字符串都需要 nul-termination,(2) 不要吝啬缓冲区大小! 如果最大您预期的字段是3 使用16 如果您认为您的最大行可能是300 字符,则将缓冲区大小设置为1024; (3) 记住,缓冲区太长10,000 字节总是比1 字节太短更好。
  • @DavidC.Rankin 谢谢,吸取了教训:)
  • 另外,总是,总是,检查scanf函数族的返回值。否则,解析错误将使程序中的一切变得混乱(例如,由于未初始化的变量带有随机数据)。解析错误可能是由您从未注意到的格式字符串中的错误或您忘记考虑的有效输入引起的,而不仅仅是因为输入格式错误。

标签: c pointers file-io printf scanf


【解决方案1】:

实际上,问题不在于sscanf。由于缓冲区溢出,您有未定义的行为 - printf 对您的字符串不是以空值结尾的事实一无所知,它将继续打印字符,直到找到 '\0'

要阻止它这样做,您可以在格式说明符中提供最大字段宽度:

printf("%.3s,%.3s,%.2s,%d\n", name, mode, op, bytes);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多