我正在制作一个程序,用逗号分隔的用户名。该程序允许用户在逗号之间放置任意数量的空格。例如:
如果我输入类似
的内容Smith, John
或
Smith,John
我想打印出来
John, Smith
问题是我的程序没有正确处理上面的以下示例;如果输入类似于
,它就可以工作Smith , John
或
Smith ,John.
这是我的代码:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LINESIZE 128
int get_last_first(FILE *fp);
int main (void)
{
get_last_first(stdin);
}
/*takes names in the format [LASTNAME],[FIRSTNAME]*/
int get_last_first(FILE *fp)
{
char first[LINESIZE];
char last[LINESIZE];
char line[LINESIZE];
size_t i;
while(1)
{
printf("Enter your last name followed by a comma and your first name\n");
/*if we cant read a line from stdin*/
if(!fgets(line, LINESIZE, fp))
{
clearerr(stdin);
break; /*stop the loop*/
}
/*goes through the line array and checks for non-alphabetic characters*/
for(i = 0; i < strlen(line); i++)
{
if(!isalpha(line[i]))
{
/*if it sees a space hyphen or comma, it continues the program*/
if((isspace(line[i]) || line[i] == ',') || line[i] == '-' )
{
continue;
}
else
{
return -1;
}
}
}
if(sscanf(line, "%s , %s", last, first))
{
printf("%s, %s", first, last);
return 1;
}
return 0;
}
}
是因为我没有正确使用sscanf吗?
答案 0 :(得分:2)
sscanf()
不进行模式匹配;逗号是一个完全有效的非空白字符串组件,因此会被%s
规范吞噬。您可以使用类似%[^ \t,]
的内容来匹配空格或逗号的字符串。
答案 1 :(得分:1)
geekosaur的answer概述了基本问题 - 是的,您滥用sscanf()
。
您的代码中还存在其他问题。
strlen()
;它每次被调用并产生相同的答案(除非你正在乱砍字符串)。在循环之前调用它一次并使用保存的值。在风格上,您在条件中有不必要的括号和空格(以及错过必要的空格):
if((isspace(line[i]) || line[i] == ',') || line[i] == '-' )
if (isspace(line[i]) || line[i] == ',' || line[i] == '-')
关键字后面应该有一个空格(参见标准)。没有必要用额外的括号来打破三向条件的对称性;并且在最后的近似括号之前不需要空格。 (或者,如果你坚持的话,那么在条件的左括号之后你需要一个平衡的开放空间。但请不要坚持。)
您需要测试sscanf()
成功转换了两个值;你只是检查它没有转换0值。它可能会返回1;它可能会返回EOF(以及0或2)。
break
打破,但该函数未返回值。main()
程序会忽略函数返回的值 - 因此您根本不需要返回值。return
的末尾省略main()
,但我更愿意在那里看到它。 (你没有承诺让main()
返回void
;谢谢你。)#include
和<stdio.h>
之间。再次,看看C标准并注意他们如何编写它:#include <stdio.h>
并且同样如此。标记为'风格'的评论是建议 - 编译器基本上没有注意到空格或缺少空格。尽管如此,C标准显示了所有在#include
和for
之类的关键字之后if
行和空格中包含空格的示例,而Kernighan和Ritchie对C的原始描述也是如此,所以你有可靠的先例。通常,如果您遵循标准约定,其他人会发现您的代码更容易阅读。支撑的位置更具争议性 - 但如果你跟随K&amp; R(即使我更喜欢Allman风格),你也不会出错。