使用fscanf读取行

7

你好,我有一个文件,其中包含以下内容:

wwa weweweof ewewe wdw:

      1    11 ms    <1 ms    <1 ms  174.78.134.1  
      2    11 ms    <1 ms    <1 ms  174.78.134.1 
      3     5 ms    <1 ms    <1 ms  x58trxd00.abcd.edu.com [143.71.290.42] 
      4    11 ms    <1 ms    <1 ms  174.78.134.1 

我正在使用

    if(linecount == 8)
    while( fscanf(fp, "%d %s %s %s %s  %s %s",&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8) != EOF ){  
          printf("%s",ch);
        } 

    else if (linecount == 9){
       while( fscanf(fp, "%d %s %s %s %s  %s %s %s",&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8,&a9) != EOF ){  
          printf("%s",ch);
       }
    }

如何检查文件中的行是否包含8或9个元素,以便我可以相应地运行上述else-if语句?

4个回答

14

使用fscanf读取行

不是好主意。

但我认为这是个好主意,因为...

还是不是好主意。


使用fgets()函数来读取行 (阅读有趣的手册):

char buf[LINE_MAX];
while (fgets(buf, sizeof buf, file) != NULL) {
    // process line here
}

然后,您可以使用sscanf()(不建议使用)或像strchr()strtok_r()这样的健康函数进行解析(推荐使用)。值得注意的是,scanf()文档)的返回值不是EOF,而是成功读取实体的数量。因此,一种懒惰解析字符串的方法可能是:
if (sscanf(buf, "%s %s %s %s %s %s %s %s %s", s1, s2, ...) < 9) {
    // there weren't 9 items to convert, so try to read 8 of them only
}

请注意,在使用%s转换说明符时最好使用一些长度限制,以避免缓冲区溢出错误,例如:

char s1[100];
sscanf(buf, "%99s", s1);

同样地,在扫描(输入)字符串时,不应使用 & 取地址运算符 - 字符数组已经衰减为 char *,而这正是 %s 转换说明符所期望的类型 - 如果 s1 是一个由 N 个 char 组成的数组,则 &s1 的类型为 char (*)[N] - 类型不匹配会导致 scanf() 调用未定义行为。

谢谢您的解释,但如果没有9个元素,我该如何读取8个元素?是使用else if ...<8)吗? - KAKAK
@DeepakTivari,你包含了8个转换说明符而不是9个,可能是吗? - user529758
然而,我的txt文件可能包含9个元素、8个元素甚至更少的元素,例如:对于9个元素,我将获取第9个元素上的IP地址并存储它;对于8个元素,我将获取第8个元素上的IP地址并存储它。基本上,重要的是我从第8或第9个元素中提取IP地址,而不是其他元素。 - KAKAK
@DeepakTivari 你没理解我的意思... 首先尝试转换9个项目,如果失败了,则尝试转换8个项目,依此类推。 - user529758
好的,看来我忽略了sscanf函数,最后一个问题是,如果我没有指定&s9或&s8,我该如何将s9或s8存储到char [16]中?谢谢! - KAKAK
1
@DeepakTivari 嗯,也许你应该写 &s9 而不是 s9 - user529758

3
使用 fgets 来获取行,并使用一个 sscanf 检查是否有 9 个元素,如果失败,则再次使用 sscanf 来检查 8 个元素的行。
如果行的格式相同,只有一个额外的项目,请记住 scanf 函数系列返回成功扫描的项目数。因此,只需调用一次 sscanf,并检查它是否返回 89 可能就足够了。

0
不要在使用scanf时将&符号与字符串类型(字符数组)数据类型一起使用。
scanf("%s",name); //use it without "&" sign

原因:

C语言中的“字符串”是字符缓冲区的地址。您希望scanf填充由变量指向的缓冲区中的内存。

相比之下,int是一块内存,而不是一个地址。为了让scanf填充该内存,您需要传递其地址。


1
这可能是真的,但你应该解释一下为什么。就目前而言,这只是一个没有帮助的评论。 - AdrianHHH

0
你必须使用 fgets() 函数,因为你数组中的 swag 值当前设置为 null

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接