scanf 用%i能夠獲得8/16進制的值, 比如0011就是9,0x11就是17,當然如果讀取到08或者09就會出錯了。
scanf簡介
scanf函數,與printf函數一樣,都被定義在stdio.h 里,因此在使用scanf函數時要加上#include<stdio.h> 。它是格式輸入函數,即按用戶指定的格式從鍵盤上把數據輸入到指定的變量之中,其關鍵字最末一個字母f即為“格式”(format)之意
scanf函數的一般形式scanf(格式控制,地址表列) int scanf(char *format[,argument,...]); “格式控制”的含義同printf函數;“地址表列”是由若干個地址組成的表列,可以是變量的地址,或字符串的首地址?! ?strong>scanf()函數返回成功賦值的數據項數,讀到文件末尾出錯時則返回EOF。 例:使用scanf函數輸入數據。 在visual c++ 6.0上的編寫方式。
[cpp] view plain
copy print ?
#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++上運行程序為:
[cpp] view plain
copy print ?
#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?! ∏曳祷刂禐閕nt型.
使用scanf函數時應該注意的問題
1、scanf()中的變量必須使用地址。
2、scanf()的格式控制串可以使用其它非空白字符,但在輸入時必須輸入這些字符?! ?/p>
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中)。我們改動一下上面的程序來驗證一下:
[cpp] view plain
copy print ?
#include?<stdio.h> ??#include<windows.h> ??int ?main()??{?? ????char ?str[80];?? ????char ?str1[80];?? ????char ?str2[80];?? ????scanf("%s" ,str);?? ????printf("%s" ,str);?? ????Sleep(5000);?? ? ?? ????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()函數還有一個 %[] 格式控制符(如果對%[]不了解的請查看本文的上篇),請看下面的程序:
[cpp] view plain
copy print ?
#include?"stdio.h" ??int ?main()??{?? ????char ?string[50];?? ????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);?? ????}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); )
[cpp] view plain
copy print ?
#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');
}
這里再給一個用“空格符”來處理緩沖區殘余信息的示例:運行出錯的程序:
[cpp] view plain
copy print ?
#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);/*這里%前沒有空格*/}
}
使用了空格控制符后:
[cpp] view plain
copy print ?
#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;??? ????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()函數全部正常讀取,它就返回幾。但這里還要注意另一個問題,如果輸入了非法數據,鍵盤緩沖區就可能還個有殘余信息問題。正確的例程:
[cpp] view plain
copy print ?
#include?<stdio.h> ??int ?main()??{?? ????int ?a,b,c;??? ????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函數的行為是不確定的?! flush(NULL)清空所有輸出流和上面提到的更新流。如果發生寫錯誤,fflush 函數會給那些流打上錯誤標記,并且返回EOF,否則返回0?! ∮纱丝芍?#xff0c;如果 stream 指向輸入流(如 stdin),那么 fflush 函數的行為是不確定的。故而使用 fflush(stdin) 是不正確的,至少是移植性不好的?! 】刹捎萌缦路椒?#xff1a; /* 此函數可以和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;??? ????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介紹
sscanf() - 從一個字符串中讀進與指定格式相符的數據.
函數原型:
int sscanf( const char *, const char *, ...);
int sscanf(const char *buffer,const char *format,[argument ]...);
buffer 存儲的數據
format 格式控制字符串
argument 選擇性設定字符串
sscanf會從buffer里讀進數據,依照argument的設定將數據寫回。
說明:
sscanf與scanf類似,都是用于輸入的,只是后者以鍵盤(stdin)為輸入源,前者以固定字符串為輸入源。 第一個參數可以是一個或多個 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符號}
注: 1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星號 (*) 表示跳過此數據不讀入. (也就是不把此數據讀入參數中) 2、{a|b|c}表示a,b,c中選一,[d],表示可以有d也可以沒有d。 3、width表示讀取寬度。 4、{h | l | I64 | L}:參數的size,通常h表示單字節size,I表示2字節 size,L表示4字節size(double例外),l64表示8字節size。 5、type :這就很多了,就是%s,%d之類。 6、特別的:%*[width] [{h | l | I64 | L}]type 表示滿足該條件的被過濾掉,不會向目標參數中寫入值 失敗返回0 ,否則返回格式化的參數個數 支持集合操作 %[a-z] 表示匹配a到z中任意字符,貪婪性(盡可能多的匹配) %[aB'] 匹配a、B、'中一員,貪婪性 %[^a] 匹配非a的任意字符,并且停止讀入,貪婪性 例子 1. 常見用法。 char buf[512] ; sscanf("123456 ", "%s", buf);//此處buf是數組名,它的意思是將123456以%s的形式存入buf中! printf("%s\n", buf); 結果為:123456 2. 取指定長度的字符串。如在下例中,取最大長度為4字節的字符串。 sscanf("123456 ", "%4s", buf); printf("%s\n", buf); 結果為:1234 3. 取到指定字符為止的字符串。如在下例中,取遇到空格為止字符串。 sscanf("123456 abcdedf", "%[^ ]", buf); printf("%s\n", buf); 結果為:123456 4. 取僅包含指定字符集的字符串。如在下例中,取僅包含1到9和小寫字母的字符串。 sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf); printf("%s\n", buf); 結果為:123456abcdedf 當輸入: sscanf("123456abcdedfBCDEF","%[1-9A-Z]",buf); printf("%s\n",buf); 結果為:123456 5. 取到指定字符集為止的字符串。如在下例中,取遇到大寫字母為止的字符串。 sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf); printf("%s\n", buf); 結果為:123456abcdedf 6、給定一個字符串iios/12DDWDFF@122,獲取 / 和 @ 之間的字符串,先將 "iios/"過濾掉,再將非'@'的一串內容送到buf中 sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf); printf("%s\n", buf); 結果為:12DDWDFF 7、給定一個字符串"hello, world",僅保留world。(注意:","之后有一空格,%s遇空格停止,加*則是忽略第一個讀到的字符串) sscanf("hello, world", "%*s%s", buf); printf("%s\n", buf); 結果為:world %*s表示第一個匹配到的%s被過濾掉,即hello被過濾了 如果沒有空格則結果為NULL。 sscanf的功能很類似于正則表達式, 但卻沒有正則表達式強大,所以如果對于比較復雜的字符串處理,建議使用正則表達式. //------------------------------------------------------- 用它來分隔類似這樣的字符串2006:03:18: int a, b, c; /*sscanf("2006:03:18", "%d:%d:%d", a, b, c); */ /*錯誤方法, 要在變量a,b,c前加上取地址符, modified by huanmie_09*/ sscanf("2006:03:18", "%d:%d:%d", &a, &b, &c); 以及2006:03:18 - 2006:04:18: char sztime1[16] = "", sztime2[16] = ""; sscanf("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2); 但是后來,我需要處理2006:03:18-2006:04:18 僅僅是取消了‘-’兩邊的空格,卻打破了%s對字符串的界定。 我需要重新設計一個函數來處理這樣的情況?這并不復雜,但是,為了使所有的代碼都有統一的風格,我需要改動很多地方,把已有的sscanf替換成我自己的分割函數。我以為我肯定需要這樣做,并伴隨著對sscanf的強烈不滿而入睡;一覺醒來,發現其實不必。 format-type中有%[]這樣的type field。如果讀取的字符串,不是以空格來分隔的話,就可以使用%[]。 %[]類似于一個正則表達式。[a-z]表示讀取a-z的所有字符,[^a-z]表示讀取除a-z以外的所有字符。 所以那個問題也就迎刃而解了: sscanf("2006:03:18 - 2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2); //-------非本段作者--------------------------------------------------------------------------------------------------- sscanf("2006:03:18-2006:04:18","%[^-]-%s",sztime1,sztime2); 描述:%[^-]匹配到‘-’默認為存到sztime1的字符串“2006:03:18”加空格符,所以%s會默認輸入“-2006:04:18”到sztime2這也就是%s前面加‘-’的原因。輸出跟作者一樣,但更易懂、易讀。 //----------------------------------------------------------------------------------------------------end----------------- 在softmse (Jake) 的問題貼http://community.csd(去掉我)n.n(去掉我)et/Expert/topic/4843/4843294.xml?temp=.4321558中 ,給出了一個很cool的sscanf用例,而后通過學習,發現sscanf真棒,現做一總結。 原問題: iios/12DDWDFF@122 獲取/和@之間的字符串怎么做 C程序里面有什么函數嗎? 代碼: #include <stdio.h> int main() { const char* s = "iios/12DDWDFF@122"; char buf[20]; sscanf( s, "%*[^/]/%[^@]", buf ); printf( "%s\n", buf ); return 0; } 結果為:12DDWDFF
總結
以上是生活随笔 為你收集整理的%d 跟%i 的区别以及scanf和sscanf的用法 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。