黑馬程式員--C語言基礎之--scanf函數

來源:互聯網
上載者:User

標籤:include   程式員   關鍵字   c語言   運算式   

------- IOS培訓期待與您交流! ----------

寫代碼的時候,我們可以看得出,幾乎每一個C程式都會包括輸入輸出。輸入輸出是程式中最基本的操作之一。C語言本身並不提供輸入輸出的語句,輸入輸出操作是由C標準函數庫中的函數來實現的。今天就先說說輸入:scanf函數。

scanf函數與printf函數一樣,都不是C語言的關鍵字,而只是函數庫的名字,它們被定義在stdio.h裡,因此在使用scanf函數時要加 上#include<stdio.h>。它是格式輸入函數,即按使用者指定的格式從鍵盤上把資料輸入到指定的變數之中,其關鍵字最末一個字母f 即為“格式”(format)之意。

scanf函數的一般形式:scanf(格式控制,地址表列)int scanf(char *format[,argument,...]);

“格式控制”的是用雙引號括起來 字串,稱“轉換控制字元串”,簡稱“格式字串”,它包含兩個資訊:

(1)、格式聲明:由%和格式字元組成,作用是將輸入的資料轉變為指定的格式後輸入,總是由%字元開始的;

(2)、一般字元:即是需要在輸出時原樣輸入的字元。

“地址表列”是由若干個地址組成的表列,可以是變數的地址,或字串首地址或運算式。

scanf()函數返回成功賦值的資料項目數,出錯時則返回EOF。

/*例:使用scanf函數輸入資料*/  #include<stdio.h>  void main()  {  int a,b,c;  printf("input a,b,c/n");  scanf("%d%d%d",&a,&b,&c);  printf("a=%d,b=%d,c=%d",a,b,c);}
  • 格式字元說明

%a,%A 讀入一個浮點值(僅C99有效) 

%c 讀入一個字元

%d 讀入十進位整數

%i 讀入十進位,八進位,十六進位整數

%o 讀入八進位整數

%x,%X 讀入十六進位整數

%s 讀入一個字串,遇空格、定位字元或分行符號結束

%f,%F,%e,%E,%g,%G 用來輸入實數,可以用小數形式或指數形式輸入

%p 讀入一個指標

%u 讀入一個無符號十進位整數

%n 至此已讀入值的等價字元數

%[] 掃描字元集合

%% 讀%符號

附加格式說明字元表修飾符說明 

L/l 長度修飾符 輸入"長"資料

h 長度修飾符 輸入"短"資料

W 整型常數 指定輸入資料所佔寬度

* 表示本輸入項在讀入後不賦值給相應的變數

  • scanf的傳回值

scanf的傳回值有後面的參數決定

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

(1)如果a和b都被成功讀入,那麼scanf的傳回值就是2

(2)如果只有a被成功讀入,傳回值為1

(3)如果a和b都未被成功讀入,傳回值為0

(4)如果遇到錯誤或遇到end of file,傳回值為EOF,且傳回值為int型.

  • 使用scanf函數時應該注意的問題

(1)sacnf()中的變數必須使用地址 
(2)scanf()的格式控制串可以使用其它非空白字元,但在輸入時必須輸入這些字元
(3)在用"%c"輸入時,空格和“逸出字元”均作為有效字元

下面讓我們來舉例說明一下scanf函數的具體使用以及使用過程中遇到的一些問題:

/*問題一:scanf()函數不能正確接受有空格的字串?如: I love you!*/#include <stdio.h>int main(){   char str[80];  scanf("%s",str);  printf("%s",str);   return 0;}

scanf()函數接收輸入資料時,遇以下情況結束一個資料的輸入:(不是結束該scanf函數,scanf函數僅在每一個資料域均有資料,並按斷行符號後結束)。
(1)遇空格、“斷行符號”、“跳格”鍵

(2)遇寬度結束

(3)遇非法輸入

因 此,上述程式並不能達到預期目的,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!

現在原因知道了,那麼scanf()函數能不能完成這個任務?回答是:能!別忘了scanf()函數還有一個 %[] 格式控制符(如果對%[]不瞭解的請查看本文的上篇),請看下面的程式:

#include "stdio.h"int main(){  char string[50];/*scanf("%s",string);不能接收空格符*/  scanf("%[^/n]",string);  printf("%s/n",string);  return 0;}

此時程式就行正確的輸出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);不管什麼情況 都可行。

#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‘);}

這裡再給一個用“空格符”來處理緩衝區殘餘資訊的樣本:運行出錯的程式:

#include <stdio.h>int main(){  int i;  char j;  for(i = 0;i < 10;i++)  {  scanf("%c",&j);/*這裡%前沒有空格*/  }}

使用了空格控制符後:

#include <stdio.h>int main(){  int i;  char j;  for(i = 0;i < 10;i++)  {  scanf(" %c",&j);/*注意這裡%前有個空格*/  }}

可以運行看看兩個程式有什麼不同哦~~

/*問題三: 如何處理scanf()函數誤輸入造成程式死結或出錯?*/#include <stdio.h>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);}

補充: fflush(stdin)這個方法在GCC下不可用。(在VC6.0下可以),以下是 C99 對 fflush 函數的定義:

int fflush(FILE *stream);

如果stream指向輸出資料流或者更新流(update stream),並且這個更新流最近執行的操作不是輸入,那麼fflush函數將把任何未被寫入的資料寫入stream指向的檔案(如標準輸出檔案stdout)。否則,fflush函數的行為是不確定的。fflush(NULL)清空所有輸出資料流和上面提到的更新流。如果發生寫錯誤,fflush函數會給那些流打上錯誤標記,並且返回EOF,否則返回0。由此可知,如果 stream 指向輸入資料流(如 stdin),那麼 fflush 函數的行為是不確定的。故而使用fflush(stdin) 是不正確的,至少是移植性不好的。可採用如下方法:

/* 此函數可以和scanf函數一起使用,但使用%c輸入時要注意,即此函數只能用於緩衝區非空的情況 */void flush() {  char c;  while ((c=getchar()) != ‘/n‘&&c!=EOF) ;  }  #include <stdio.h>  int main()  {  int a,b,c; /*計算a+b*/  while(scanf("%d,%d",&a,&b)!=2) flush();  c=a+b;  printf("%d+%d=%d",a,b,c);}

黑馬程式員--C語言基礎之--scanf函數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.