9

我遇到了一些代码,想知道原始开发人员在做什么。下面是一个使用这种模式的简化程序:

      #include <stdio.h>

      int main()  {     

      char title[80] = "mytitle";      
      char title2[80] = "mayataiatale";      
      char mystring[80]; 

      /* hugh ? */
      sscanf(title,"%[^a]",mystring);
      printf("%s\n",mystring); /* Output is "mytitle" */


      /* hugh ? */
      sscanf(title2,"%[^a]",mystring); /* Output is "m" */
      printf("%s\n",mystring);


      return 0;  
  }

scanf的手册页有相关信息,但我无法阅读它。使用这种符号的目的是什么?它试图完成什么?

4

4 回答 4

8

字符类的主要原因是 %s 符号在第一个空白字符处停止,即使您指定了字段长度,而且您通常不希望它这样做。在这种情况下,字符类表示法会非常有用。

考虑此代码以读取最多 10 个字符的行,丢弃任何多余的字符,但保留空格:

#include <ctype.h>
#include <stdio.h>

int main(void)
{
    char buffer[10+1] = "";
    int rc;
    while ((rc = scanf("%10[^\n]%*[^\n]", buffer)) >= 0)
    {
            int c = getchar();
            printf("rc = %d\n", rc);
            if (rc >= 0)
                    printf("buffer = <<%s>>\n", buffer);
            buffer[0] = '\0';
    }
    printf("rc = %d\n", rc);
    return(0);
}

这实际上是关于 comp.lang.c.moderated(大约 2004 年 6 月)与getline()变体相关的讨论的示例代码。


至少出现了一些混乱。第一个格式说明符 ,%10[^\n]最多读取 10 个非换行符并将它们分配给缓冲区,以及尾随的 null。第二个格式说明符%*[^\n]包含赋值抑制字符 ( *) 并从输入中读取零个或多个剩余的非换行符。当scanf()函数完成时,输入指向下一个换行符。循环体读取并打印该字符,因此当循环重新开始时,输入正在查看下一行的开头。然后重复该过程。如果该行短于 10 个字符,则将这些字符复制到缓冲区,并且“零个或多个非换行符”格式处理零个非换行符。

于 2009-04-20T02:55:16.020 回答
4

类似%[a]%[^a]存在的结构scanf()可以用作一种词法分析器。这些有点像%s,但它们不是收集尽可能多的“字符串”字符,而是只收集字符类描述的字符范围。在某些情况下,编写%[a-zA-Z0-9]可能有意义,但我不确定我是否看到了具有scanf().

恕我直言,scanf()根本不是这项工作的正确工具。每次我开始使用它的一个更强大的功能时,我最终都会把它撕掉并以不同的方式实现该功能。strtok()在某些情况下,这意味着使用 lex 编写真正的词法分析器,但通常一次执行 I/O 并在进行值转换之前将其粗略地分解为标记就足够了。

编辑:我结束了删除scanf()通常是因为当面对用户坚持提供不正确的输入时,它只是不擅长帮助程序对问题提供良好的反馈,并且让汇编程序打印“错误,终止”。因为它唯一有用的错误信息并没有被我的用户接受。(我,在那种情况下。)

于 2009-04-20T00:45:19.843 回答
2

这就像正则表达式中的字符集;[0-9]匹配一串数字,[^aeiou]匹配任何不是小写元音的东西,等等。

有各种各样的用途,例如提取数字、标识符、空格块等。

于 2009-04-20T00:40:38.340 回答
0

您可以在在线提供的ISO/IEC9899 标准中了解它。

这是我从文件中引用的一段[(第286页):

匹配一组预期字符中的非空字符序列。

转换说明符包括格式字符串中的所有后续字符,直到并包括匹配的右括号 (])。括号之间的字符(扫描列表)组成扫描集,除非左括号之后的字符是一个抑扬符 (^),在这种情况下,扫描集包含所有未出现在抑扬符和右括号之间的扫描列表中的字符。如果转换说明符以 [] 或 [^] 开头,则右括号字符在扫描列表中,并且下一个右括号字符是结束说明的匹配右括号;否则后面的第一个右括号字符是结束规范的字符。如果 - 字符在扫描列表中并且不是第一个字符,也不是第一个字符是 ^ 的第二个字符,也不是最后一个字符,

于 2016-11-08T16:13:07.907 回答