2017-07-19 45 views
0

我有一个程序是为了采取命令第一个问题是格式的命令将在命令行或文件通过键入c或f 如果都没有输入while循环重复,而不允许输入等于不正确输入中的字符数,而不是停止并允许scanf再次获取输入。我不会在任何时候使用它的返回值,所以我为什么会发生这种情况而感到不知所措。正确输入'f'或'c'不会导致问题。 任何帮助,将不胜感激while循环重复scanf等于读取的字符数

#include<stdio.h> 
#include <math.h> 
#include <stdlib.h> 
#include <string.h> 
#define true 1 
#define false 0 
typedef int bool; 

double **temp_array; 
double temp1d_array[36]; 
char consolep[100]; 
char *fp1; 
FILE *fp; 
char string_IO1[50]; 
char string_temp[50]; 
char buffer[50]; 
char current_command[10]; 
int halt = 0; 
char *strtodptr; 

void main(){ 
printf("welcome \n"); 
char IO; 
char read[250]; 
char file_console; 
int IO_method = 0; 
char command[10]; 
char type_IO; 
char type_of_var_IO; 
char dim_IO[3]; 
char array_string_IO[40]; 

//console or file 

//decide IO Method loop 1 
while (IO_method==0) 
{ 
    printf("please type 'c'for console or 'f' for file to select input type\n"); 
    scanf("%c", &file_console); 

//if console 
if(file_console =='c') 
{ 
    IO_method=1; 
    printf("method is console\n"); 

} 

//if file 
    else if(file_console=='f') 
    { 
     IO_method=2; 
     printf("method is file\n"); 
     printf("please enter a file directory\n"); 
     scanf("%s",&string_IO1); 
    } 

    else 
    { 
     printf("invalid entry\n"); 
     file_console=NULL; 
     IO_method=0; 
    } 
}}//code here continues but i compiled it without and has no bearing on the error. 
+0

只适用于1个字符错误答案输入“ccccc”仍然导致重复 –

+2

发布代码不会编译 –

+0

固定代码编译,忘记了我的导入 –

回答

0

的调用在发布代码许可字符scanf()输入流中落后。例如,如果用户在第一个提示时输入g,则按ENTER之后,\n字符被留下。如果用户输入多个字符,则会留下额外的字符。后来对I/O函数的调用将拾取这些意外的字符,导致程序不合适。

一种解决方案是这样的I/O函数调用后写一点函数来清除输入流:

void clear_input(void) 
{ 
    int c; 
    while ((c = getchar()) != '\n' && c != EOF) { 
     continue; 
    } 
} 

此功能丢弃保持在输入流中的任何字符(直到并包括第一换行符)。请注意,c必须是int以确保EOF处理正确。另请注意,只有在输入流不为空时才应调用此函数;一个空的输入流将导致getchar()的呼叫阻塞,等待输入。

例如,在第一次调用scanf()后,您知道至少有一个\n字符仍在输入流中(也许在换行符之前有更多字符)。只需拨打clear_input()下一个I/O调用之前清理输入流:

scanf("%c", &file_console); 
clear_input(); 

通过scanf()返回的值应该在健壮的代码进行检查;返回成功分配的次数,或者在发生错误时很少出现EOF。这可以帮助验证输入。

更好的选择是使用fgets()stdin中读取并获取一行输入到缓冲区,然后使用sscanf()解析缓冲区。这里的一个好处是,fgets()将读取所有字符,包括换行符,只要缓冲区中有足够的空间。因此,分配一个慷慨的buffer[],以使缓冲区中可能没有合理的输入失败。如果您需要更加小心,可以检查输入缓冲区是否有\n字符(例如,使用strchr())。如果在缓冲区中发现的\n字符,然后输入流为空,否则有被留下多余的字符,并且clear_input()函数可以调用清理东西:

#include <stdlib.h> 
#include <string.h> 
... 
char buffer[1000]; 
char end; 
while (IO_method==0) 
{ 
    printf("please type 'c'for console or 'f' for file to select input type\n"); 
    if (fgets(buffer, sizeof buffer, stdin) == NULL) { 
     /* Handle input error */ 
     perror("Error in fgets()"); 
     exit(EXIT_FAILURE); 
    } 

    /* May need to clear input stream, if input is too large */ 
    if (strchr(buffer, '\n') == NULL) { 
     clear_input(); 
    } 

    /* Input again if input is not as expected */ 
    if (sscanf(buffer, "%c%c", &file_console, &end) != 2 || end != '\n') { 
     continue; 
    } 
... 

这里,buffer[]声明了一个慷慨的大小来保存所有合理的投入。 fgets()将输入放入buffer,直至包括换行符(空格允许)。请注意,检查从fgets()返回的值;如果存在罕见的I/O错误,则返回空指针。接下来,strchr()用于检查buffer中的\n;预期会出现,但如果不存在,则返回空指针,表示输入流中仍有字符被清除。接下来,使用sscanf()解析缓冲区。这里请注意,end用于存储用户输入字符后面的字符。在预期输入中,这是一个\n字符。如果用户输入太多字符,则测试end将显示此信息,并再次输入。

另请注意,在发布的代码中,未声明string_IO1(并且由于IO1中的字符难以在屏幕上区分,因此不是很好的名称)。如果这是一个字符数组,然后调用scanf()应该看起来像:

scanf("%s",string_IO1); 

而且,file_console已被宣布为char,所以分配新建分配FY file_console = NULL;是错误的,因为NULL是空指针宏,不一个整数类型。

+0

非常感谢你,我一直在寻找方式在线尝试和清除流。 它工作得很好 如果输入流已经空了,现在有什么方法可以保证安全吗?为了安全起见,我可以折腾一些吗?或者是否有内置的c函数可以检查流是否干净? –

+0

这样做的方式是当输入流为空时不能调用它。在scanf()之后调用是安全的,只要你不使用其他技巧来首先删除多余的字符。不过,没有必要使用额外的安全电话。我会稍后添加一些示例,以便更多地解决您的疑虑...... –

+0

“...丢弃保留在输入流中的任何字符。” - >更接近“...丢弃输入流中的字符直到行尾”。 – chux