2.4 输入输出对象

在C语言中,输入与输出功能是通过调用标准库函数中的函数来实现的。在函数库中包含一系列标准输入输出函数,有格式化输入输出函数:“printf”,“scanf”;字符输入输出函数:“putchar”,“getchar”;字符串输入输出函数:“puts”,“gets”。

2.4.1 格式化输入函数

scanf()函数的作用是从输入设备输入若干个任意类型的数据。它的函数原型在头文件<stdio.h>中,C语言是允许在使用scanf()函数之前不包含<stdio.h>文件。scanf()函数最末一个字母f即为“格式”(format)之意。

1.scanf()函数的调用格式

scanf()函数是C语言提供的标准格式输入函数,用来按照指定的格式输入数据并保存到指定变量的存储地址中去。scanf()函数调用的一般形式为:

    scanf ("格式控制字符串",地址列表);

例如:

    scanf("%d %c", &a,&b);

该函数主要有如下两个参数:

(1)格式控制字符串:用来指定每个输入项的输入格式。格式控制字符串通常由“%”和格式字符组成,如%d、%c、%f等。它的作用是确定输入数据的格式,格式说明都是由“%”字符开头的。

(2)地址列表:地址列表给出各变量的地址。地址是由地址运算符“&”后跟变量名组成的,例如,&a表示变量a在内存中的地址,其中&是取地址运算符,其作用是求变量的地址。

其地址列表的个数必须与格式字符串中规定字符的个数一样多,各地址之间用“,”分开,且顺序必须一一对应,否则将会出现意想不到的错误信息提示,并且各变量前必须加上“&”,用于指向各变量在内存中的地址。

提示

区分变量的值和变量的地址这两个不同的概念。变量的地址是由C编译系统分配的。用户不必深究具体的地址是多少。

在赋值表达式中给变量赋值,例如:

    a=1;

则变量的地址与变量值的关系如下所示:a为变量名,1是变量的值,&a是变量a的地址。

在赋值号左边是变量名,不能写地址。而scanf()函数本质上也属于给变量赋值,但要求必须写变量的地址,如:&a。两者在形式上略有不同。“&”是一个取地址运算符,&a是一个表达式,其作用是求变量的地址。

2.scanf()函数的格式控制符

scanf()函数的格式控制符中也可以有多种规定字符,常见格式控制符如表2-1所示。

表2-1 scanf()函数的格式控制符

3.scanf()函数格式控制的注意事项

scanf()函数格式控制可表示为:

    %[*][宽度][长度]类型

其中“[]”中为可省略项,其余各项的意义如下:

(1)符号“*”用于表示输入项在录入后被跳过,不赋予相应的变量。

例如,读入整型变量a,b的值,在输入时跳过第二个录入值:

    scanf("%d%*d%d",&a,&b);

假设输入2,3,4,则2被赋予变量a,3被跳过,4被赋予变量b。

【例2-2】编写一段程序,读入整型变量a,b的值,在输入时跳过第二个录入值。(源代码\ch02\2-2)

    #include<stdio.h>
    int main()
    {
    int a,b,c;
    printf("请输入三个数:\n");
    scanf("%d %*d %d",&a,&b,&c);
    printf("a=%d b=%d c=%d\n",a,b,c);
    return 0;
    }

运行上述程序,结果如图2-2所示。

图2-2 “*”的使用

【代码解析】

本例用于演示格式控制的不同情况。输入三个数据4,5,6。打印出来会发现,4被赋予变量a,5被跳过,6被赋予变量b,c就是一段杂乱的数据,没有任何意义。

(2)用于指定所录入的数据宽度,它的书写形式为“%n类型”,表示录入一个宽度为n的数据,若输入的数据宽度大于n,则保留n位数据,其余舍去。

例如,输入长度为3的整型数据:

    scanf("%3d",&a);

假设输入123456,则实际将123赋予变量a,456被舍去。

例如,输入2个长度为3的整型数据:

    scanf("%3d%3d",&a, &b);

假设输入123456,则实际将123赋予变量a,将456赋予变量b。

【例2-3】编写一段程序,通过scanf()读入一串数字,查看打印结果。(源代码\ch02\2-3)

    #include<stdio.h>
    int main()
    {
    int a,b;
    printf("请输入一串数字:\n");
    scanf("%3d  %2d",&a,&b);
    printf("a=%d b=%d\n",a,b);
    return 0;
    }

运行上述程序,结果如图2-3所示。

图2-3 “%n类型”的使用

【代码解析】

本例用于演示通过scanf()输入函数录入数据,并通过格式控制字符串控制输入的数据格式。“%3d”就是将123赋予变量a,“%2d”将45赋予变量b,67则被舍去。

(3)长度

通常使用字母“l”与字母“h”表示长度格式符,其中字母“l”表示输入长整型数据,如“%ld”“%lo”“%lx”“%lu”,以及double型数据,如“%lf”“%le”;字母“h”表示输入短整型数据,如“%hd”“%ho”“%hx”。

注意:

  • scanf()函数中的“地址列表”输入的必须是地址,而不能是变量名。这也是C语言与其他高级语言的不同之处。

例如:

    scanf ("%d,% d",&a,&b );

不能将上述语句写成:

    scanf ("%d,%d",a,b);
  • scanf()函数中不支持精度控制。

例如:

    scanf("%3.14f",&x);

此语句是非法的,不能使用此语句输入小数。

  • 在“格式控制字符串”中除了格式说明符外,也允许非格式字符出现,但输入时在对应位置上也要输入这些非格式字符。

例如:

    scanf ("a=%d,b=%d",&a,&b);

则键盘输入时应输入:

    a=1,b=2;

看似起提示作用,但由于用户看不见程序中的a=和b=,所以实际起不到提示作用。应尽量不写,若需要加提示,在上一行加上“printf("a=,b=");”更好。

  • C源程序在编译时碰到空格键、Tab键、回车键或非法数据时即认为该数据结束。

2.4.2 格式化输出函数

printf()函数的作用是向终端输出若干个任意类型的数据。它的函数原型在头文件<stdio.h>中,与格式输入函数scanf()相同,C语言中允许在使用printf()函数之前不包含<stdio.h>文件。

1.printf()函数的调用格式

格式化输出函数printf()主要是将标准输入流读入的数据向输出设备进行输出,它的语法形式如下:

    printf (格式控制字符串,输出列表);

该函数主要有如下两个参数:

(1)格式控制字符串:用来指定每个输出项的输出格式,格式控制字符串通常由格式说明、转义字符和普通字符组成。

① 普通字符:也称为非格式说明符,按原样输出字符。

例如:

    printf("a+b=%d\n",x);

其中,“a+b=”是非格式说明符,执行时按原样输出。

② 转义字符:是以“\”开头的字符,例如“\t”“\n”等。

③ 格式说明:由“%”和格式字符组成,例如%d、%c、%f等用来指定数据的输出格式。格式说明都是由“%”开头,以说明输出数据的类型、形式、长度、小数位数等。例如:

    "%d"   // 按十进制整型输出
    "%ld"  // 按十进制长整型输出
    "%c"   // 按字符型输出

(2)输出列表:是要输出的各项数据,这些数据可以是常量、变量、函数或表达式,其具体类型由格式控制符中的格式字符决定。输出列表的个数必须与格式控制字符串中规定的字符个数一样多,各参数之间用“,”分开,且顺序一一对应,否则将会出现意想不到的错误。

【例2-4】编写程序,输出代码中变量的值。(源代码\ch02\2-4)

    #include <stdio.h>
    int main()
    {
    int a=3,b=2,c;
    printf("a=%d,b=%d\n",a,b);
    printf("a=%d\n",a,b,c);
    printf("a=%d,b=%d,c=%d\n",a,b);
    printf("c=%d\n",c=a+b);
    printf("a=%d\n",a=a+2);
    return 0;
    }

运行上述程序,结果如图2-4所示。

图2-4 输出列表

【代码解析】

本例演示了printf()函数的输出列表。在代码中,第一个printf()函数中输出列表的个数与格式控制字符串中规定的字符个数一样多,所以正确地输出了两个变量a和b的值;第二个printf()函数中输出列表有三个变量a、b、c,格式控制字符串中却只有一个字符a,所以也只输出了一个变量a的值;第三个printf()函数由于缺少输出项,最后就会输出一段没有意义的数据;最后两个printf()函数的输出列表允许是表达式。

2.printf()函数的格式控制符

C语言提供的printf()函数中使用的格式控制符如表2-2所示。

表2-2 printf()函数的格式控制符

提示

使用格式字符时,除了X、E等有大写形式的,其余格式字符必须使用小写形式,否则会出现错误。

【例2-5】编写程序,分别定义int型、float型以及char型变量,使用相应的输出格式字符将它们输出。(源代码\ch02\2-5)

    #include <stdio.h>
    int main()
    {
    int x=5;            // 分别定义int、float以及char型变量
    float y=3.14;
    char c='w';
    printf("x=%d\n",x);  // 使用相应的格式字符输出
    printf("y=%f\n",y);
    printf("c=%c\n",c);
    return 0;
    }

运行上述程序,结果如图2-5所示。

图2-5 格式字符

【代码解析】

本例用于演示通过使用不同的格式字符,将相应类型的变量进行输出的操作。代码中首先定义了不同类型的变量,包括int、float以及char型,然后使用%d来输出int型变量数据;使用%f来输出float型变量数据;使用%c来输出char型变量数据。

3.printf()函数格式控制的注意事项

在输出函数printf()中,格式转换字符一般可以表示为:

    %[符号][宽度][.精度]格式字符

其中“[]”中为可省略项,其余各项的意义如下:

(1)通常输出数据都隐含右对齐,如果想实现左对齐,可以在格式控制中的“%”和宽度之间加一个符号“-”。

以输出字符串为例:

    printf("%-s","Hello");  // 输出字符串"Hello",并保持左对齐

其中“%-s”表示输出的字符串内容左对齐,若没有“-”符号则右对齐输出。

(2)宽度指的是域宽,也就是对应的输出项输出到设备上时所占的字符数。

以输出字符串为例:

    printf("%8s","Hello");  // 输出字符串长度5小于8,则左补3个空格
    printf("%2s","Hello");  // 输出字符串长度5大于2,则突破2的限制,全部输出

其中“%ms”表示输出的字符串共占m列,若输出的字符串长度大于m,则突破m限制,将字符串全部输出;若字符串长度小于m,则左补空格。

提示

“%0s”表示输出的字符串若有空位,则用数字“0”进行补位。

例如:

    printf("%08s","Hello");  // 表示右对齐输出长度5的"Hello",8为宽度,所以左补3个0

(3)精度用于说明所输出的实型数据的小数位数。它的书写格式为:“%.nf”,表示输出小数位数为n的实型数据。

例如:

    float a=5.4321;
    printf("%.3f\n",a);  // 输出float变量a,保留3为小数,则结果为5.432

提示

若将要输出的实数小数点后位数大于所要保留的小数位数,则通过四舍五入后保留;若将要输出的实数小数点后位数小于所要保留的小数位数,则缺位补0。

对于输出精度的情况,还有一种在格式字符前加字母“l”的表示方法:“%ld”,字母“l”的加入表示对于整型,则输出long型;对于实型,则输出double型。

例如:

    long a=54321;
    printf("%ld\n",a);  // 输出长整型变量a的值

【例2-6】编写程序,定义float型变量a=5.4321,定义long型变量b=12345678,通过格式控制,输出变量a保留3位小数的形式,输出长整型变量b,输出字符串“program”左端“pro”,并保持左对齐,而左端补空格。(源代码\ch02\2-6)

运行上述程序,结果如图2-6所示。

图2-6 格式控制

【代码解析】

本例用于演示格式控制的不同情况。首先定义float型变量a与long型变量b,使用精度控制输出变量a保留3位小数的形式,结果为5.432,可以发现是经过了四舍五入后的结果;使用“%ld”的形式输出变量b;而“%7.3s”表示右对齐输出内容,“7”表示输出宽度,“.3”表示精度3,在字符串中为截取左端3个字符,所以输出的结果为7个长度,右端为“pro”,左端补4个空格,并使用“|”符号来检验空格。

2.4.3 字符的输入函数

getchar()函数是字符输入函数,作用是从标准输入设备(键盘)上输入一个字符,在同一时间只能读取一个单一的字符。

getchar()函数的使用语法如下:

    getchar();

注意:

(1)使用getchar()函数输入时,都是转换为ASCII码值来存储,所以getchar()函数读取一个字符,返回的是一个整数。

(2)getchar()函数无参数,但括号不能省略。输入数字也必须按字符进行处理。当输入多个字符时,只能接收第一个字符。

而在编写C程序时,通常把输入的字符赋予一个字符变量,使其构成一个赋值语句,语法如下:

    char x ;         //定义字符变量x
    x = getchar( ); // 从键盘输入一个字符,然后将字符的值赋给变量x

提示

同putchar()函数一样,使用getchar()函数时,首先要添加头文件“#include <stdio.h>”。

【例2-7】编写程序,使用getchar()函数通过输入端输入一个字符,然后通过putchar()函数将此字符输出。(源代码\ch02\2-7)

    #include <stdio.h>
    int main()
    {
    char c;        // 定义字符变量
    printf("请输入一个字符:");
    c=getchar();  // 从键盘输入单个字符B给c字符变量
    putchar(c);    // 输出c字符变量的值
    putchar('\n');
    return 0;
    }

运行上述程序,结果如图2-7所示。

图2-7 getchar()函数

【代码解析】

本例用于演示如何使用getchar()函数输入一个字符。首先定义一个char型变量c,用于存放要输入的字符,然后通过printf()函数输出一行提示信息,接着使用getchar()函数,通过输入端输入一个字符并赋予变量c,然后通过putchar()函数输出变量c。

在使用getchar()函数时,如果需要连续地输入两个字符,那么在输入第二个字符前需要清除缓冲区,或者使用getchar()函数获取回车字符。

【例2-8】编写程序,使用getchar输入两个字符,然后再输出它们。(源代码\ch02\2-8)

运行上述程序,结果如图2-8所示。

图2-8 连续输入

【代码解析】

在本例中,如果需要连续输入两个或者更多字符时,需要在输入下一个字符前加上“getchar()”语句。“getchar()”语句是获取回车符,因为一般在输入字符后会按回车键确认,此时回车符就会被输入,而使用“getchar()”语句相当于将输入的回车符存入缓冲区,这样使得下一句的输入函数能够正常获取下一个字符。

2.4.4 字符的输出函数

putchar()函数是字符输出函数,作用是向标准输出设备(显示器)上输出一个字符,同一时间内只能输出一个单一的字符。

其语法格式如下:

    putchar(ch);

提示

其中的ch可以是常量、变量、转义字符或表达式等,其数据类型可以是字符型或整型,如果是整型数据,代表的是与一个字符相对应的ASCII码值。

例如:

    putchar('A');    // 输出大写字母A
    putchar('a');    // 输出小写字母a
    putchar(a);     // 输出字符变量a的值
    putchar('101'); // 转义字符,输出字符A
    putchar('\n');  // 转义字符,换行

注意:

(1)putchar函数只能用于单个字符的输出,且一次只能输出一个字符。

(2)在程序中使用putchar函数,务必牢记:在程序(或文件)的开头加上编译预处理命令(也称包含命令),即:#include <stdio.h>。

例如:

【例2-9】编写程序,要求使用putchar()函数输出字符串“New year”。(源代码\ch02\2-9)

运行上述程序,结果如图2-9所示。

图2-9 putchar()函数

【代码解析】

本例用于演示通过使用putchar()函数,将定义的字符变量输出,组成字符串。程序中首先定义字符变量ch1、ch2、ch3。然后分别为它们赋值,再通过使用putchar()函数将字符串补齐后将它们一一输出,使用putchar()函数输出字符时,如果没有特意输出换行转义符的话,每个字符是连续输出的。

2.4.5 字符串的输入函数

gets()函数是字符串输入函数,其作用是从输入流的缓冲区中读取字符到指定的数组,直到遇见换行符或者读到文件尾时停止。

注意:

(1)gets()函数可以直接输入字符串,并且只能输入字符串。scanf()函数是通过格式控制符“%s”输入字符串。

(2)gets()函数在读取字符串时会忽略掉所有前导空白符,而从字符串第一个非空白符读起。并且所读取的字符串将暂时存放于给定的string中。

gets()函数的使用语法如下:

    char *gets(char *string);

其中string为字符指针变量,是一个形式参数。gets()函数的返回值为char型,若读取成功返回string的指针,若失败则返回NULL。

【例2-10】编写程序,定义xchar型数组str1[]和str2[]用于存放输入的字符串,使用gets()函数读入一个字符串,然后使用printf()函数将该字符串输出。(源代码\ch02\2-10)

运行上述程序,结果如图2-10所示。

图2-10 get()函数

【代码解析】

本例演示了如何使用gets()函数从输入端读取一个字符串。代码中首先定义两个char型数组str1[]和str2[],注意这两个数组的长度为30,作为了解,数组所定义的长度意为该数组所能存储的数据上限。最后使用printf()函数将输入的字符串输出。

2.4.6 字符串的输出函数

puts()是字符串输出函数,该函数是向输出缓冲区中写入一个字符串,在字符串输出完毕后,紧跟着输出一个换行符“\n”。

提示

puts()函数可以直接输出字符串,并且只能输出字符串。printf()函数通过格式控制符“%s”输出字符串。

puts()函数的使用语法如下:

    int puts(char *string);

其中string为将要输出的字符串。输出成功后返回值为非0值,否则返回0。

【例2-11】编写程序,定义一个char型数组str[],并初始化为“My first C program”,使用puts()函数将字符串输出。(源代码\ch02\2-11)

    #include <stdio.h>
    int main()
    {
    char str[] = "My first C program";  // 定一个字符串数组
    printf("%s\n", str);                           // 通过变量输出
    printf("%s\n", "My first C program");          // 直接输出
    puts(str);                                     // 通过变量输出
    puts("My first C program");                    // 直接输出
    return 0;
    }

运行上述程序,结果如图2-11所示。

图2-11 puts()函数

【代码解析】

本例用于演示一个字符串的4种输出方式。代码中首先定义了一个char型数组str[],然后初始化str[]数组为“My first C program”。先使用printf()函数通过变量和直接输出的方式打印出数组str,再使用puts()函数通过变量和直接输出的方式打印出该数组。

通过对比发现,puts()函数与printf()函数的用法一样。但是puts()函数在输出字符串后会自动输出一个回车符“\n”,而printf()函数需要使用回车符“\n”才能实现换行。

提示

在printf()函数中使用%s输出字符串时,在变量列表中给出数组名即可,不能写为printf("%s",str[]);