C語言中的scanf()和printf()函數

C語言中的輸入、輸出函數,在C++中一直使用cin、cout,對scanf和printf的使用不太熟悉,現做以下整理。


scanf()函數詳解

函數名:scanf
功能:執行格式化輸入
用法:int scanf(char *format,[argument,...]);
scanf()函數是通用終端格式化輸入函數,它從標準輸入設備(鍵盤)讀取輸入的信息。可以讀入任何固有類型的數據並自動把數值變換成適當的機內格式。
其調用格式爲:scanf(“<格式化字符串>”,<地址表>);
scanf()函數返回成功賦值的數據項數,出錯時則返回EOF;
其控制串由三類字符構成:
1、格式化說明符
2、空白符
3、非空白符

格式化說明符

格式化字符 說明
%a 讀入一個浮點值(僅C99有效)
%A 同上
%c 讀入一個字符
%d 讀入十進制整數
%i 讀入十進制,八進制,十六進制整數
%o 讀入八進制整數
%x 讀入十六進制整數
%X 同上
%c 讀入一個字符
%s 讀入一個字符串
%f 讀入一個浮點數
%F 同上
%e 同上
%E 同上
%g 同上
%G 同上
%p 讀入一個指針
%u 讀入一個無符號十進制整數
%n 至此已讀入值的等價字符數
%[] 掃描字符集合
%% 讀%符號

附加格式說明字符表

修飾符 說明
L/l長度修飾符 輸入“長”數據
h長度修飾符 輸入“短”數據
W整型常數 指定輸入數據所佔寬度
*星號 空讀一個數據
hh,ll 同上h、l,但僅對C99有效

空白字符

空白字符會使scanf()函數在讀操作中略去輸入中的一個或多個空白字符,空白符可以是space,tab,newline等等,直到第一個非空白符出現爲止。

非空白字符

一個非空白字符會使scanf()函數在讀入時剔除掉與這個非空白字符相同的字符。

實例詳解

問題一

例1

#include "stdio.h" 
int main(void) 
{ 
int a,b,c;
scanf("%d,%d,%d",&a,&b,&c);
printf("%d,%d,%d/n",a,b,c);
return 0;
}  

運行時按如下方式輸入三個值:
3□4□5 ↙(輸入a,b,c的值)
3,4,5 (printf輸出的a,b,c的值)
(1) &a、&b、&c中的&是地址運算符,分別獲得這三個變量的內存地址。
(2) “%d%d%d”是按十進值格式輸入三個數值。輸入時,在兩個數據之間可以用一個或多個空格、tab鍵、回車鍵分隔。
以下是合法輸入方式:
① 3□□4□□□□5↙
② 3↙
4□5↙
③ 3(tab鍵)4↙
5↙

例2

#include "stdio.h" 
int main(void) 
{ 
int a,b,c;
scanf("%d,%d,%d",&a,&b,&c);
printf("%d,%d,%d/n",a,b,c);
return 0;
}  

運行時按如下方式輸入三個值:
3,4,5 ↙(輸入a,b,c的值)
或者
3,□4,□5 ↙(輸入a,b,c的值)
3,□□□4,□5 ↙(輸入a,b,c的值)
……
都是合法的,但是”,”一定要跟在數字後面,如:
3□,4,□5 ↙就非法了,程序出錯。(解決方法與原因後面講)
再如:
1、sacnf()中的變量必須使用地址

int a, b;
scanf("%d%d",a,b); //錯誤
scanf("%d%d",&a,&b);

2、scanf()的格式控制串可以使用其它非空白字符,但在輸入時必須輸入這些字符。
例:
scanf("%d,%d",&a,&b);
輸入: 3,4 ↙(逗號與”%d,%d”中的逗號對應)
scanf("a=%d,b=%d",&a,&b);
輸入: a=3,b=4 ↙(”a=”,”b=”,逗號與”%d,%d”中的”a=”,”b=”及逗號對應)

3、在用”%c”輸入時,空格和“轉義字符”均作爲有效字符。
例:
scanf("%c%c%c",&c1,&c2,&c3);
輸入:a□b□c↙
結果:a→c1,□→c2,b→c3 (其餘被丟棄)

scanf()函數接收輸入數據時,遇以下情況結束一個數據的輸入:(不是結束該scanf()函數,scanf()函數僅在每一個數據域均有數據,並按回車後結束)。
① 遇空格、“回車”、“跳格”鍵。
② 遇寬度結束。
③ 遇非法輸入。

問題二

scanf()函數不能正確接受有空格的字符串?如: I love you!

#include <stdio.h>
int main()
{
    char str[80];

    scanf("%s",str);
    printf("%s",str);
    return 0;
}

輸入:I live you!
輸出:I
scanf()函數接收輸入數據時,遇以下情況結束一個數據的輸入:(不是結束該scanf函數,scanf函數僅在每一個數據域均有數據,並按回車後結束)。
① 遇空格、“回車”、“跳格”鍵。
② 遇寬度結束。
③ 遇非法輸入。
所以,上述程序並不能達到預期目的,scanf()掃描到”I”後面的空格就認爲對str的賦值結束,並忽略後面的”love you!”.這裏要注意是”love you!”還在鍵盤緩衝區(關於這個問題,網上我所見的說法都是如此,但是,我經過調試發現,其實這時緩衝區字符串首尾指針已經相等了,也就是說緩衝區清空了,scanf()函數應該只是掃描stdin流,這個殘存信息是在stdin中)。我們改動一下上面的程序來驗證一下:

#include <stdio.h>
int main()
{
    char str[80];
    char str1[80];
    char str2[80];

    scanf("%s",str);/*此處輸入:I love you! */
    printf("%s",str);
    sleep(5);/*這裏等待5秒,告訴你程序運行到什麼地方*/
    scanf("%s",str1);/*這兩句無需你再輸入,是對鍵盤盤緩衝區再掃描   */
    scanf("%s",str2);/*這兩句無需你再輸入,是對鍵盤盤緩衝區再掃描    */
    printf("/n%s",str1);
    printf("/n%s",str2);
    return 0;
}

輸入:I love you!
輸出:I
love
you!

問題三

鍵盤緩衝區殘餘信息問題

#include <stdio.h>
int main()
{
    int a;
    char c;
    do
    {
        scanf("%d",&a);
        scanf("%c",&c);
        printf("a=%d     c=%c/n",a,c);
        /*printf("c=%d/n",c);*/
    }while(c!='N');
}

scanf("%c",&c);這句不能正常接收字符,什麼原因呢?我們用printf("c=%d/n",c);將C用int表示出來,啓用printf("c=%d/n",c);這一句,看看scanf()函數賦給C到底是什麼,結果是 c=10 ,ASCII值爲10是什麼?換行即/n.對了,我們每擊打一下”Enter”鍵,向鍵盤緩衝區發去一個“回車”(/r),一個“換行”(/n),在這裏/r被scanf()函數處理掉,而/n被scanf()函數“錯誤”地賦給了c.
解決辦法:可以在兩個scanf()函數之後加個fflush(stdin);,還有加getch(); getchar();也可以,但是要視具體scanf()語句加那個,這裏就不分析了,讀者自己去摸索吧。但是加fflush(stdin);不管什麼情況都可行。

函數名: fflush
功 能: 清除一個流
用 法: int fflush(FILE *stream);

#include <stdio.h>
int main()
{
    int a;
    char c;
    do
    {
        scanf("%d",&a);
        fflush(stdin);
        scanf("%c",&c);
        fflush(stdin);
        printf("a=%d     c=%c/n",a,c);
    }while(c!='N');
}     

問題四

int main()
{
int a,b,c; /*計算a+b*/
scanf("%d,%d",&a,&b);
c=a+b;
printf("%d+%d=%d",a,b,c);
}

如上程序,如果正確輸入a,b的值,那麼沒什麼問題,但是,你不能保證使用者每一次都能正確輸入,一旦輸入了錯誤的類型,你的程序不是死鎖,就是得到一個錯誤的結果,呵呵,這可能所有人都遇到過的問題吧?
解決方法:scanf()函數執行成功時的返回值是成功讀取的變量數,也就是說,你這個scanf()函數有幾個變量,如果scanf()函數全部正常讀取,它就返回幾。但這裏還要注意另一個問題,如果輸入了非法數據,鍵盤緩衝區就可能還個有殘餘信息問題。
正確的例程:

#include <stdio.h>
int main()
{
int a,b,c; /*計算a+b*/
while(scanf("%d,%d",&a,&b)!=2)fflush(stdin);
c=a+b;
printf("%d+%d=%d",a,b,c);
}

printf()函數詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章