C语言中,scanf 是常用的输入函数,但它在某些情况下可能不够灵活或容易导致问题。scanf 直接读取输入并试图将其解析成指定类型,如果输入格式不正确,scanf 会失败而不提供足够的反馈。可能导致缓冲区问题或错误的输入。scanf 会把输入保留在缓冲区中,如果没有适当地清除缓冲区,可能导致下一次输入出错。scanf 不可以灵活处理用户输入,尤其是在需要逐步处理输入时。

1、使用 fgets 和 sscanf

fgets 用于读取整行输入,并且能更好地控制缓冲区大小和输入格式。然后可以使用 sscanf 将读取的字符串转换成其他类型的数据。

#include <stdio.h>

int main() {
    char input[100];
    int number;

    // 使用 fgets 获取整行输入
    printf("请输入一个整数: ");
    if (fgets(input, sizeof(input), stdin)) {
        // 使用 sscanf 转换输入
        if (sscanf(input, "%d", &number) != 1) {
            printf("输入无效!\n");
        } else {
            printf("您输入的数字是: %d\n", number);
        }
    }

    return 0;
}

2、使用 getline (GNU 扩展)

getline 是 GNU 提供的一个更安全的输入函数,它可以动态调整缓冲区大小以适应用户输入。

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

int main() {
    char *line = NULL;
    size_t len = 0;
    ssize_t nread;
    int number;

    printf("请输入一个整数: ");
    // 使用 getline 获取整行输入
    nread = getline(&line, &len, stdin);
    if (nread == -1) {
        printf("读取输入失败!\n");
        free(line);
        return 1;
    }

    // 使用 sscanf 转换输入
    if (sscanf(line, "%d", &number) != 1) {
        printf("输入无效!\n");
    } else {
        printf("您输入的数字是: %d\n", number);
    }

    free(line);
    return 0;
}

3、使用 getchar (逐个字符输入)

如需要逐个字符处理输入,getchar 可以逐字符读取用户输入并进行处理。

#include <stdio.h>

int main() {
    int number = 0;
    char ch;

    printf("请输入一个整数: ");
    // 使用 getchar 逐字符读取输入
    while ((ch = getchar()) != '\n' && ch != EOF) {
        // 逐字符处理
        if (ch >= '0' && ch <= '9') {
            number = number * 10 + (ch - '0');
        } else {
            printf("输入无效!\n");
            return 1;
        }
    }

    printf("您输入的数字是: %d\n", number);
    return 0;
}

4、使用 scanf 的替代方法(手动清除缓冲区)

如仍然希望使用 scanf,可以在输入之后使用 fflush(stdin) 来清除缓冲区,尽管这并不被所有编译器支持。

#include <stdio.h>

int main() {
    int number;
    printf("请输入一个整数: ");
    
    if (scanf("%d", &number) != 1) {
        printf("输入无效!\n");
        fflush(stdin);  // 清除缓冲区(仅某些编译器支持)
    } else {
        printf("您输入的数字是: %d\n", number);
    }

    return 0;
}

推荐文档