使用scanf接受用户输入

gcc 4.4.2

我正在阅读一篇关于scanf的文章。 我个人从未检查过scanf的返回码。

#include  int main(void) { char buf[64]; if(1 == scanf("%63s", buf)) { printf("Hello %s\n", buf); } else { fprintf(stderr, "Input error.\n"); } return 0; } 

我只是想知道当程序员在想要获得用户输入时使用scanf时还有其他技术吗? 或者他们使用其他function还是自己编写?

谢谢你的任何建议,

编辑=========

 #include  int main(void) { char input_buf[64] = {0}; char data[64] = {0}; printf("Enter something: "); while( fgets(input_buf, sizeof(input_buf), stdin) == NULL ) { /* parse the input entered */ sscanf(input_buf, "%s", data); } printf("Input [ %s ]\n", data); return 0; } 

我认为大多数程序员都认为scanf很糟糕,大多数人同意使用fgets和sscanf。 但是,我可以使用fgets来读取输入。 但是,如果我不知道用户将输入什么,我怎么知道要解析什么。 例如,如果用户要输入包含数字和字符并按任何顺序的地址?

不要直接使用scanf 。 令人惊讶的是难以使用。 最好读取整行输入然后解析它(可能使用sscanf )。

从comp.lang.c FAQ中读取此条目(以及它引用的条目): http : //c-faq.com/stdio/scanfprobs.html

编辑:好的,从您自己的编辑中解决您的其他问题:如果您允许非结构化输入,那么您将不得不尝试以多种方式解析字符串,直到找到有效的字符串。 如果找不到有效匹配,则应拒绝输入并再次提示用户,可能会解释您希望输入的格式。

对于任何更复杂的事情,你可能最好使用正则表达式库,甚至使用专用词法分析器/解析器工具包(例如flex和bison)。

我不使用scanf()进行交互式用户输入; 我使用fgets()读取所有内容作为文本,然后根据需要解析输入,使用strtol()strtod()将文本转换为数值。

scanf()落入的一个例子是用户输入错误的数值,但其初始部分有效,如下所示:

 if (scanf("%d", &num) == 1) { // process num } else { // handle error } 

如果用户输入“12e4”,则scanf()将成功转换并将“12”分配给num,在输入流中留下“e4”以填写将来的读数。 整个输入应该被视为伪造,但scanf()无法捕获这种错误。 OTOH,如果我这样做:

 if (fgets(buffer, sizeof buffer, stdin)) { int val; char *chk; val = (int) strtol(buffer, &chk, 10); if (!isspace(*chk) && *chk != 0) { // non-numeric character in input; reject it completely } else { // process val } } 

我可以捕获输入中的错误并在使用它的任何部分之前拒绝它。 这也可以更好地避免在输入流中留下垃圾。

scanf()是一个很好的工具, 如果你能保证你的输入始终是格式良好的。

scanf()有问题,因为如果希望用户键入一个整数,并输入一个字符串,通常程序就会发生炸弹。 这可以通过将所有输入作为字符串读取(使用getchar()),然后将字符串转换为正确的数据类型来克服。

 /* example one, to read a word at a time */ #include  #include  #define MAXBUFFERSIZE 80 void cleartoendofline( void ); /* ANSI function prototype */ void cleartoendofline( void ) { char ch; ch = getchar(); while( ch != '\n' ) ch = getchar(); } main() { char ch; /* handles user input */ char buffer[MAXBUFFERSIZE]; /* sufficient to handle one line */ int char_count; /* number of characters read for this line */ int exit_flag = 0; int valid_choice; while( exit_flag == 0 ) { printf("Enter a line of text (<80 chars)\n"); ch = getchar(); char_count = 0; while( (ch != '\n') && (char_count < MAXBUFFERSIZE)) { buffer[char_count++] = ch; ch = getchar(); } buffer[char_count] = 0x00; /* null terminate buffer */ printf("\nThe line you entered was:\n"); printf("%s\n", buffer); valid_choice = 0; while( valid_choice == 0 ) { printf("Continue (Y/N)?\n"); scanf(" %c", &ch ); ch = toupper( ch ); if((ch == 'Y') || (ch == 'N') ) valid_choice = 1; else printf("\007Error: Invalid choice\n"); cleartoendofline(); } if( ch == 'N' ) exit_flag = 1; } } 

我做一个循环调用fgets直到读取行的结尾,然后调用sscanf来解析数据。 检查sscanf是否到达输入行的末尾是个好主意。

我很少使用scanf 。 大多数时候,我使用fgets()将数据作为字符串读取。 然后,根据需要,我可以使用sscanf()或其他函数,如strto*函数族, str*chr()等,从字符串中获取数据。

如果我使用scanf()fgets() + sscanf() ,我总是检查函数的返回值,以确保它们完成了我想要它们做的事情。 我也不使用strtok()来标记字符串,因为我认为strtok()的接口被破坏了。