首页 > 解决方案 > 在输入中获取一个整数而不会遇到任何错误

问题描述

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

代码:

char *end;
char buf[LINE_MAX];

do {
     if (!fgets(buf, sizeof buf, stdin))
        break;

     // remove \n
     buf[strlen(buf) - 1] = 0;

     int n = strtol(buf, &end, 10);
} while (end != buf + strlen(buf));

编辑:

我根据@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;
    }
}

标签: cdebugginginputscanf

解决方案


发布的代码需要一些改进,但可以包装在一个函数中以读取一个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
    }
}

推荐阅读