【C语言】scanf 函数的使用

发布时间 2024-01-06 00:20:45作者: hzyuan

C语言通过 scanf 函数读取键盘输入,键盘输入又被称为标准输入(stdin)。
当 scanf 函数读取标准输入时,如果没有任何内容,那么 scanf 函数会被阻塞。

scanf 函数的声明:

#include <stdio.h>
int scanf(const char *format, ...);

scanf 函数根据给出的 format 格式将值读取到匹配的变量空间中。
返回的值的匹配成功的成员个数,中间有任何一个成员匹配出错,后面的成员都会匹配出错。

scanf 函数的原理

当我们使用 scanf 函数时,从键盘输入的一切数据,不管是数字、字母,还是空格、回车、Tab 等字符,都会被当作数据存入缓冲区。存储的顺序是先输入的排前面,后输入的依次往后排。按回车键的时候 scanf 开始进入缓冲区取数据,从前往后依次取。

#include <stdio.h>
//scanf 用来读取标准输入,scanf 是把标准输入内的内容放到某个变量空间里。因此变量必须取地址
//scanf 会阻塞,是因为标准输入缓冲区是空的
int main() {
    int i, ret;
    char c;
    float f;
    scanf("%d", &i); //&是取地址符
    printf("i=%d\n", i); //把标准缓冲区中的整型数据读走
//    fflush(stdin); //清空标准缓冲区
    scanf("%c", &c);
    printf("c=%c\n", c);
    scanf("%f", &f);
    printf("f=%f\n", f);
    return 0;
}

运行结果:

当我们输入 123 并按下回车时(按下回车时 scanf 函数才开始匹配),此时 stdin 中的内容是 "123\n",scanf 函数中的 %d 匹配整型数20,放入变量 i 中。
scanf 函数匹配一个字符时,会在 stdin 删除对应的字符。这时 '\n' 仍然在 stdin 内,如果第二个 scanf 函数为 scanf("%d, &i);,那么依然会发生阻塞,因为 scanf 函数在读取整型数、浮点数、字符串时,会忽略 '\n'、空格符等字符(忽略是指 scanf 函数执行时会首先删除这些字符,然后再阻塞)。
scanf 函数在读取字符时,不会忽略任何字符,所以 scanf("%c", &c); 读取了 stdin 中残留的 '\n',不发生阻塞。
在读取字符型数据前,通过 fflush(stdin); 清空缓冲区即可解决此问题。

【注意】在 scanf 函数中,所有的“非输入控制符”都要原样输入。所以对于scanf("i=%d", &i);,在输入时必须输入 i=123才正确。所以在 scanf 尽量不要加任何“非输入控制符”。

多种数据类型混合输入

从键盘输入数据同时给多个变量赋值时,值之间一定要用空格、回车或者 Tab 键隔开,用以区分是给不同变量赋的值。而且空格、回车或 Tab 键的数量不限,一般都使用一个空格。
当我们让 scanf 函数一次读取多种类型的数据时,必须要格外小心字符型数据。

#include <stdio.h>

int main() {
    int i, ret;
    char c;
    float f;

    ret = scanf("%d%c%f", &i, &c, &f);
    printf("i=%d, c=%c, f=%5.2f, ret=%d\n", i, c, f, ret);
    fflush(stdin);
    ret = scanf("%d %c%f", &i, &c, &f); //在%c之前加上空格解决字符型数据读取问题
    printf("i=%d, c=%c, f=%5.2f, ret=%d\n", i, c, f, ret);
    return 0;
}

运行结果: