To be a better coder
分类: C/C++
2018-10-30 10:47:01
原文地址:sprintf和sscanf做了什么 作者:lvyilong316
l 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
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
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,累加,得到最终结果。