首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >fscanf()的输出无效

fscanf()的输出无效
EN

Stack Overflow用户
提问于 2012-06-26 11:14:58
回答 3查看 378关注 0票数 0

我使用的语言是C,我试图扫描文件中的数据,代码段如下:

代码语言:javascript
复制
char lsm;
long unsigned int address;
int objsize;
while(fscanf(mem_trace,"%c %lx,%d\n",&lsm,&address,&objsize)!=EOF){
    printf("%c %lx %d\n",lsm,address,objsize);
}

我读取的文件的第一行如下:

代码语言:javascript
复制
 S 00600aa0,1
I  004005b6,5
I  004005bb,5
I  004005c0,5
 S 7ff000398,8

stdout中显示的结果为:

代码语言:javascript
复制
  8048350 134524916
S 600aa0 1
I 4005b6 5
I 4005bb 5
I 4005c0 5
S 7ff000398,8

显然,结果有额外的一行来自nowhere.Is,有人知道这是怎么发生的吗?谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-06-26 12:45:22

这对我适用于您提供的数据:

代码语言:javascript
复制
#include <stdio.h>

int main(void)
{
    char lsm[2];
    long unsigned int address;
    int objsize;
    while (scanf("%1s %lx,%d\n", lsm, &address, &objsize) == 3)
        printf("%s %9lx %d\n", lsm, address, objsize);
    return 0;
}

有多个变化。最简单和最不重要的是从fscanf()scanf()的更改;这是为了方便我。

一个重要的变化是lsm的类型从单个char变为两个字符的数组。然后,格式字符串使用%1s将一个字符(加上NUL '\0')读取到字符串中,但它也(这一点至关重要)跳过了前导空格。

另一个变化是在条件中使用== 3而不是!= EOF。如果出现错误,scanf()将返回成功匹配的数量。假设它设法读取了一个字母,但后面不是十六进制数字;它将返回1(不是EOF)。此外,它会在每次迭代中返回1,直到找到与十六进制数字匹配的值为止。始终测试您期望的值的数量。

输出格式已使用%9lx进行了整理。我是在64位系统上测试的,所以9位十六进制可以很好地转换。scanf()的一个问题是,如果在转换时出现溢出,则行为是未定义的。

输出:

代码语言:javascript
复制
S    600aa0 1
I    4005b6 5
I    4005bb 5
I    4005c0 5
S 7ff000398 8

你为什么会得到这样的结果呢?

第一次转换将一个空格读入lsm,但随后无法将S转换为十六进制数,因此将其留到下一个周期。因此,您在地址和对象大小列中打印了剩余的垃圾。第二次迭代读取S,然后与数据同步,直到最后一行。格式末尾的换行符(就像格式字符串中的任何其他空格一样)会占用空格,这就是为什么尽管有前导空格,最后一行仍然有效。

票数 1
EN

Stack Overflow用户

发布于 2012-06-26 12:49:02

作为转换规范的指令定义了一组匹配的输入序列,如下针对每个说明符所述。在以下步骤中执行转换规范:

除非规范包含[、c或n说明符,否则将跳过输入空格字符(由isspace函数指定)。

输入项是从流中读取的,除非规范包含n说明符。

..。

第一次调用fscanf时,%c将读取文件中的第一个空格。您的空白字符读取零个或多个空白字符,这次是零个。您的%lx无法匹配文件中的S字符,因此返回fscanf。你不会检查结果。您的变量包含它们从早期操作中获得的值。

第二次调用fscanf时,%c读取文件中的第一个S字符。从那时起,其他一切也都成功了。

在编辑中添加,以下是对格式字符串的最简单更改,以解决您的问题:

代码语言:javascript
复制
" %c %lx,%d\n"

开头的空格将读取零个或多个空白字符,然后%c将读取文件中的第一个非空白字符。

下面是另一个格式字符串,它也可以解决您的问题:

代码语言:javascript
复制
" %c %lx,%d"

原因是,如果您在一行中读取并丢弃零个或多个空格字符两次,结果与只读取一次相同。

票数 1
EN

Stack Overflow用户

发布于 2012-06-26 11:47:00

我认为fsanf将第一个字符空间读入lsm,然后无法读取addressobjsize,因为格式转换与该行的其余部分不匹配。

然后打印一个空格,然后声明它时在addressobjsize中发生的任何事情

编辑--

fscanf在每次调用后都会使用空格,如果您调用ftell,您将看到

代码语言:javascript
复制
printf("%c %lx %d %d\n",lsm,address,objsize,ftell(mem_trace));
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11200335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档