C

C 知识量:16 - 74 - 317

4.4 scanf()函数><

使用scanf()函数- 4.4.1 -

scanf()函数是C语言中常用的输入函数,它可以读取不同格式的数据。当然,从键盘上输入的都是文本,比如:字母、数字、标点符号等等。而将这些文本转换成整数、浮点数、字符或字符串,进而用于程序计算和存储,这就是scanf()函数的工作了。printf()函数与scanf()函数的功能正好相反,printf()函数会把整数、浮点数、字符或字符串转换成能够在屏幕上显示的文本。

scanf()函数和printf()函数都使用格式字符串和参数列表,区别在于参数列表中,printf()函数使用变量、常量和表达式,而scanf()函数使用指向变量的指针。使用scanf()函数时需要注意:

  • 如果读取基本变量类型的值,要在变量名前加一个&。

  • 如果把字符串读入字符数组中,就不要使用&。

下面是一个使用scanf()函数的示例:

#include <stdio.h>

int main(void) {
    char name[20];
    int age;
    float height;

    printf("Please input your name , age and height.\n");
    scanf("%s", name);
    scanf("%d %f", &age, &height);
    printf("\nHello %s,your age is %d and your height is %.2f", name, age, height);
    system("pause");
    return 0;
}

运行结果为:

Please input your name , age and height.
Jam
33 176.6521

Hello Jam,your age is 33 and your height is 176.65

注意:scanf()函数使用空白(换行符、制表符和空格)把输入分成多个字段,只要在每个输入项之间输入至少一个换行符、制表符或空格即可,每个scanf()函数的输入使用一个回车结束。

scanf()函数的转换说明及修饰符- 4.4.2 -

scanf()函数的转换说明与printf()函数的几乎相同,区别在于:对float和double类型,printf()使用%f、%e、%E、%g和%G转换说明,而scanf()只把它们用于float类型,对于double类型要使用l修饰符。

scanf()函数的转换说明如下:

转换说明含义
%c把输入解释成字符。
%d把输入解释成有符号十进制整数。
%e、%f、%g、%a把输入解释成浮点数。
%E、%F、%G、%A把输入解释成浮点数。
%i把输入解释成有符号十进制整数。
%o把输入解释成有符号八进制整数。
%p把输入解释成指针(地址)。
%s把输入解释成字符串。(注意:从第一个非空白字符到下一个空白字符之间所有字符都是输入)
%u把输入解释成无符号十进制整数。
%x、%X把输入解释成有符号十六进制整数。

可以在转换说明中(百分号与转换字符之间)使用修饰符,但必须按照下表所列顺序书写:

转换说明含义
*抑制赋值。例如:%*d
数字最大字段宽度。输入达到最大字段宽度处,或第1次遇到空白字符时停止。例如:%10s
hh把整数作为signed char或unsigned char类型读取。例如:%hhd
ll把整数作为long long或unsigned long long类型读取。例如:%lld
h、l或L
  • %hd和%hi表明把对应的值存储为short int类型。

  • %ho、%hx和%hu表明把对应的值存储为unsigned short int类型。

  • %ld和%li表明把对应的值存储为long类型。

  • %lo、%lx和%lu表明把对应的值存储为unsigned long类型。

  • %le、%lf和%lg表明把对应的值存储为double类型。

  • 在e、f和g前面使用L而不是l,表明把对应的值存储为long double类型。

  • 如果没有修饰符,d、i、o和x表明把对应的值存储为int类型,f和g表明把对应的值存储为float类型。

j在整型转换说明后面时,表明使用intmax_t或uintmax_t类型。例如:%zd
z在整型转换说明后面时,表明使用sizeof的返回类型。
t在整型转换说明后面时,表明使用表示两个指针差值的类型。例如:%td

scanf()函数读取操作细节- 4.4.3 -

关于scanf()函数读取数据的细节问题以一个例子来说明。假设以%d转换说明来读取一个整数:

  • scanf()函数总是以一个非空白字符开始读取数据。所以,每次读取一个字符,都会跳过所有空白字符,直到遇到第1个非空白字符才正式开始读取。

  • 如果遇到一个数字或符号(+或-),便保存该字符,并继续读下一个字符。

  • 如果下一个也是数字,便保存并继续读取。

  • scanf()函数不断的读取,直至遇到非数字字符,便认为读到了整数的末尾。

  • scanf()函数会把非数字字符放回输入,因此,下一次读取操作将从本次放回的非数字字符开始。

  • scanf()函数计算已读取的数字(包括符号)相应的数值,并将计算结果放入指定的变量中。

需要进一步说明的是:

  • 如果使用了字段宽度,scanf()函数会在字段结尾或第1个空白字符处停止读取(满足两个条件之一便停止)。

  • 如果输入的第一个就是非数字字符,那么scanf()函数会把这个非数字字符放回输入。如果只使用%d转换说明,那么scanf()函数将一直停留在此处,而无法越过非数字字符去读取下一个字符。

  • 如果使用带多个转换说明的scanf()函数,scanf()函数将在第1个出错处停止读取输入。

对于其他转换说明:

  • %x转换说明要求scanf()函数识别十六进制数a~f和A~F。

  • 浮点转换说明要求scanf()函数识别小数点、e记数法(指数记数法)和p记数法(十六进制指数记数法)。

  • %s转换说明要求scanf()函数识别除空白以外的所有字符。scanf()函数从第1个非空白字符开始读取,保存非空白字符直到再次遇到空白。因此,可以使用scanf()函数读取一个英文单词,但是无法通过设置字段宽度等手段,读取多个单词(或英文句子)。scanf()函数将字符串放入指定数组中时,会在字符数组末尾加上“\0”,表示这是一个字符串。

格式字符串中的普通字符- 4.4.4 -

可以将普通字符放在scanf()函数的格式字符串中,但是,除了空格字符外的普通字符必须与输入字符串严格匹配。例如对于scanf("%d,%d",&a,&b),在输入时,两个数字之间必须以逗号(,)分割,否则就会出错。

除了%c外,其他转换说明都会自动跳过待输入值前面所有的空白。因此,对于scanf("%d,%d",&a,&b),在输入的数字和用于分割的逗号之间加入空格是没问题的。

scanf()函数的返回值- 4.4.5 -

scanf()函数返回成功读取的项数。如果没有读取任何项,且如果需要读取一个数字,而用户却输入了一个非数字字符串,scanf()函数将返回0。当scanf()函数读取到“文件结尾”时,会返回EOF。EOF是stdio.h中定义的特殊值,通常用#define指令定义为-1。

#include <stdio.h>

int main(void) {
    char name[20];
    int remember;

    printf("Please input your name.\n");
    remember = scanf("%s", name);
    printf("Return value is %d", remember);
    system("pause");
    return 0;
}

运行结果为:

Please input your name.
James
Return value is 1