C 在输入中获取整数而不会遇到任何错误

C 在输入中获取整数而不会遇到任何错误,c,debugging,input,scanf,C,Debugging,Input,Scanf,scanf()肯定是一个有很多问题的函数,所以我一直在寻找替代它的方法。 我在post的第一个答案中发现了这段代码,但即使是这段代码也有错误(如果用户输入换行符,循环结束)。 有没有一种方法可以在输入中获得一个整数而不会遇到任何类型的错误 代码: 编辑: 我根据@chqrlie的答案和我在[here][2]中找到的一段代码编写了这个函数,有没有办法改进这个函数并使其更好? int readInteger(const char *prompt, const char *error) { i

scanf()
肯定是一个有很多问题的函数,所以我一直在寻找替代它的方法。
我在post的第一个答案中发现了这段代码,但即使是这段代码也有错误(如果用户输入换行符,循环结束)。 有没有一种方法可以在输入中获得一个整数而不会遇到任何类型的错误

代码: 编辑: 我根据@chqrlie的答案和我在[here][2]中找到的一段代码编写了这个函数,有没有办法改进这个函数并使其更好?
int readInteger(const char *prompt, const char *error) {
    int number;
    char buf[1024]; // use 1KiB to be sure
    
    while(1) {
        printf("%s", prompt);
        if(!fgets(buf, 1024, stdin)) exit(1);  // reading input failed
        
        // have some input, convert it to integer
        char *endptr;
        errno = 0;
        number = (int)strtol(buf, &endptr, 10);
        
        while(isspace((unsigned char)*endptr)) endptr++; // ignore trailing white space

        if(errno == ERANGE) printf("%s", error);
        else if(endptr != buf && !(*endptr && *endptr != '\n')) return number;
    }
}

发布的代码需要一些改进,但可以包装在函数中以读取
int
值:

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

int get_int(const char *prompt, int *result) {
    char buf[100];
    char *end;

    for (;;) {
        if (prompt) {
            printf("%s: ", prompt);
        }
        if (!fgets(buf, sizeof buf, stdin)) {
            printf("unexpected end of file\n");
            return -1;
        }
        errno = 0;
        long n = strtol(buf, &end, 0);
        if (end == buf) {
            printf("invalid input: %s", buf);
            continue;
        }
        if (errno != 0 || n > INT_MAX || n < INT_MIN) {
            printf("value outside range of int: %s", buf);
            continue;
        }
        // ignore trailing white space
        while (isspace((unsigned char)*end) {
            end++;
        }
        if (*end != '\0') {
            printf("ignoring tailing input: %s", end);
        }
        *result = (int)n;
        return 0;   // success
    }
}
#包括
#包括
#包括
#包括
#包括
int get_int(常量字符*提示符,int*结果){
char-buf[100];
字符*结束;
对于(;;){
如果(提示){
printf(“%s:”,提示符);
}
如果(!fgets(buf,sizeof buf,stdin)){
printf(“意外的文件结尾\n”);
返回-1;
}
errno=0;
长n=strtol(buf,&end,0);
如果(结束==buf){
printf(“无效输入:%s”,buf);
继续;
}
if(errno!=0 | | n>INT|u MAX | | n
buf[strlen(buf)-1]=0;
to
//删除\n
不安全。首先,输入不保证以
\n
字符结尾,如果输入是空字符串(也可能)
buf[strlen(buf)-1]=0;
是未定义的行为。没错,该代码非常糟糕。有关如何在不使用
scanf
的情况下合理可靠地读取输入的好答案,请参阅。在跳过空白之前,必须测试
if(endptr==buf).*
。同时将最后一行更改为
if(*endptr='\0')返回编号;
测试
errno==ERANGE
是不够的,因为类型
long
的范围可能大于类型
int
。在
strtol()之后
call,您必须检查转换是否成功:如果
endptr==buf
转换失败,因为缓冲区不包含数字。如果
errno!=0
数字超出了类型
long
的范围。请注意,
strtol
可能返回的数字超出了类型
int
的范围也应该测试。在
while(isspace(…)
循环中完成数字后跳过空格,并且它还跳过换行符。如果
*endptr!='\0'
输入行上有额外的非空白字符,这也应视为错误。
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

int get_int(const char *prompt, int *result) {
    char buf[100];
    char *end;

    for (;;) {
        if (prompt) {
            printf("%s: ", prompt);
        }
        if (!fgets(buf, sizeof buf, stdin)) {
            printf("unexpected end of file\n");
            return -1;
        }
        errno = 0;
        long n = strtol(buf, &end, 0);
        if (end == buf) {
            printf("invalid input: %s", buf);
            continue;
        }
        if (errno != 0 || n > INT_MAX || n < INT_MIN) {
            printf("value outside range of int: %s", buf);
            continue;
        }
        // ignore trailing white space
        while (isspace((unsigned char)*end) {
            end++;
        }
        if (*end != '\0') {
            printf("ignoring tailing input: %s", end);
        }
        *result = (int)n;
        return 0;   // success
    }
}