代码之家  ›  专栏  ›  技术社区  ›  Donotalo

在fscanf()中使用[]

  •  6
  • Donotalo  · 技术社区  · 14 年前

    我有一个包含以下内容的文本文件:

    "abc","def","ghi"
    

    以下操作可正确读取文件内容:

    int main()
    {
        char name[1024] = {0};
        FILE *file = fopen("file.txt", "r");
    
        while(1)
        {
            if (fscanf(file, " %[\",]s ", name) == EOF)
                break;
            if (fscanf(file, " %[a-zA-Z]s ", name) == EOF)
                break;
    
            printf("%s\n", name);
        }
    
        return 0;
    }
    

    但是,以下失败:

    int main()
    {
        char name[1024] = {0}, garbage[5];
        FILE *file = fopen("file.txt", "r");
    
        while(1)
        {
            if (fscanf(file, " %[\",]s%[a-zA-Z]s ", garbage, name) == EOF)
                break;
    
            printf("%s\n", name);
        }
    
        return 0;
    }
    

    我正在使用MSVC++08。我错过了什么?我在找一个解决方案 fscanf() while 循环。

    4 回复  |  直到 7 年前
        1
  •  7
  •   pmg    14 年前

    有效吗???纯属厄运:-)

    你的转换规格意味着

    " %[\",]s "
             ^= optionally skip whitespace
            ^== read a literal 's'
      ^^^^^^=== read an unlimited string of quotes and commas
     ^========= optionally skip whitespace
    

    " %[a-zA-Z]s "
                ^= optionally skip whitespace
               ^== read a literal 's'
      ^^^^^^^^^=== read an unlimited string of letters
     ^============ optionally skip whitespace
    

    " %[\",]s%[a-zA-Z]s "
                       ^= optionally skip whitespace
                      ^== read a literal 's'
             ^^^^^^^^^=== read an unlimited string of letters
            ^============ read a literal 's'
      ^^^^^^============= read an unlimited string of quotes and commas
     ^=================== optionally skip whitespace
    

    我想你想要

    " %4[\",]%1023[a-zA-Z] "
                          ^= optionally skip whitespace
             ^^^^^^^^^^^^^== read a string of at most 1023 letters
      ^^^^^^^=============== read a string of at most 4 quotes and commas
     ^====================== optionally skip whitespace
    

    scanf 返回成功转换的次数或出错时的EOF。当您应该与1(或2,或其他值)进行比较时,您正在将结果值与EOF进行比较:与您期望的转换次数进行比较。

    if (scanf() == 3) /* expected 3 conversions */
    { /* ok */ }
    else { /* oops, something went wrong */ }
    
        2
  •  4
  •   Nietzche-jou    14 年前
    1. 括号是它们自己的转换说明符,而不是修饰符。 %[a-zA-Z]s 意思是“匹配任意数量的字母字符并指定给 name ,然后匹配文字 s . 移除 角色。
    2. 如果要匹配但丢弃某个内容,请使用星号而不是垃圾缓冲区: %*[\",] .
    3. 扫描 不会再回来了 EOF i . 考虑测试指定的说明符的计数,或者 "%*[\"]" 在结尾处把后面的引号括起来。

    这也是第一个版本起作用的原因。字面意义 无法匹配,但第一次转换成功,因此 名称 但不是 .


    if (fscanf(file, " %*[\",]%[a-zA-Z] ", name) < 1)
        break;
    

    fscanf(file, " %*[\",]%[a-zA-Z]%*[\"] ", name)
    
        3
  •  2
  •   chrisaycock spacemanspiff    14 年前

    删除“s”转换标志,如下所示:

    if (fscanf(file, " %[\",]%[a-zA-Z] ", garbage, name) < 2)
    

    请注意,我必须与2而不是EOF进行比较,因为下一次迭代将读取最后一个引号。

    编辑 :我很惊讶您的第一个代码示例也能工作,但是它在MacOSX上与gcc一起运行得很好,所以这不是微软特有的问题。

        4
  •  0
  •   Eugene Smith    14 年前

    以下方法应该有效:

          if (fscanf(file, " %[\",]%[a-zA-Z] ", garbage, name) == EOF) 
            break;