在scanf中使用[^表示法]的目的是什么?

问题描述 投票:5回答:4

我遇到了一些代码,并想知道最初的开发人员是做什么的。以下是使用此模式的简化程序:

      #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;  
  }

man page for scanf有相关信息,但我无法阅读它。使用这种表示法的目的是什么?它想要完成什么?

c scanf format-specifiers
4个回答
6
投票

字符类的主要原因是%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);
}

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


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


4
投票

%[a]%[^a]这样的结构存在,因此scanf()可以用作一种词法分析器。这有点像%s,但它们不是收集尽可能多的“字符串”字符的范围,而是收集字符类所描述的字符范围。可能有些情况下写%[a-zA-Z0-9]可能有意义,但我不确定我看到一个令人信服的用例与scanf()补充类。

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

编辑:我通常因为面对坚持提供错误输入的用户而扯掉scanf(),它只是不善于帮助程序提供有关问题的良好反馈,并且有一个汇编程序打印“错误,终止”。因为它唯一有用的错误消息与我的用户不太好。 (在这种情况下,我。)


2
投票

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

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


0
投票

您可以在线查看ISO/IEC9899 standard中的相关内容。

以下是我从[(页286)文档中引用的一段:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.