[轉載]C語言 格式化字符
前段時間用C寫了一個程式,發現3年前學的C的基本語法都忘得差不多了。下面的格式化字符,我覺得值得我寫個隨筆,免得下次再寫時,忘記了。
格式字符控制:
說明:sprintf(格式化后的字符,"%(長度)格式符",格式化前的字符);
1、 d格式符。用來輸出十進制數。有以下幾種用法:
(1)、%d按整數的實際長度輸出。
(2)、%md,m為指定的輸出字段的寬度。如果數據位數小于m,則左端補以空格,若大于m,則按實際位數輸出。(3)、%ld,輸出長整型數據。例:long a=135790;printf(“%ld”,a);如果用%d輸出就會發生錯誤,因為整型數據的范圍是-32768到32767.對long型數據應當用%ld格式輸出,對長整型數據也可以指定字段寬度,如:%8ld。
2、 o格式符,以八進制數形式輸出整數。由于內存單元中的各位的值(0或1)按八進制形式輸出,因此輸出的數值不帶符號,即將符號位也一起作為八進制的一部分輸出。
3、 x格式符,以十六進制數形式輸出整數。同樣不會出現負的十六進制數。同樣可以用%lx輸出長整型數,也可以指定輸出字段寬度。
4、 u格式符,用來輸出unsigned型數據,即無符號數,以十進制形式輸出。一個有符號整數(int型)也可以用%u格式輸出,反之,一個unsigned型的數據也可以用%d格式輸出。按相互賦值的規則處理。Unsigned型數據也可以用%x格式輸出。
5、 c格式符,用來輸出一個字符。一個字符型數據也可以用整數形式輸出。
6、 s格式符,用來輸出一個字符串。
(1)、%s,printf(“%s”,“HELLO”);
(2)、%ms輸出字符串占m列,如字符串本身大于m,則突破m的限制,字符串全部輸出,如果小于m,則左補空格。(3)、%-ms如果字符串小于m,則在m范圍內,字符串向左靠,右補空格。
(4)、%m.ns,輸出占m列,但只取字符串中左端n個字符。這n個字符輸出在m列的右側,左補空格。
(5)、%-m.ns,其中m,n含義同上,n個字符輸出在m范圍的左側,右補空格。如果n>m,則自動取n值,即保證n個字符正常輸出。
7、 f格式符,用來輸出實數(包括單,雙精度),以小數形式輸出。
(1)、%f,不指定字段寬度,有系統自動指定,使整數部分全部如數輸出,并輸出6位小數。應當注意,并非全部數字都是有效數字。單精度實數的有效位數一般是7位。
(2)、%m.nf指定輸出的數據占m列,其中有n位小數。如果數值長度小于m,則左補空格。
(3)、%-m.nf與%m.nf基本相同,只是輸出的數值向左端靠,右端補空格。
8、 e格式符,以指數形式輸出。
9、 g格式符,用來輸出實數,它根據數值的大小,自動選擇f格式或e格式(選擇輸出時占寬度較小的一種),且不輸出無意義的零。
*********************************************************
Code | 格式 |
%c | 字符 |
%d | 帶符號整數 |
%i | 帶符號整數 |
%e | 科學計數法, 使用小寫"e" |
%E | 科學計數法, 使用大寫"E" |
%f | 浮點數 |
%g | 使用%e或%f中較短的一個 |
%G | 使用%E或%f中較短的一個 |
%o | 八進制 |
%s | 一串字符 |
%u | 無符號整數 |
%x | 無符號十六進制數, 用小寫字母 |
%X | 無符號十六進制數, 用大寫字母 |
%p | 一個指針 |
%n | 參數應該是一個指向一個整數的指針 指向的是字符數放置的位置 |
%% | 一個'%'符號 |
一個位于一個%和格式化命令間的整數擔當著一個最小字段寬度說明符,并且加上足夠多的空格或0使輸出足夠長. 如果你想填充0,在最小字段寬度說明符前放置0. 你可以使用一個精度修飾符,它可以根據使用的格式代碼而有不同的含義.
- 用%e, %E和 %f,精度修飾符讓你指定想要的小數位數. 例如,
%12.6f
將會至少顯示12位數字,并帶有6位小數的浮點數.
- 用%g和 %G, 精度修飾符決定顯示的有效數的位數最大值.
- 用%s,精度修飾符簡單的表示一個最大的最大長度, 以補充句點前的最小字段長度.
所有的printf()的輸出都是右對齊的,除非你在%符號后放置了負號. 例如,
%-12.4f
將會顯示12位字符,4位小數位的浮點數并且左對齊. 你可以修改帶字母l和h%d, %i, %o, %u和 %x 等類型說明符指定長型和短型數據類型 (例如 %hd 表示一個短整數). %e, %f和 %g 類型說明符,可以在它們前面放置l指出跟隨的是一個double. %g, %f和 %e 類型說明符可以置于字符'#'前保證出現小數點, 即使沒有小數位. 帶%x類型說明符的'#'字符的使用, 表示顯示十六進制數時應該帶'0x'前綴. 帶%o類型說明符的'#'字符的使用, 表示顯示八進制數時應該帶一個'0'前綴.
****************************格式化符在sscanf函數中的強大用法*****************************
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);
在softmse (Jake) 的問題貼http://community.csd(去掉我)n.n(去掉我)et/Expert/topic/4843/4843294.xml?temp=.4321558中 ,給出了一個很cool的sscanf用例,而后通過學習,發現sscanf真棒,現做一總結。
搜集一些特殊用法:
%[ ] 的用法:%[ ]表示要讀入一個字符集合, 如果[ 后面第一個字符是”^”,則表示反意思。
[ ]內的字符串可以是1或更多字符組成。空字符集(%[])是違反規定的,可
導致不可預知的結果。%[^]也是違反規定的。
%[a-z] 讀取在 a-z 之間的字符串,如果不在此之前則停止,如
char s[]="hello, my friend” ; // 注意: ,逗號在不 a-z之間
sscanf( s, “%[a-z]”, string ) ; // string=hello
%[^a-z] 讀取不在 a-z 之間的字符串,如果碰到a-z之間的字符則停止,如
char s[]="HELLOkitty” ; // 注意: ,逗號在不 a-z之間
sscanf( s, “%[^a-z]”, string ) ; // string=HELLO
%*[^=] 前面帶 * 號表示不保存變量。跳過符合條件的字符串。
char s[]="notepad=1.0.0.1001" ;
char szfilename [32] = "" ;
int i = sscanf( s, "%*[^=]", szfilename ) ;
// szfilename=NULL,因為沒保存
int i = sscanf( s, "%*[^=]=%s", szfilename ) ;
// szfilename=1.0.0.1001
%40c 讀取40個字符
%[^=] 讀取字符串直到碰到’=’號,’^’后面可以帶更多字符,如:
char s[]="notepad=1.0.0.1001" ;
char szfilename [32] = "" ;
int i = sscanf( s, "%[^=]", szfilename ) ;
// szfilename=notepad
如果參數格式是:%[^=:] ,那么也可以從 notepad:1.0.0.1001讀取notepad
注意:當碰到不滿足條件的字符后,sscanf就會停止執行,不再掃描之后的字符。
********************strtok字符串分割函數也是個實戰性較強的函數,但是已被strsep函數取代***********************
#include <string.h>
char *strtok( char *str1, const char *str2 );
功能:函數返回字符串str1中緊接“標記”的部分的指針, 字符串str2是作為標記的分隔符。如果分隔標記沒有找到,函數返回NULL。為了將字符串轉換成標記,第一次調用str1 指向作為標記的分隔符。之后所以的調用str1 都應為NULL。
例如:
char str[] = "now # is the time for all # good men to come to the # aid of their country";
char delims[] = "#";
char *result = NULL;
result = strtok( str, delims );
while( result != NULL ) {
printf( "result is \"%s\"\n", result );
result = strtok( NULL, delims );
}
以上代碼的運行結果是:
result is "now "
result is " is the time for all "
result is " good men to come to the "
result is " aid of their country"
---------------------------------------------------------------------------------
char* strname=NULL;
strname=(char*)malloc(sizeof(char));
memset(strname,0,sizeof(char));
strcpy(strname,"tong|sun|java|google");
char delims[] = "|";
char* ret=NULL;
ret=(char*)malloc(sizeof(char));
memset(ret,0,sizeof(char));
ret=strtok(strname,delims);
while(ret!=NULL)
{
printf("%s\n",ret);
ret=(char*)malloc(sizeof(char));
memset(ret,0,sizeof(char));
ret=strtok(NULL,delims);
}
-------------------------------------------------------------------------------------
strsep
baikeViewInfo={id:"2466295",editable:"true",title:"strsep",expIndex:"0"};
*********************strncat字符串截取拼接*********************************
strncat
baikeViewInfo={id:"1028544",editable:"true",title:"strncat",expIndex:"0"};
以上代碼的運行結果是:
Golden Global View 注意view前面有個空格字符。
***********************strncasecmp***************************
strncasecmp
baikeViewInfo={id:"1589829",editable:"true",title:"strncasecmp",expIndex:"0"};
char *a="acddfefekr";
char *b="AbCddfefekr";
printf("%d\n",strncasecmp(a,b,2));
以上代碼的運行結果是:1
******************************strcasecmp*************************
strcasecmp
(忽略大小寫比較字符串)
相關函數 bcmp,memcmp,strcmp,strcoll,strncmp
表頭文件 #include<string.h>
定義函數 int strcasecmp (const char *s1, const char *s2);
函數說明 strcasecmp()用來比較參數s1和s2字符串,比較時會自動忽略大小寫的差異。
此原文這里有錯誤:返回值 若參數s1和s2字符串相同則返回0。s1長度大于s2長度則返回大于0 的值,s1 長度若小于s2 長度則返回小于0的值。
strcasecmp是比較兩個字符串,但比較的不是它們的長度,而是字符的編碼大小——但字母不區分大小寫,如果S1小于S2,返回小于0的一個整數;如果S1等于S2,返回值是0;如果S1>S2,返回一個大于0的整數。
#include <string.h>
main()
{
char *a="aBcddfefekr";
char *b="AbCddfefekr";
printf("%d\n",strcasecmp(a,b));
執行 aBcDeF=AbCdEf
以上代碼的運行結果是:0
注意與strncasecmp()的區別,不要弄混了。
該函數是二進制安全的,且對大小寫不敏感。
*************************strncpy*******************************
strncpy:字串復制 原型:char * strncpy(char *dest, char *src, size_t n);
功能:將字符串src中最多n個字符復制到字符數組dest中(它并不像strcpy一樣遇到NULL才停止復制,而是等湊夠n個字符才開始復制),返回指向dest的指針。
說明:
如果n > dest串長度,dest棧空間溢出產生崩潰異常。
否則:
1)src串長度<=dest串長度,(這里的串長度包含串尾NULL字符)
如果n=(0, src串長度),src的前n個字符復制到dest中。但是由于沒有NULL字符,所以直接訪問dest串會發生棧溢出的異常情況。
如果n = src串長度,與strcpy一致。
如果n = dest串長度,[0,src串長度]處存放于desk字串,(src串長度, dest串長度]處存放NULL。
2)src串長度>dest串長度
如果n =dest串長度,則dest串沒有NULL字符,會導致輸出會有亂碼。如果不考慮src串復制完整性,可以將dest最后一字符置為NULL。
綜上,一般情況下,使用strncpy時,建議將n置為dest串長度(除非你將多個src串都復制到dest數組,并且從dest尾部反向操作),復制完畢后,為保險起見, 將dest串最后一字符置NULL,避免發生在第2)種情況下的輸出亂碼問題。當然嘍,無論是strcpy還是strncpy,保證src串長度<dest串長度才是最重要的。
*******************************snprintf*******************************
snprintf
baikeViewInfo={id:"1966670",editable:"true",title:"snprintf",expIndex:"0"};
int snprintf(char *restrict buf, size_t n, const char * restrict format, ...);
函數說明:最多從源串中拷貝n-1個字符到目標串中,然后再在后面加一個0。所以如果目標串的大小為n
的話,將不會溢出。
函數返回值:若成功則返回欲寫入的字符串長度,若出錯則返回負值。
Result1(推薦的用法)
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[10]={0,};
snprintf(str, sizeof(str), "0123456789012345678");
printf("str=%s\n", str);
return 0;
}
**************************************************************
實戰常用函數:
printf scanf sscanf strcat strncat fprint fwrite fread fopen fclose
sprintf snprintf strcmp strncmp strstr strchr strlen strcasecmp strncasecmp
memcpy strcpy strncpy