3.2 數(shù)據(jù)的輸入和輸出
將數(shù)據(jù)通過計算機外部設(shè)備送到計算機內(nèi)存中的操作稱為輸入,反之,將數(shù)據(jù)從計算機內(nèi)存送到計算機外部設(shè)備的操作稱為輸出。
首先說明,C語言本身不提供輸入/輸出語句,它的輸入/輸出操作都是通過調(diào)用C語言系統(tǒng)提供的輸入/輸出標(biāo)準(zhǔn)函數(shù)來實現(xiàn)的。這些輸入/輸出標(biāo)準(zhǔn)函數(shù)被存放在標(biāo)準(zhǔn)函數(shù)庫中,如果要使用這些輸入/輸出函數(shù),必須要求在源程序的開始包含預(yù)處理命令:#include "stdio.h"(關(guān)于C語言的預(yù)處理功能詳見第7章)。在這里,系統(tǒng)默認的標(biāo)準(zhǔn)輸入/輸出設(shè)備是鍵盤和顯示器。
本節(jié)主要介紹兩類常用的標(biāo)準(zhǔn)輸入/輸出函數(shù):一類是用于單個字符的輸入/輸出函數(shù)getchar( )和putchar( ),另一類是用于格式輸入/輸出的函數(shù)scanf( )和printf( ),其中最后一個字符f是format的縮寫,即格式的意思。
3.2.1 字符輸入函數(shù)getchar( )
getchar( )函數(shù)調(diào)用的一般形式為:
getchar( )
該函數(shù)的功能是從標(biāo)準(zhǔn)輸入設(shè)備(鍵盤)上輸入一個字符,按回車鍵后,getchar( )將接收該字符作為函數(shù)的值。通常將getchar( )函數(shù)得到的值通過賦值運算符賦給某個字符型變量。
例如:
char ch;
ch=getchar( );
ch++;
當(dāng)程序執(zhí)行到“ch=getchar( );”語句時,程序會暫停,等待用戶從鍵盤輸入一個字符,然后繼續(xù)執(zhí)行后面的語句。
注意:getchar( )只能接收一個字符,而且只有在用戶按回車鍵<Enter>后,讀入才開始執(zhí)行。
3.2.2 字符輸出函數(shù)putchar( )
putchar( )函數(shù)調(diào)用的一般形式為:
putchar(ch)
函數(shù)的功能是向標(biāo)準(zhǔn)輸出設(shè)備(顯示器)輸出一個字符(即ch的值),其中,ch可以是字符型常量、變量或整型變量。
【例3.1】 字符輸出函數(shù)示例。
#include "stdio.h"
main( )
{
char a,b,c;
a='T';b='e';c='a';
putchar(a);putchar(b);putchar(c);
}
程序運行結(jié)果為:
Tea
putchar( )函數(shù)也可以輸出轉(zhuǎn)義字符,例如,putchar('\n') 輸出一個換行符。如果將例3.1中程序的最后一行改為:
putchar(a);putchar (b);putchar ('\n'); putchar (c);
則輸出結(jié)果為:
Te
a
還可以輸出其他轉(zhuǎn)義字符,例如:
putchar('\102'); /* 輸出字符“B” */
putchar('\"); /* 輸出單引號字符“ ' ” */
putchar('\015'); /* 輸出回車,不換行 */
【例3.2】 從鍵盤輸入一個字符并顯示該字符。
#include "stdio.h"
main( )
{
char ch;
ch=getchar( );
putchar(ch);
}
該程序在運行到“ch=getchar( );”語句時會暫停下來,等待用戶從鍵盤上輸入一個字符。如果用戶從鍵盤輸入字符“c”并按回車鍵(用<Enter>表示回車鍵),就會在屏幕上看到字符c。執(zhí)行情況如下:
c <Enter>
c
注意:getchar( )函數(shù)得到的字符可以賦給一個整型變量或字符型變量,也可以不賦給任何變量而作為表達式的一部分。例如,可以將例3.2程序中的第5行和第6行用下面的語句代替:
putchar(getchar( ));
3.2.3 格式輸出函數(shù)printf( )
putchar( )函數(shù)只能輸出單個字符。如果用戶在程序中需要輸出若干個任意類型的數(shù)據(jù),就要使用在前面章節(jié)中用到的格式輸出函數(shù)printf( )來實現(xiàn)。printf( )函數(shù)在整個C語言程序設(shè)計中應(yīng)用非常廣泛,希望讀者能夠很好地掌握。
1.printf( )函數(shù)調(diào)用的一般形式
printf( )函數(shù)調(diào)用的一般形式如下:
printf("控制字符串",輸出項列表)
printf( )函數(shù)的功能是,按控制字符串規(guī)定的輸出格式,將輸出項列表中的各輸出項的值依次輸出到系統(tǒng)指定的標(biāo)準(zhǔn)輸出設(shè)備(顯示器)上。
下面分別介紹printf( )函數(shù)中各參數(shù)的含義。
(1)控制字符串
控制字符串是用雙引號括起來的字符串,也稱轉(zhuǎn)換控制字符串,它可以包含以下兩種信息。
① 格式說明
格式說明由“%”和跟隨其后的一個格式字符組成。它的作用是將要輸出的數(shù)據(jù)轉(zhuǎn)換為指定的格式輸出。格式說明總是由“%”字符開始,以一個格式字符作為結(jié)束,對不同類型的數(shù)據(jù)應(yīng)使用不同的格式字符控制其輸出格式。C語言提供的格式字符及其功能如表3.1所示。
表3.1 printf( )格式字符及其功能
%[+][-][0][#][m.n][l]格式字符;
附加格式說明符及其功能如表3.2所示。
表3.2 printf( )附加格式說明字符及其功能
普通字符是需要原樣輸出的字符,它包含可打印的字符和不可打印的字符。可打印的字符在“控制字符串”中直接用字符符號表示,如a、b等;不可打印的字符用轉(zhuǎn)義字符表示,如換行'\n',橫向跳格'\t',響鈴'\a'等。
(2)輸出項列表
輸出項列表是需要輸出的一些數(shù)據(jù),可以是一個或者多個輸出項。當(dāng)有多個輸出項時,各輸出項之間用逗號“,”隔開。輸出項可以是常量、變量或表達式。輸出項與控制字符串中的格式說明從左到右在類型上必須一一對應(yīng)匹配。如果不匹配將導(dǎo)致數(shù)據(jù)不能正確輸出。另外,輸出項的個數(shù)與控制字符串中格式說明的個數(shù)應(yīng)該相同。如果輸出項的個數(shù)多于格式說明的個數(shù),則多余的輸出項不輸出;如果輸出項的個數(shù)少于格式說明的個數(shù),則對于多余的格式說明將輸出不定值(或0值)。
2.printf( )函數(shù)的調(diào)用
printf( )函數(shù)的調(diào)用可分為以下3種情況。
(1)控制字符串中只有普通字符
此時控制字符串中沒有格式說明,也就沒有輸出項列表這一部分參數(shù),其結(jié)果是將該字符串原樣顯示。例如,下面的程序段:
printf("What is your name? \n");
printf("My name is Li li. \n");
該程序段執(zhí)行后,屏幕顯示:
What is your name?
My name is Li li.
這兩個printf語句的最后都有一個轉(zhuǎn)義字符“\n”,表示回車換行。其他的則是格式字符串中的普通字符,原樣輸出。
(2)控制字符串中只有格式說明
此時控制字符串中沒有普通字符,只含有格式說明,因此需要有輸出項列表這一部分參數(shù)。表3.3列舉了常用格式字符的各種輸出結(jié)果。
表3.3 printf( )函數(shù)的調(diào)用示例
(3)控制字符串中既有格式說明又有普通字符
將二者混合使用可使輸出結(jié)果更清楚,所以是經(jīng)常采用的一種形式。
【例3.3】 格式輸出函數(shù)示例
#include "stdio.h"
main( )
{
int a=5,b=8;
printf("%d%d%d\n",a,b,a+b);
printf("%d %d %d\n",a,b,a+b);
printf("%d,%d,%d\n",a,b,a+b);
printf("a=%d,b=%d,a+b=%d\n",a,b,a+b);
}
程序運行結(jié)果如下:
5813
5 8 13
5,8,13
a=5,b=8,a+b=13
特別強調(diào)的是,用printf( )函數(shù)輸出時,注意輸出的數(shù)據(jù)類型應(yīng)與上述格式說明匹配,否則將會出現(xiàn)錯誤。
另外,如果希望輸出字符“%”,使用特殊格式說明“%%”。例如:
printf("%d%%\n",10);
執(zhí)行后將輸出:
10%
3.2.4 格式輸入函數(shù)scanf( )
1.scanf( )函數(shù)調(diào)用的一般形式
scanf( )函數(shù)調(diào)用的一般形式為:
scanf (“控制字符串”,輸入項地址列表)
scanf( )函數(shù)的功能是,按控制字符串規(guī)定的輸入格式,從系統(tǒng)指定的標(biāo)準(zhǔn)輸入設(shè)備(鍵盤)上將輸入的數(shù)據(jù)依次存到輸入項地址列表所指定的內(nèi)存單元中。
其中,輸入項地址列表是由若干個地址組成的列表,可以是變量的地址或字符串的首地址等。若為多項,各項之間用逗號隔開??刂谱址暮x與printf( )函數(shù)類似,它規(guī)定了輸入數(shù)據(jù)的輸入格式。它可以包含以下兩種信息。
(1)格式說明
與printf( )函數(shù)中的格式說明類似,scanf( )函數(shù)的格式說明也是以“%”開始,以一個格式字符結(jié)束的,中間可以插入附加格式說明符。表3.4中列出了scanf( )函數(shù)用到的格式字符,表3.5列出了scanf( )函數(shù)可以使用的附加說明符(修飾符)。
表3.4 scanf( )格式字符
表3.5 scanf( )附加的格式說明符
普通字符在輸入數(shù)據(jù)時要求原樣輸入相同的字符。
說明:
① 在VC環(huán)境下,輸入long整型數(shù)據(jù)時,在“%”和“d” 之間必須加字母“l(fā)”;輸入double型數(shù)據(jù)時,在“%”和“f(e)”之間也必須加“l(fā)”,否則得不到正確的數(shù)據(jù)。
② 當(dāng)指定輸入數(shù)據(jù)所占的寬度m時,系統(tǒng)自動按寬度m截取所需數(shù)據(jù),但不能對實型數(shù)據(jù)指定小數(shù)位的寬度。例如:
scanf ("%6.3f",&a );
是不合法的,不能企圖輸入以下信息而使a的值為123.456:
123456<Enter>
③ 輸入項與控制字符串中的格式說明從左到右在類型上必須一一對應(yīng)匹配,如果不匹配將得不到正確的數(shù)據(jù)。另外,輸入項的個數(shù)與控制字符串中格式說明的個數(shù)應(yīng)該相同。如果輸入項的個數(shù)多于格式說明的個數(shù)時,scanf( )函數(shù)結(jié)束輸入,多余的輸入項不會從鍵盤接收到新的數(shù)據(jù);如果輸入項的個數(shù)少于格式說明的個數(shù),則scanf( )函數(shù)同樣結(jié)束輸入。
④ 在輸入數(shù)據(jù)時,遇到下列情況之一時認為該數(shù)據(jù)結(jié)束:
● 空格符(空格鍵)、制表符(Tab鍵)或回車符(回車鍵);
● 寬度結(jié)束,如“%2d”,則只取兩列;
● 非法輸入。
當(dāng)輸入的數(shù)據(jù)少于輸入項的個數(shù)時,程序等待輸入,直到輸入的數(shù)據(jù)個數(shù)與輸入項的個數(shù)相同為止;當(dāng)輸入的數(shù)據(jù)多于輸入項的個數(shù)時,多于的數(shù)據(jù)將留作下一個輸入函數(shù)的輸入數(shù)據(jù)。
⑤ 在用“%c”格式輸入字符時,空格符、制表符、回車符、轉(zhuǎn)義字符等都是有效字符。但是,如果在格式說明之間加入了空格,這時輸入字符中的空格符、制表符和回車符都將作為間隔符。
2.scanf( )函數(shù)的調(diào)用
scanf( )函數(shù)的調(diào)用將通過下面的例題來進一步講解。
【例3.4】 格式輸入函數(shù)示例。
#include "stdio.h"
main( )
{
int a,b; char c;
scanf("%d%c%d",&a,&c,&b);
printf("%d,%d,%c\n",a,b,c);
}
程序運行結(jié)果如下:
輸入:33a66<Enter> (輸入a、c、b的值)
輸出:33,66,a (輸出a、b、c的值)
其中,&a、&b、&c中的&是取地址運算符。&a的含義是a在內(nèi)存中的地址。例3.4中scanf( )函數(shù)的作用是,將從鍵盤上輸入的3個數(shù)據(jù)33、66、a存入系統(tǒng)為變量a、b、c分配的內(nèi)存單元中,如圖3.1所示。第一個數(shù)據(jù)對應(yīng)格式%d輸入22之后遇字母a,因此認為數(shù)值22后已沒有數(shù)字了,第1個數(shù)據(jù)到此結(jié)束,把22賦給變量a;第2個數(shù)據(jù)對應(yīng)格式%c,因此將字符a賦給變量c;第3個數(shù)據(jù)66后面是回車鍵,認為此數(shù)值到此結(jié)束,則將66賦給變量b。
表3.6中列舉了常用格式字符的各種輸入形式及變量獲得的值。
表3.6 scanf( )函數(shù)的調(diào)用示例
注意:當(dāng)調(diào)用scanf( )函數(shù)從鍵盤輸入數(shù)據(jù)時,最后一定要按下回車鍵,scanf( )函數(shù)才開始接收從鍵盤上輸入的數(shù)據(jù)。scanf( )函數(shù)中的第二部分參數(shù)(即輸入項地址表列)應(yīng)當(dāng)是變量的地址,而不應(yīng)是變量名。例如:
int a,b;
scanf ("%d,%d",a,b );
是錯誤的,應(yīng)將“a,b”改為“&a,&b”。這是初學(xué)者常犯的錯誤!