【问题标题】:reading the remainder of a string with sscanf用 sscanf 读取字符串的剩余部分
【发布时间】:2014-03-28 19:32:27
【问题描述】:

我正在尝试读取一个字符串,该字符串由一组数字和一个字符串组成,并用一些其他基本文本包裹。

换句话说,行的格式是这样的:

Stuff<5,10,-5,8,"Test string here.">

天真地,我试过了:

sscanf(str,"Stuff<%d,%d,%d,%d,\"%s\">",&i1,&i2,&i3,&i4,str2);

但经过一些研究,我发现%s 在遇到空白字符时应该停止解析。我找到了this question,但没有一个答案能解决我遇到的问题:字符串中可以包含任何字符,包括换行符和正确转义的引号。后者不是问题,如果我可以让 sscanf 将所有内容放在我提供的预分配缓冲区中的第一个引号之后,我可以自己剥离结尾。

但是我该怎么做呢?我不能使用%[],因为它需要其中的一些东西来终止字符串,而我唯一想要终止它的是空终止符。所以我想,“嘿,我只使用空终止符!”但是%[\0] 让编译器脾气暴躁:

warning: no closing ‘]’ for ‘%[’ format
warning: embedded ‘\0’ in format
warning: no closing ‘]’ for ‘%[’ format
warning: embedded ‘\0’ in format

使用%*c 之类的东西也不起作用,因为我不知道需要提取多少个字符。我尝试传递strlen(str),因为它会小于那个值,但是sscanf 返回4,并且没有任何东西放入str2,这表明可能是因为长度太长而放弃并且没有打扰。

更新:我想我可以这样做:

sscanf(str,"Stuff<%d,%d,%d,%d,\"%n",&i1,&i2,&i3,&i4,&n);
str2 = str+n;

【问题讨论】:

    标签: c string scanf


    【解决方案1】:

    您的更新似乎是一个很好的答案。在使用sscanf 得到i1i4 之后,我将建议strchr 找到第一个引号字符的位置。旁注,您应该始终检查来自sscanf 的返回值,以确保转换有效。这对于您建议的答案更为重要,因为如果前四次转换不成功,n 将保持未初始化状态。

    【讨论】:

      【解决方案2】:

      扫描'\"',然后扫描除'\"'以外的所有内容,然后再次扫描'\"'

      请务必检查sscanf() 结果并限制测试字符串的长度。

      char test_string[100];
      int n = 0;
      if (sscanf(str, "Stuff<%d,%d,%d,%d, \"%99[^\"]\"> %n",
            &i1, &i2, &i3, &i4, test_string, &n) == 5 && str[n] == '\0') Good();
      

      sscanf() 的角度来看,您使用"...%[\0]..." 的尝试是"...%["
      "\0" 开始的所有格式都将被忽略。

      使用int n = 0,将" %n" 附加到格式字符串,将&amp;n 附加到参数并检查str[n] == '\0' 是一个巧妙的技巧,sscanf() 可以确保正确解析整行。注意:"%n" 不会添加到 sscanf() 结果中。

      【讨论】:

        【解决方案3】:

        这不是实现您想要实现的目标的唯一方法,但可能是最简洁的方法:您需要使用 scansets。我不会直接用这个答案告诉你解决方案,我会解释如何使用我所知道的扫描集,希望你能够自己做。

        扫描集%[...] 就像%s 在赋值时一样,它们将值解释为字符并将它们存储到字符数组中。 %s 是以空格结尾的,%[...] 是它的灵活版本。

        有两种使用扫描集的方法,第一种是没有前面插入符号^,第二种是前面有插入符号^

        当您在没有前面插入符号^ 的情况下使用scanset 时,您放在括号内的字符将是唯一将被读取、存储然后留下的字符。只要scanf 遇到不匹配的字符,%[...] 就会结束。例如:

        // input: asdasdasdwasdasd
        char s[100] = { 0 };
        scanf( "%[das]", s );
        printf( "%s", s );
        // output: asdasdasd
        

        当您将 scanset 与前面的插入符号 ^ 一起使用时,搜索会反转。它读取、存储并留下每个字符,直到它到达您在前面的插入符号^ 之后放下的任何一个字符。示例:

        // input: abcdefgh^kekQ
        char s[100] = { 0 };
        scanf( "%[^Q^]", s );
        printf( "%s", s );
        // output: abcdefgh
        

        注意,剩余的字符仍然要在流中读取,文件指针不会超出导致终止的字符。 IE。对于第一个,getchar( ); 将给出一个 'w',对于第二个它将给出一个 '^'

        我希望这已经足够了。如果还是找不到出路,请走开,我可以给你解决办法。

        【讨论】:

          猜你喜欢
          • 2016-05-08
          • 1970-01-01
          • 1970-01-01
          • 2016-08-14
          • 1970-01-01
          • 2011-04-20
          • 1970-01-01
          • 2012-06-06
          相关资源
          最近更新 更多