当字符和整数混合时,在C中控制用户输入

当字符和整数混合时,在C中控制用户输入,c,input,scanf,defensive-programming,C,Input,Scanf,Defensive Programming,因此,我尝试为一个只接受选项1、2和3的程序创建一个简单的菜单,我想控制用户输入,以防止出现错误,比如用户输入char而不是int 现在,它控制一些情况,例如,如果选项小于1或大于3,如果选项是字符,它也不会影响,但当用户输入“02”或“2a”之类的内容时,它会运行选项2,但应该使该选项无效 此外,如果我错过了更多的案例,我想知道它们以及如何克服它们 #include <stdio.h> #include <stdlib.h> void empty_stdin(void

因此,我尝试为一个只接受选项1、2和3的程序创建一个简单的菜单,我想控制用户输入,以防止出现错误,比如用户输入char而不是int

现在,它控制一些情况,例如,如果选项小于1或大于3,如果选项是字符,它也不会影响,但当用户输入“02”或“2a”之类的内容时,它会运行选项2,但应该使该选项无效

此外,如果我错过了更多的案例,我想知道它们以及如何克服它们

#include <stdio.h>
#include <stdlib.h>

void empty_stdin(void);

int main() {
    int option;
    int rtn;

    do {
        printf("\n--\nOptions:\n1.Option 1\n2.Option 2\n3.Option 3\n--\n\nPlease chose option (1/2/3) to continue: ");
        rtn = scanf("%d", &option);

        if (rtn == 0 || option < 1 || option > 3) {
            printf("-Invalid Option-\n");
            empty_stdin();
        } else {

            empty_stdin();

            switch (option) {
                case 1:
                    printf("Option 1");
                    break;

                case 2:
                    printf("Option 2");
                    break;
                case 3:
                    printf("Option 3");
                    exit(0);

                default:
                    printf("\n-Invalid Option-\n");
            }
        }
    } while (option != 3);
    return 0;
}

void empty_stdin(void) {
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}
预期输入/输出

--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 1
Option 1
--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 12
-Invalid Option-

--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: char
-Invalid Option-

--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 02
Option 2
--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 2a
Option 2
--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 02a
Option 2
--
Options:
1.Option 1
2.Option 2
3.Option 3
-- 

--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 1
Option 1
--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 12
-Invalid Option-

--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: char
-Invalid Option-

--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 02
-Invalid Option-
--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 2a
-Invalid Option-
--
Options:
1.Option 1
2.Option 2
3.Option 3
--

Please chose option (1/2/3) to continue: 02a
-Invalid Option-
--
Options:
1.Option 1
2.Option 2
3.Option 3
--


考虑使用
fgets
捕获输入,使用
strtol
解析整数

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>

int fgetsint ( int *value, int min, int max, FILE *fin) {
    char line[100] = "";
    char extra = '\0';
    char *end = NULL;
    long int number = 0;

    if ( fgets ( line, sizeof line, fin)) {//read a line
        errno = 0;
        number = strtol ( line, &end, 10);
        if ( end == line) {// nothing was parsed. no digits
            printf ( "input [%s] MUST be a number\n", line);
            return 0;// return failure
        }
        if ( ( errno == ERANGE && ( number == LONG_MAX || number == LONG_MIN))
        || ( errno != 0 && number == 0)) {// parsing error from strtol
            perror ( "input error");
            return 0;
        }
        if ( 1 == sscanf ( end, " %c", &extra)) {//parse trailing character
            printf ( "enter one number only. try again\n");
            return 0;
        }
        if ( number > max || number < min) {
            printf ( "Input [%ld] out of range: min: %d max: %d\n", number, min, max);
            return 0;
        }
        if ( 1 != (int)( end - line)) {
            printf ( "input one digit\n");
            return 0;// return failure
        }
        *value = number;//assign number to pointer
    }
    else {
        fprintf ( stderr, "problem fgets\n");
        exit ( EXIT_FAILURE);
    }

    return 1;//success
}

int main ( void) {
    int option = 0;

    do {
        printf("\n--\nOptions:\n1.Option 1\n2.Option 2\n3.Option 3\n--\n\nPlease chose option (1/2/3) to continue: ");

        option = 0;
        fgetsint ( &option, 1, 3, stdin);

        switch (option) {
            case 1:
                printf("Option 1");
                break;

            case 2:
                printf("Option 2");
                break;
            case 3:
                printf("Option 3");
                exit(0);

            default:
                printf("\n-Invalid Option-\n");
        }
    } while ( option != 3);
    return 0;
}
#包括
#包括
#包括
#包括
int fgetsint(int*值、int最小值、int最大值、文件*fin){
字符行[100]=“”;
字符额外='\0';
char*end=NULL;
长整数=0;
如果(fgets(line,sizeof line,fin)){//读取一行
errno=0;
编号=strtol(行和结束,10);
如果(end==line){//未分析任何内容。无数字
printf(“输入[%s]必须是一个数字\n”,第行);
返回0;//返回失败
}
if((errno==ERANGE&&(number==LONG_MAX | | number==LONG_MIN))
||(errno!=0&&number==0)){//strtol解析错误
perror(“输入错误”);
返回0;
}
如果(1==sscanf(end,“%c”,&extra)){//分析尾随字符
printf(“仅输入一个数字。重试\n”);
返回0;
}
如果(数量>最大值| |数量<最小值){
printf(“输入[%ld]超出范围:最小值:%d最大值:%d\n”,数字,最小值,最大值);
返回0;
}
如果(1!=(int)(结束行)){
printf(“输入一位数字”);
返回0;//返回失败
}
*value=number;//将数字分配给指针
}
否则{
fprintf(标准,“问题集”);
退出(退出失败);
}
返回1;//成功
}
内部主(空){
int选项=0;
做{
printf(“\n--\n选项:\n1.Option 1\n2.Option 2\n3.Option 3\n--\n\n请选择选项(1/2/3)继续:”;
选项=0;
fgetsint(选项1、3、标准);
开关(选件){
案例1:
printf(“选项1”);
打破
案例2:
printf(“选项2”);
打破
案例3:
printf(“选项3”);
出口(0);
违约:
printf(“\n-无效选项-\n”);
}
}while(选项!=3);
返回0;
}

以下建议的代码:

#include <stdio.h>

void empty_stdin( void );

int main( void ) 
{
    int option = 9;

    do 
    {
        printf("\n--\nOptions:\n"
               "1.Option 1\n"
               "2.Option 2\n"
               "3.Option 3\n"
               "--\n\n"
               "Please chose option (1/2/3) to continue: ");
        option = getchar();

        empty_stdin();

        switch (option) 
        {
            case 1:
                printf( "Option 1\n" );
                break;

            case 2:
                printf( "Option 2\n" );
                break;

            case 3:
                printf( "Option 3, exiting\n" );
                //exit(0);
                break;

            default:
                printf( "\n-option: %d invalid-\n", option );
                break;
        }
    } while ( option != 3 && option != EOF );
    return 0;
}

void empty_stdin( void ) 
{
    //int c = getchar();

    //while (c != '\n' && c != EOF)
        //c = getchar();
    int c;
    while( (c = getchar() ) != EOF && c != '\n' );
}
  • 干净地编译
  • 执行所需的功能
  • 处理所有“oops”案例
  • 为印刷等而使用右边距
  • 现在,拟议的守则:

    #include <stdio.h>
    
    void empty_stdin( void );
    
    int main( void ) 
    {
        int option = 9;
    
        do 
        {
            printf("\n--\nOptions:\n"
                   "1.Option 1\n"
                   "2.Option 2\n"
                   "3.Option 3\n"
                   "--\n\n"
                   "Please chose option (1/2/3) to continue: ");
            option = getchar();
    
            empty_stdin();
    
            switch (option) 
            {
                case 1:
                    printf( "Option 1\n" );
                    break;
    
                case 2:
                    printf( "Option 2\n" );
                    break;
    
                case 3:
                    printf( "Option 3, exiting\n" );
                    //exit(0);
                    break;
    
                default:
                    printf( "\n-option: %d invalid-\n", option );
                    break;
            }
        } while ( option != 3 && option != EOF );
        return 0;
    }
    
    void empty_stdin( void ) 
    {
        //int c = getchar();
    
        //while (c != '\n' && c != EOF)
            //c = getchar();
        int c;
        while( (c = getchar() ) != EOF && c != '\n' );
    }
    
    #包括
    void empty_stdin(void);
    内部主(空)
    {
    int选项=9;
    做
    {
    printf(“\n--\n选项:\n”
    “1.选项1\n”
    “2.选项2\n”
    “3.选项3\n”
    “--\n\n”
    “请选择选项(1/2/3)继续:”;
    option=getchar();
    空_stdin();
    开关(选件)
    {
    案例1:
    printf(“选项1\n”);
    打破
    案例2:
    printf(“选项2\n”);
    打破
    案例3:
    printf(“选项3,退出\n”);
    //出口(0);
    打破
    违约:
    printf(“\n-选项:%d无效-\n”,选项);
    打破
    }
    }while(选项!=3&&option!=EOF);
    返回0;
    }
    void empty\u stdin(void)
    {
    //int c=getchar();
    //而(c!='\n'&&c!=EOF)
    //c=getchar();
    INTC;
    而((c=getchar())!=EOF&&c!='\n');
    }
    
    而不是
    scanf
    我将使用get
    getchar
    读取用户输入;然后有一个字符可以检查数字。就
    scanf(“%d”…)
    而言,
    02
    2
    一样是一个有效的整数,它们的值相同。另外,
    2a
    将读取
    2
    。如果希望更准确,请将输入作为单个字符读取,因为例如,前导0将是C库中任何整数解析函数的有效整数输入的一部分。初始化所有变量是您应该采用的习惯。