sprintf
首先看程序段一。
程序一:
char buf[10];
int i=1234;
printf("%d\n",i); //1234
sprintf(buf,"%d",i);
printf("%d\n",strlen(buf)); //4 (sprintf自動添加0結尾)
for(i=0;i<strlen(buf);i++)
printf("%x\n",buf[i]);//31 32 33 34
printf("%s\n",buf); //1234
下面分析sprintf(buf,"%d",i),printf("%s\n",buf);做了什麼:
首先,將i的十進表示形式即1234變為單個數字(使用取余和除法),然後查找對應碼表(這裡是ASCII碼)轉換為對應字符,即:1->’1’,2->’2’,3->’3’,4->’4’。因為’’1’,’2’,’3’,’4’的ASCII碼分別為39,50,51,52(十進制),所以buf的內容的十六進制形式即為0x31323334。但是當將buf輸出時,因為是%s,所以又會查碼表,轉為字符串輸出。
i(1234)的內存為(0x000004d2)和buf的內存數據(0x31323334)是不一樣的。
注意:碼表的作用是什麼?其實碼表就是存放字符到數字的一個對應轉換關系。每一個碼表都有一個編碼規則。而具體作用有兩個:
(1) 就是上面的第一次查找碼表過程,其實就是根據相應碼表的轉換規則將數字變換為另一個數字(對於ASCII碼表,十進制數字轉換規則為x+’0’(x+48),x為當前字節對應的數字)。
(2) 就是在顯示的時候,操作系統將上述轉換得到的數字參照對應的碼表顯示相應的字符。
綜上可知,數字轉換為的字符串的二進制表示是和程序使用的碼表有關的,使用不同的碼表,得到字符串的二進制表示也不同。
下面一段程序分析也類似
程序二:
char buf[10];
int i=0x1234;
printf("%x\n",i); //1234
sprintf(buf,"%x",i);
printf("%d\n",strlen(buf)); //4
for(i=0;i<strlen(buf);i++)
printf("%x\n",buf[i]); //31 32 33 34
printf("%s\n",buf); //1234
分析:首先,將i的轉換為按十六進轉換為單個數字(除十六取余),%x和%d的不用也體現了在這裡——取余的對象不同(16和10),每個字節查找對應碼表(這裡是ASCII碼)轉換為對應字符,即:1->’1’,2->’2’,3->’3’,4->’4’。因為’’1’,’2’,’3’,’4’的ASCII碼分別為39,50,51,52(十進制),所以buf的內容的十六進制形式即為0x31323334。但是當將buf輸出時,因為是%s,所以又會查碼表,轉為字符串輸出。
注:對比程序一、二,我們發現,不同的數字(1234和0x1234)對應轉換後的字符串的底層表示是一樣的(都是0x31323334),所以數字和字符串的轉換除了和碼表有關還和轉換時的進制有關。
l Sscanf
程序三:
char buf[5]="1234";
int i;
sscanf(buf,"%d",&i);
printf("%d\n",i);//輸出1234
Buf中的二進制內容是0x31323334(字符’1’,’2’,’3’,’4’的ASCII碼的二進制表示),將buf中的每個字節(字符)逐個取出查詢碼表(ASCII碼),找到對應的數字,如0x31 (49)對應數字1,之後根據十進制規則(因為是%d)進行×10,累加,得到最終結果。