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