【C语言】scanf 函数的使用

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;
}

运行结果:

循环读取多个整型元素

#include <stdio.h>

int main() {
    int a[5];
    for (int i = 0; i < 5; ++i) { //循环读取多个整型元素
        scanf("%d",&a[i]);
    }
    for (int i = 0; i < 5; ++i) {
        printf("%-3d",a[i]);
    }
    printf("%c",'\n');
    return 0;
}

posted @   hzyuan  阅读(209)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2022-01-06 【算法】计数排序
2022-01-06 【java】比较器的使用

喜欢请打赏

扫描二维码打赏

支付宝打赏

点击右上角即可分享
微信分享提示