%d 跟%i 的區別以及scanf和sscanf的用法
scanf 用%i能夠獲得8/16進位制的值,
比如0011就是9,0x11就是17,當然如果讀取到08或者09就會出錯了。
scanf簡介
scanf函式,與printf函式一樣,都被定義在裡,因此在使用scanf函式時要加上#include<stdio.h>。它是格式輸入函式,即按使用者指定的格式從鍵盤上把資料輸入到指定的變數之中,其關鍵字最末一個字母f即為“格式”(format)之意
scanf函式的一般形式scanf(格式控制,地址表列) int scanf(char *format[,argument,...]); “格式控制”的含義同printf函式;“地址表列”是由若干個地址組成的表列,可以是變數的地址,或字串的首地址。 scanf()函式返回成功賦值的資料項數,讀到檔案末尾出錯時則返回EOF。
- #include<stdio.h>
- void main()
- {
- int a,b,c;
- printf("please input a,b,c");
- scanf("%d,%d,%d",&a,&b,&c);
- printf("a=%d,b=%d,c=%d",a,b,c);
- }
#include<stdio.h> void main() { int a,b,c; printf("please input a,b,c"); scanf("%d,%d,%d",&a,&b,&c); printf("a=%d,b=%d,c=%d",a,b,c); }
在Dev-C++上執行程式為:
- #include<stdio.h>
- int main()
- {
- int a,b,c;
- printf("please input a,b,c");
- scanf("%d,%d,%d",&a,&b,&c);
- printf("a=%d,b=%d,c=%d",a,b,c);
- fflush(stdin);
- getchar();
- }
#include<stdio.h> int main() { int a,b,c; printf("please input a,b,c"); scanf("%d,%d,%d",&a,&b,&c); printf("a=%d,b=%d,c=%d",a,b,c); fflush(stdin); getchar(); }
注意上面的scanf("%d,%d,%d",&a,&b,&c);中%d,%d,%d之間有逗號,在輸入資料時也要加逗號,如果去掉逗號,輸入時就不用逗號,而用空格,tab鍵或回車鍵將各個資料隔開
格式字元說明%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); 如果a和b都被成功讀入,那麼scanf的返回值就是2 如果只有a被成功讀入,返回值為1 如果a和b都未被成功讀入,返回值為0 如果遇到錯誤或遇到end of file,返回值為EOF。 且返回值為int型.
使用scanf函式時應該注意的問題
1、scanf()中的變數必須使用地址。
2、scanf()的格式控制串可以使用其它非空白字元,但在輸入時必須輸入這些字元。
3、在用"%c"輸入時,空格和“轉義字元”均作為有效字元。
問題一
scanf()函式不能正確接受有空格的字串?如: I love you!
[cpp] view plain copy print?- #include <stdio.h>
- int main()
- {
- char str[80];
- scanf("%s",str);
- printf("%s",str);
- return 0;
- }
#include <stdio.h>
int main()
{
char str[80];
scanf("%s",str);
printf("%s",str);
return 0;
}
輸入:I love you! 輸出:scanf()函式接收輸入資料時,遇以下情況結束一個數據的輸入:(不是結束該scanf函式,scanf函式僅在每一個數據域均有資料,並按回車後結束)。 ① 遇空格、“回車”、“跳格”鍵。 ② 遇寬度結束。 ③ 遇非法輸入。 所以,上述程式並不能達到預期目的,scanf()掃描到"I"後面的空格就認為對str的賦值結束,並忽略後面的"love you!".這裡要注意是"love you!"還在鍵盤緩衝區(關於這個問題,網上我所見的說法都是如此,但是,我經過除錯發現,其實這時緩衝區字串首尾指標已經相等了,也就是說緩衝區清空了,scanf()函式應該只是掃描stdin流,這個殘存資訊是在stdin中)。我們改動一下上面的程式來驗證一下:
- #include <stdio.h>
- #include<windows.h>
- int main()
- {
- char str[80];
- char str1[80];
- char str2[80];
- scanf("%s",str);/*此處輸入:I love you! */
- printf("%s",str);
- Sleep(5000);/*這裡等待5秒,告訴你程式執行到什麼地方*//*不是sleep(5) 1,函式名是Sleep不是sleep。
- 2,C/C++中,unsigned Sleep(unsigned)應該是毫秒ms.
- scanf("%s",str1);/*這兩句無需你再輸入,是對鍵盤盤緩衝區再掃描 */
- scanf("%s",str2);/*這兩句無需你再輸入,是對鍵盤盤緩衝區再掃描 */
- printf("/n%s",str1);
- printf("/n%s",str2);
- return 0;
- }
#include <stdio.h>
#include<windows.h>
int main()
{
char str[80];
char str1[80];
char str2[80];
scanf("%s",str);/*此處輸入:I love you! */
printf("%s",str);
Sleep(5000);/*這裡等待5秒,告訴你程式執行到什麼地方*/ /*不是sleep(5) 1,函式名是Sleep不是sleep。
2,C/C++中,unsigned Sleep(unsigned)應該是毫秒ms.
scanf("%s",str1);/*這兩句無需你再輸入,是對鍵盤盤緩衝區再掃描 */
scanf("%s",str2);/*這兩句無需你再輸入,是對鍵盤盤緩衝區再掃描 */
printf("/n%s",str1);
printf("/n%s",str2);
return 0;
}
輸入:I love you! 輸出: 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;
- }
#include "stdio.h"
int main()
{
char string[50];/*scanf("%s",string);不能接收空格符*/
scanf("%[^/n]",string);
printf("%s/n",string);
return 0;
}
問題二
鍵盤緩衝區殘餘資訊問題
[cpp] view plain copy print?- #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');
- }
#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');
- }
#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);/*這裡%前沒有空格*/
}
}
使用了空格控制符後:
- #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()函式誤輸入造成程式死鎖或出錯?
[cpp] view plain copy print?- #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);
- }
#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);
- }
#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) ;
}
[cpp] view plain copy print?- #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);
- }
#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);
}
sscanf介紹
相關推薦
%d 跟%i 的區別以及scanf和sscanf的用法
scanf 用%i能夠獲得8/16進位制的值, 比如0011就是9,0x11就是17,當然如果讀取到08或者09就會出錯了。 scanf簡介 scanf函式,與printf函式一樣,都被定義在裡,因此在使用scanf函式時要加上#include<stdio.h>
普通集合和泛型集合的區別,哈希表和字典表的區別,隊列和堆棧的區別以及堆和棧的區別。
ear 釋放內存 main 廣泛 棧內存 節點 except {0} 常數 普通集合和泛型集合的區別: 泛型集合與傳統集合相比 類型更安全. 泛型集合無需裝箱拆箱操作. 泛型的重要性. 泛型是未來五年的主流技術 ...通常情況下,建議您使用泛型集合,因為這樣可以獲得類型安全
display和visibility的區別以及迴流和重繪
display:none會脫離文件流,不佔據頁面空間; visibility:hidden,只是隱藏內容,並沒有脫離文件流,會佔據頁面的空間。 講述迴流以及重繪之前需要先了解頁面在文件載入完成之後到完全顯示中間的過程: 1.根據文件生成DOM樹(包括display:none的節點) 2.在D
==和equals方法的區別以及Integer和String的應用
==和equals方法的區別以及Integer和String的應用 == 比較的是兩個物件的地址記憶體地址,而equals比較的是兩個物件的值。 例如String的equals比較方法,先呼叫==判斷是否相同,然後再判斷物件value的char陣列是否相同。 建議:比較兩個物件是否相
掛起和阻塞區別以及sleep和wait的區別
阻塞 VS 掛起 阻塞與掛起都是程序的狀態,但他們有一些相似之處,也有一些區別,下面先對他們進行概述,再進行比較 阻塞:正在執行的程序由於發生某時間(如I/O請求、申請緩衝區失敗等)暫時無法繼續執行。此時引起程序排程,OS把處理機分配給另一個就緒程序,而讓受阻程序處於暫停狀態,一般將這種狀態
dp,px,pt,sp 的區別 以及dp 和 px 互轉
dp = dip : device independent pixels(裝置獨立畫素). 不同裝置有不同的顯示效果,這個和裝置硬體有關,一般我們為了支援WVGA、HVGA和QVGA 推薦使用這個,不依賴畫素。px: pixels(畫素). 不同裝置顯示效果相同,一般我們H
runnable和thread的區別以及run和start的區別(多執行緒)
在java中可有兩種方式實現多執行緒,一種是繼承Thread類,一種是實現Runnable介面;Thread類是在java.lang包中定義的。一個類只要繼承了Thread類同時覆寫了本類中的run()方法就可以實現多執行緒操作了,但是一個類只能繼承一個父類,這是此方法的
split和block的區別以及maptask和reducetask個數設定
split和block的區別: 很多人可能認為在hadoop中的split和block是一樣的,可能是因為hadoop在預設情況下split的大小和hdfs檔案分塊大小是一樣而被誤導吧。 下面來談談他們的區別和聯絡: 1.split是mapreduce
字串和字元陣列的區別以及sizeof和strlen的區別
一、sizeof sizeof是運算子,其值在編譯時即計算好了,引數可以是陣列、指標、型別、物件、函式等。它的功能是:獲得保證能容納實現所建立的最大物件的位元組大小。 由於在編譯時計算,因此sizeof不能用來返回動態分配的記憶體空間的大小。實際上,用sizeof來返回型別以及靜態分配的物件、
Verilog中 reg和wire 用法和區別以及always和assign的區別
1、從模擬角度來說,HDL語言面對的是編譯器,相當於使用軟體思路,此時: wire對應於連續賦值,如assign; reg對應於過程賦值,如always,initial; 2、從綜合角度,HDL語言面對的是綜合器,相當於從電路角度來思考,此時: wi
login shell和nologin shell的區別以及su和su
Login shell與nologin shell的區別 說下定義,其實很好理解。Login shell就是你進入shell是需要輸使用者名稱密碼的,比如你啟動圖形介面最後一步需要你輸入使用者名稱密碼,只有你輸入正確,才能進入桌面,這進入的就是一個login shell。另
Log圖文詳解(Log.v,Log.d,Log.i,Log.w,Log.e)的用法
在除錯程式碼的時候我們需要檢視除錯資訊,那我們就需要用Android Log類。 android.util.Log常用的方法有以下5個:Log.v()Log.d()Log.i()Log.w()以及Log.e()。根據首字母對應VERBOSE,DEBUG,INFO,WA
關於字串輸入的scanf和gets用法的一些小知識點
#include<stdio.h> int a; char str[10000]; int main() { scanf("%d",&a); getchar(); while(a>0) {gets(str); pu
Qemu模擬IO和半虛擬化Virtio的區別以及I/O半虛擬化驅動介紹
RoCE 缺少 靈活 緩沖 不支持 src 自動 令行 nic QEMU的基本原理和優缺點 基本原理: 使用QEMU模擬I/O的情況下,當客戶機中的設備驅動程序(device driver)發起I/O操作請求之時,KVM模塊中的I/O操作捕獲代碼會攔截這次I/O請求,然後
C語言中scanf(),sscanf(),fscanf()的用法和區別
scanf(),sscanf(),fscanf()區別: 第一個是從控制檯(鍵盤)輸入; 第二個是從字串輸入; 第三個是從檔案輸入; scanf scanf()函式根據由format(格式)指定的格式從stdin(標準輸入)讀取,並儲存資料到其它引數. int main
C語言中printf(),sprintf(),scanf(),sscanf()的用法和區別
printf 語法: #include <stdio.h> int printf( const char *format, ... ); printf()函式根據format(格式)給出的格式列印輸出到STDOUT(標準輸出)和其它引數中。返
我來告訴你怎麼計算i++ + ++i + i++以及為什麼i++和++i區別這麼大?
先來看原理: 我們知道,++作為後置遞增時,優先順序為16,而作為前置遞增時,優先順序為15=作為賦值運算子時,優先順序為3所以,++會優先於=而執行 結論: 當運算子在運算元之前,稱為前增量運算子,它對運算元進行增量操作,並返回計算後的值{var i=1;j=++i;
js ==和===以及!= 和 !==的區別
true style cnblogs 基礎類型 family var ber 16px 運算 一、js == 與 === 的區別[轉] 1. 對於string,number等基礎類型,==和===是有區別的 1)不同類型間比較,==之比較“轉化成同一類型後的值”看“
線程和進程的區別以及進程通信方法
當前 實現 比較 fff nor stx 克服 orm -h 進程是資源分配的最小單位,線程是CPU調度的最小單位 對比維度 多進程 多線程 總結 數據共享、同步 數據共享復雜,需要用IPC;數據是分開的,同步簡單 因為共享進程數據,數據共享簡單,但也是因為這個
UTF-8和GBK編碼之間的區別(頁面編碼、數據庫編碼區別)以及在實際項目中的應用
同方 截斷 擴展 字節 文章 ech shu 基礎上 頁面 第一節:UTF-8和GBK編碼概述 UTF-8 (8-bit Unicode Transformation Format) 是一種針對Unicode的可變長度字符編碼,又稱萬國碼,它包含全世界所有國家需要用到的字符