引题
博主对sprintf()和itoa()两者区别的关注要从PAT Basic Level 1002题说起。PAT是Programming Ability Test(PAT,编程能力考试),该网站提供了一些编程题目并可以在线判别结果,类似于POJ。它旨在通过统一组织的在线考试及自动评测方法客观地评判考生的算法设计与程序设计实现能力,科学的评价计算机程序设计人才,为企业选拔人才提供参考标准。
题目:
第一次源码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 100
int main(){
char numStr[N];
int i = 0, sum = 0;
char numPy[10][5]={"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
scanf("%s",numStr);
for(i = 0; i < strlen(numStr); i++){
sum += numStr[i]-48;
}
char sumStr[3];
itoa(sum,sumStr,16);
for(i = 0; i < strlen(sumStr)-1; i++){
printf("%s ",numPy[sumStr[i] - 48]);
}
printf("%s",numPy[sumStr[i] - 48]);
}
PAT提供的C编译器是gcc 4.7.2,提交源码后,在线判题系统报编译错误,给出编译错误日志如下:
ERROR: can not renice
a.c: In function 'main':
a.c:16:2: warning: implicit declaration of function 'itoa' [-Wimplicit-function-declaration]
itoa(sum,sumStr,16);
^
/tmp/ccMsn3Gd.o: In function `main':
a.c:(.text.startup+0x100): undefined reference to `itoa'
collect2: error: ld returned 1 exit status
编译日志给出提示主要有两条:
- undefined reference to `itoa’
这里说的意思是没有定义调用的函数itoa,事实上我在代码开始处已经引题了包含itoa()的头文件stdlib.h。 - collect2: ld returned 1 exit status
在ld的时候系统无法找到itoa函数。也就是说编译器在link得时候找不到其中的一个使用库的函数。
itoa()
itoa()介绍
itoa是广泛应用的非标准C语言和C++语言扩展函数,但它不是标准C/C++语言函数,所以不能在所有的编译器中使用。不过大多数的编译器(如Windows上的)通常在头文件<stdlib.h>/<cstdlib>头文件中包含这个函数。
itoa()的功能是将任意类型的数字转换为字符串。在<stdlib.h>中与之有相反功能的函数是atoi()。用法如下:
char* itoa(int value, char* string, int radix)
int value 被转换的整数,char *string 转换后储存的字符数组,int radix 转换进制数,如2,8,10,16 进制等
itoa()实现
itoa()的C语言实现如下:
char* itoa(intnum,char*str,intradix){/*索引表*/
char index[]="0123456789ABCDEF";
unsigned unum;/*中间变量*/
int i=0,j,k;
/*确定unum的值*/
if(radix==10&&num<0)/*十进制负数*/{
unum=(unsigned)-num;
str[i++]='-';
}else unum=(unsigned)num;/*其他情况*/
/*转换*/
do{
str[i++]=index[unum%(unsigned)radix];
unum/=radix;
}while(unum);
str[i]='\0';
/*逆序*/
if(str[0]=='-')k=1;/*十进制负数*/
else k=0;
char temp;
for(j=k;j<=(i-1)/2;j++){
temp=str[j];
str[j]=str[i-1+k-j];
str[i-1+k-j]=temp;
}
return str;
}
itoa()不是C标准库中的函数,而是Windows平台下扩展的,标准库中有sprintf,功能比这个更强,用法跟printf类似,因此建议大家更多的使用sprintf()。
sprintf()
sprintf()介绍
sprintf()是字符串格式化命令,主要功能是把格式化的数据写入某个字符串中。它是个变参函数,是C标准库中的函数,包含在<stdio.h>中。
原型
int sprintf( char *buffer, const char *format, [ argument] … );
参数列表
buffer:char型指针,指向将要写入的字符串的缓冲区。
format:格式化字符串。
[argument]…:可选参数,可以是任何类型的数据。
返回值
返回写入buffer 的字符数,出错则返回-1. 如果 buffer 或 format 是空指针,且不出错而继续,函数将返回-1,并且 errno 会被设置为 EINVAL。
sprintf 返回被写入buffer 的字节数,结束字符‘\0’不计入内。即,如果“Hello”被写入空间足够大的buffer后,函数sprintf 返回5。
注意:使用sprintf 对于写入buffer的字符数是没有限制的,这就存在了可能buffer溢出。解决这个问题,可以考虑使用 snprintf函数,该函数可对写入字符数做出限制。
sprintf()示例
示例源码
// 程序使用sprintf 将各种数据格式化后置于字符数组buffer中
#include <stdio.h>
int main( void )
{
char buffer[200], s[] = "computer", c = 'l';
int i = 35, j=0;
float fp = 1.7320534f;
// 格式化并打印各种数据到buffer
j = sprintf( buffer, " String: %s\n", s );
j += sprintf( buffer + j, " Character: %c\n", c );
j += sprintf( buffer + j, " Integer: %d\n", i );
j += sprintf( buffer + j, " Real: %f\n", fp );
printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}
运行结果
使用格式
格式
sprintf格式的规格如下所示,[]中的部分是可选的。
%[指定参数][标识符][宽度][.精度]指示符
若想输出’%’本身时, 请使用’%%’处理。
1. 处理字符方向。负号时表示从后向前处理。
2. 填空字元。 0 的话表示空格填 0;空格是内定值,表示空格就放着。
3. 字符总宽度。为最小宽度。
4. 精确度。指在小数点后的浮点数位数。
转换字符
%% 印出百分比符号,不转换。
%c 整数转成对应的 ASCII 字元。
%d 整数转成十进位。
%f 倍精确度数字转成浮点数。
%o 整数转成八进位。
%s 整数转成字符串。
%x 整数转成小写十六进位。
%X 整数转成大写十六进位。