我遇到了一些代码,并且想知道最初的开发人员是做什么的。以下是使用此模式的简化程序:
#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有相关信息,但我无法阅读。使用这种表示法的目的是什么?它想要完成什么?
答案 0 :(得分: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个字符,则将这些字符复制到缓冲区,“零或多个非换行”格式处理零非换行。
答案 1 :(得分:4)
%[a]
和%[^a]
之类的结构存在,因此scanf()
可以用作一种词法分析器。它们有点像%s
,但它们不是收集尽可能多的“字符串”字符的范围,而是收集字符类所描述的字符范围。可能存在编写%[a-zA-Z0-9]
可能有意义的情况,但我不确定我是否会在scanf()
的补充类中看到令人信服的用例。
恕我直言,scanf()
根本不适合这项工作。每当我开始使用其中一个更强大的功能时,我最终都会将其剥离并以不同的方式实现该功能。在某些情况下,这意味着使用lex编写一个真正的词法分析器,但通常在进行值转换之前一次执行I / O并将其粗略地分解为strtok()
的标记就足够了。
修改:我结束了scanf()
,因为当面对坚持提供错误输入的用户时,它只是不善于帮助程序提供有关问题的良好反馈,和汇编程序打印“错误,终止。”因为它唯一有用的错误消息与我的用户不太好。 (在这种情况下,我。)
答案 2 :(得分:2)
这就像正则表达式中的字符集; [0-9]
匹配一串数字,[^aeiou]
匹配任何非小写元音等等。
有各种用途,例如拔出数字,标识符,空格块等。
答案 3 :(得分:0)
您可以在ISO/IEC9899 standard在线提供的内容中阅读相关内容。
以下是我从文档中引用[
(页286):
匹配一组预期的非空字符序列 字符。
转换说明符包括中的所有后续字符 格式字符串,包括匹配的右括号(])。该 括号之间的字符(扫描列表)组成扫描集, 除非左括号后的字符是旋音(^),否则 在哪种情况下,scanset包含所有未出现的字符 旋转和右支架之间的扫描列表。如果 转换说明符以[]或[^](右括号)开头 字符在扫描列表中,下一个右括号 character是匹配规范的匹配右括号; 否则第一个跟随右括号字符是那个 结束规范。如果 - 字符在扫描列表中而不是 第一个,也就是第一个字符是^的第二个,也不是 最后一个字符,行为是实现定义的。