本章重点学习stdlib.h库函数。
#include <REG51.h> //包含头文件REG51.h,使能51内部寄存器;
#include <stdlib.h>
//float atof (char *s1);
//参数s1字符串可包含正负号,小数点或E(e)来表示指数部分,如123.456或123e-2;
//若首字符是非数据字符,或为正负号且次字符不是数据,则停止转换;
//atof()会扫描参数s1字符串,跳过前面的空格字符,直到遇上数字或正负符号才开
//始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回,返回值为浮点数;
//long atol (char *s1);
//参数s1字符串可包含正负号,如+100或-100;
//若首字符是非数据字符,或为正负号且次字符不是数据,则停止转换;
//atol()会扫描参数s1字符串,跳过前面的空格字符,直到遇上数字或正负符号才开
//始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回,返回值为4字节型数据;
//int atoi (char *s1);
//参数s1字符串可包含正负号,如+100或-100;
//若首字符是非数据字符,或为正负号且次字符不是数据,则停止转换;
//atoi()会扫描参数s1字符串,跳过前面的空格字符,直到遇上数字或正负符号才开
//始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回,返回值为双字节型数据;
//float strtod(char *s1, char **end_ptr);
//参数s1字符串可包含正负号,小数点或E(e)来表示指数部分,如123.456或123e-2;
//若s1首字符是非数据字符,或为正负号且次字符不是数据,则停止转换;
//strtod()会扫描参数s1字符串,跳过前面的空格字符,直到遇上数字或正负符号才开
//始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回,返回值为浮点数;
//将遇到不符合条件而中止的s1中的下1个字符指针保存到end_ptr中;
//long strtol(char *s, char **end_ptr, unsigned char base);
//将s字符串数组转换为base进制的有符号4字节型数据,将遇到不符合条件而中止的s中的字符指针保
//存到end_ptr中;
//若base=10或base=0,则按十进制转换;
//若字符串前置为0x,则按十六进制转换;
//若字符串前置为0,则按八进制转换;
//unsigned long strtoul (char *s, char **end_ptr, unsigned char base);
//将s字符串数组转换为base进制的无符号4字节型数据,将遇到不符合条件而中止的s中的字符指针保
//存到end_ptr中;
//若base=10或base=0,则按十进制转换;
//若字符串前置为0x,则按十六进制转换;
//若字符串前置为0,则按八进制转换;
//void xdata *calloc(unsigned int size, unsigned int len);
//在外部RAM中,分配len*size个字节空间,若允许分配,则返回首地址,且所分配RAM区域用0进行初始
//化,否则返回NULL;
//void free(void xdata *ptr);
//将ptr所指的外部RAM空间释放出来,ptr必须是经过calloc(),mcalloc(),realloc()分配的外部RAM空间;
//void xdata *malloc(unsigned int size);
//在外部RAM中,分配size个字节空间,若允许分配,则返回首地址,且所分配RAM区域不用初始化,否则
//返回NULL;
//void xdata *realloc(void xdata *ptr, unsigned int size);
//将ptr所指向的外部RAM空间改变为size个字节,小于size的部分不变,多于size的部分也不用初始化;
//当外部RAM空间没有size大时,则保持原存储空间不变;
//int init_mempool(void xdata *ptr, unsigned int memory_size);
//对外部RAM进行初始化,地址范围:ptr to ptr+memory_size;
//初始化的外部RAM区必须是函数calloc(),free(),malloc(),realloc()可以管理的区域;
//int abs(int val);计算双字节型数据val的绝对值,输入参数val为双字节型数据,返回值为双字节型数据;
//long labs(long val); 计算4字节数据val的绝对值,输入参数val为4字节型数据,返回值为4字节型数据;
//#include <intrins.h> //包含头文件intrins.h,要放在stdio.h的头文件之前;
//使能函数: _nop_(); 相当于汇编的NOP指令;
//使能函数: bit _testbit_( bit bit_value ); 对bit_value进行测试,若bit_value=1,返回1,否则返回0;
//使能函数: unsigned char _cror_( unsigned char x, unsigned char n ); 将字节型变量x的值,向右循环移动n
//位,相当于汇编的RR A命令;
//使能函数: unsigned int _iror_( unsigned int x, unsigned char n ); 将双字节型变量x的值,向右循环移
//动n位,相当于汇编的RR A命令;
//使能函数: unsigned long _lror_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向右循环移动
//n位,相当于汇编的RR A命令;
//使能函数: unsigned char _crol_( unsigned char x, unsigned char n ); 将字节型变量x的值,向左循环移动n
//位,相当于汇编的RL A命令;
//使能函数: unsigned int _irol_( unsigned int x, unsigned char n ); 将双字节型变量x的值,向左循环移
//动n位,相当于汇编的RL A命令;
//使能函数: unsigned long _lrol_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向左循环移动
//n位,相当于汇编的RL A命令;
//以上的循环左移和循环右移,同C语言的左移和右移是不同的,使用时要小心;
#include <string.h>
//void *memchr(void *s,char val,int n);
//在字符串s[]中,搜索前n个字符,查找是否具有val的值,若有,则返回指向val的指针,否则返回NULL;
//char memcmp (void *s1, void *s2, int n);
//比较字符串数组s1[]和字符串数组s2[]的前n个字符是否相等,若相等,则返回0;
//若s1>s2,则返回一个正数,若s1<s2,则返回一个负数;
//char strncmp (char *s1, char *s2, int n);
//比较字符串数组s1[]和字符串数组s2[]的前n个字符是否相等,若相等,则返回0;
//若s1>s2,则返回一个正数,若s1<s2,则返回一个负数;
//char strcmp (char *s1, char *s2);
//比较字符串数组s1[]和字符串数组s2[],若s1=s2则返回0,表示这两个字符串是相同的;
//若s1>s2,则返回一个正数,若s1<s2,则返回一个负数;
//char *strcpy (char *s1, char *s2);
//将字符串数组s2[]的字符(包括结束符)拷贝到数组s1[]中,并将数组s1[]的首地址返回;
//char *strncpy (char *s1, char *s2, int n);
//将字符串s2[]的前n个字符拷贝到数组s1[]中,若s2的长度小于n,则用0补齐到长度n,拷贝到s1中,
//并将数组s1[]的首地址返回;
//void *memcpy (void *s1, void *s2, int n);
//将字符串数组s2[]的前n个字符拷贝到数组s1[]中,并将数组s1[]的首地址返回;
//注意:s1[]和s2[]是互相独立,没有重叠;
//void *memccpy (void *s1, void *s2, char val, int n);
//将字符串数组s2[]的前n个字符拷贝到数组s1[]中,若拷贝了n个字符,没有遇到val的值,则返回NULL;
//在拷贝过程中,若遇到val的值,则在拷贝完该字符后,将指向s1[]的下一个元素的指针返回;
//void *memmove (void *s1, void *s2, int n);
//将字符串数组s2[]的前n个字符拷贝到数组s1[]中,并将数组s1[]的首地址返回;
//注意:s2[]可以是s1[]的一部分,即有重叠部分;
//void *memset (void *s, char val, int n);
//将s[]的前n个元素设置为val的值;
//char *strcat (char *s1, char *s2);
//将字符串数组s2[]拷贝到字符串数组s1[]的尾部,并将s1[]的首字符指针返回;
//注意:s1[]要可以接受s2的字符串;
//char *strncat (char *s1, char *s2, int n);
//将字符串数组s2[]的前n个字符拷贝到字符串数组s1[]的尾部,并将s1[]的首字符指针返回;
//若字串数组s2[]的元素个数小于n,则只拷贝到s2的结束符,就停止拷贝;
//int strlen (char *s1); //返回字符串s1[]中的字符个数,包括结束符'\0';
//char *strchr (const char *s, char c);
//在s[]中搜索c的值并将第1次出现c值的指针返回,若没有搜索到,则返回NULL;
//int strpos (const char *s, char c);
//在s[]中搜索c的值并将第1次出现c值的位置值返回,若没有搜索到,则返回-1;
//char *strrchr (const char *s, char c);
//在s[]中搜索c的值并将最后1个出现c值的指针返回,若没有搜索到,则返回NULL;
//int strrpos (const char *s, char c);
//在s[]中搜索c的值并将最后1个出现c值的位置值返回,若没有搜索到,则返回-1;
//char *strstr (char *s, char *sub);
//在s[]中搜索字符串数组sub[]的字符串,并将第1次出现"sub[]的字符串"的指针返回,若没有搜索到,则返
//回NULL;
#include <stdio.h> //包含头文件stdio.h
//_getkey();从串口读入一个字符;
//putchar();向串口发送一个字节;
//printf();向串口发送一串字节;
//函数功能:测试atof()函数;
void test_atof()
{ float data float_value;
char s[]="+10S";
char s1[]="-10.5D";
char s2[]="-12e-2D";
char s3[]=".100";
char s4[]="e-2D";
float_value=atof(s); //将符合符合条件的字符串转换为符点数;
//参数s字符串可包含正负号,小数点或E(e)来表示指数部分,如123.456或123e-2;
//若首字符是非数据字符,或为正负号且次字符不是数据,则停止转换;
//atof()会扫描参数s字符串,跳过前面的空格字符,直到遇上数字或正负符号才开
//始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回,返回值为浮点数;
printf( "atof(%s)=%2.0f\n",s,float_value ); //输出:"atof(+10S)=10"
float_value=atof(s1);
printf( "atof(%s)=%2.1f\n",s1,float_value ); //输出:"atof(-10.5D)=-10.5";
float_value=atof(s2);
printf( "atof(%s)=%1.2f\n",s2,float_value ); //输出:"atof(-12e-2D)=-0.12";
float_value=atof(s3);
printf( "atof(%s)=%1.3f\n",s3,float_value ); //输出:"atof(.100)=0.100";
float_value=atof(s4);
printf( "atof(%s)=%f\n",s4,float_value ); //输出:"atof(e-2D)=NAN",不可转换;
}
//函数功能:测试strtod()函数;
void test_strtod()
{ float float_value;
char *end_ptr;
char s[]="+10ABCDEF";
float_value=strtod(s,&end_ptr); //将符合符合条件的字符串转换为符点数;
//参数s字符串可包含正负号,小数点或E(e)来表示指数部分,如123.456或123e-2;
//若s首字符是非数据字符,或为正负号且次字符不是数据,则停止转换;
//strtod()会扫描参数s字符串,跳过前面的空格字符,直到遇上数字或正负符号才开
//始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回,返回值为浮点数;
//将遇到不符合条件而中止的s1中的下1个字符指针保存到end_ptr中;
printf( "strtod(+10ABCDEF)=%f\n",float_value ); //输出:"strtod(+10ABCDEF)=10.000000"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr-1 ); //输出:"stop char is ABCDEF"
}
//函数功能:测试atol()函数;
void test_atol()
{ long long_value;
char s[]="+1000.5S";
char s1[]="-1000.5D";
char s2[]="-v1000.5D";
long_value=atol(s); //将字符串数组转换为10进制的4字节型数据;
//参数s字符串可包含正负号,如+100或-100;
//若首字符是非数据字符,或为正负号且次字符不是数据,则停止转换;
//atol()会扫描参数s1字符串,跳过前面的空格字符,直到遇上数字或正负符号才开
//始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回,返回值为整型数据;
printf( "atol(%s)=%ld\n",s,long_value ); //输出:"atol(+10.5S)=10"
long_value=atol(s1);
printf( "atol(%s)=%ld\n",s1,long_value ); //输出:"atol(-10.5D)=-10";
long_value=atol(s2);
printf( "atol(%s)=%ld\n",s2,long_value ); //输出:"atol(v10.5D)=0",不可转换;
}
//函数功能:测试strtol()函数;
void test_strtol()
{ long long_value;
char *end_ptr;
char s[]="-10BCDEF";
char s1[]="A0T";
char s2[]="0xA0T";
char s3[]="0x10T";
long_value=strtol(s,&end_ptr,10); //将字符串数组转换为10进制的4字节型数据;
//将s字符串数组转换为base进制的有符号4字节型数据,将遇到不符合条件而中止的s中的下1个字符
//指针保存到end_ptr中;
//若base=10或base=0,则按十进制转换;
//若字符串前置为0x,则按十六进制转换;
//若字符串前置为0,则按八进制转换;
printf( "strtol(%s)=%ld\n",s,long_value ); //输出:"strtol(-10BCDEF)=-10"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is BCDEF"
long_value=strtol(s,&end_ptr,0); //将字符串数组转换为10进制的4字节型数据;
printf( "strtol(%s)=%ld\n",s,long_value ); //输出:"strtol(-10BCDEF)=-10"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is BCDEF"
long_value=strtol(s1,&end_ptr,16); //将字符串数组转换为16进制的4字节型数据;
printf( "strtol(%s)=%ld\n",s1,long_value ); //输出:"strtol(A0T)=160"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is T"
long_value=strtol(s2,&end_ptr,0); //将字符串数组转换为16进制的4字节型数据;
printf( "strtol(%s)=%ld\n",s2,long_value ); //输出:"strtol(0xA0T)=160"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is T"
long_value=strtol(s2,&end_ptr,10); //将字符串数组转换为10进制的4字节型数据;
printf( "strtol(%s)=%ld\n",s2,long_value ); //输出:"strtol(0xA0T)=0"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is xA0T"
long_value=strtol(s3,&end_ptr,10); //将字符串数组转换为10进制的4字节型数据;
printf( "strtol(%s)=%ld\n",s3,long_value ); //输出:"strtol(0x10T)=0"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is x10T"
}
//函数功能:测试strtoul()函数;
void test_strtoul()
{ unsigned long Ulong_value;
char *end_ptr;
char s[]="-20T";
char s1[]="A0T";
char s2[]="0xA0T";
char s3[]="0x10T";
Ulong_value=strtoul(s,&end_ptr,10);
//将字符串数组转换为无符号10进制的4字节型数据,keil转换不正确,使用小心;
//将s字符串数组转换为base进制的无符号4字节型数据,将遇到不符合条件而中止的s中的下1个字符
//指针保存到end_ptr中;
//若base=10或base=0,则按十进制转换;
//若字符串前置为0x,则按十六进制转换;
//若字符串前置为0,则按八进制转换;
printf( "strtoul(%s)=%ld\n",s,Ulong_value ); //输出:"strtoul(-20T)=-20",keil转换不正确;
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is T"
Ulong_value=strtoul(s,&end_ptr,0); //将字符串数组转换为无符号10进制的4字节型数据;
printf( "strtoul(%s)=%lu\n",s,Ulong_value ); //输出:"strtoul(-20T)=4294967276",即-20的补码;
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is T"
Ulong_value=strtoul(s1,&end_ptr,16); //将字符串数组转换为无符号16进制的4字节型数据;
printf( "strtoul(%s)=%lu\n",s1,Ulong_value ); //输出:"strtoul(A0T)=160"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is T"
Ulong_value=strtoul(s2,&end_ptr,0); //将字符串数组转换为无符号16进制的4字节型数据;
printf( "strtoul(%s)=%lu\n",s2,Ulong_value ); //输出:"strtoul(0xA0T)=160"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is T"
Ulong_value=strtoul(s2,&end_ptr,10); //将字符串数组转换为无符号10进制的4字节型数据;
printf( "strtoul(%s)=%lu\n",s2,Ulong_value ); //输出:"strtoul(0xA0T)=0"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is xA0T"
Ulong_value=strtoul(s3,&end_ptr,10); //将字符串数组转换为无符号10进制的4字节型数据;
printf( "strtoul(%s)=%lu\n",s3,Ulong_value ); //输出:"strtoul(0x10T)=0"
if(end_ptr!=NULL) printf( "stop char is %s\n",end_ptr ); //输出:"stop char is x10T"
}
//函数功能:测试atoi()函数;
void test_atoi()
{ int int_value;
char s[]="+10.5S";
char s1[]="-10.5D";
char s2[]="v10.5D";
int_value=atoi(s); //将字符串数组转换为2字节型数据;
//参数s字符串可包含正负号,如+100或-100;
//若首字符是非数据字符,或为正负号且次字符不是数据,则停止转换;
//atoi()会扫描参数s字符串,跳过前面的空格字符,直到遇上数字或正负符号才开
//始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回,返回值为整型数据;
printf( "atoi(%s)=%d\n",s,int_value ); //输出:"atoi(+10.5S)=10"
int_value=atoi(s1);
printf( "atoi(%s)=%d\n",s1,int_value ); //输出:"atoi(-10.5D)=-10";
int_value=atoi(s2);
printf( "atoi(%s)=%d\n",s2,int_value ); //输出:"atoi(v10.5D)=0",不可转换;
}
//函数功能:测试calloc()和free()函数;
void test_calloc()
{ char xdata *ptr; //在外部RAM区,声明指针ptr,用来指向外部RAM的地址;
ptr=calloc( 1,10 ); //分配10个单字节空间;
//在外部RAM中,分配len*size个字节空间,若允许分配,则返回首地址,且所分配RAM区域用0进行初
//始化,否则返回NULL;
//使用软件模拟仿真外部RAM,必须另外添加零件库才可以;
if(ptr==NULL) printf( "There is no space\n");
else{ strcpy( ptr,"123456789" ); //将"123456789"拷贝到ptr的数组里;
printf("Array address is %p\n",&ptr ); //输出:"Array address is x:0000"
printf( "String is %s\n",&ptr ); //输出:"String is 123456789"
}
free(ptr); //将ptr所指向的外部RAM空间释放出来;
}
//函数功能:测试malloc()和free()函数;
void test_malloc()
{ char xdata *ptr; //在外部RAM区,声明指针ptr,用来指向外部RAM的地址;
ptr=malloc( 10 ); //分配10个字节空间;
//在外部RAM中,分配10个字节空间,若允许分配,则返回首地址,且所分配RAM不用初始化,否则返回
//NULL;
//使用软件模拟仿真外部RAM,必须另外添加零件库才可以;
if(ptr==NULL) printf( "There is no space\n");
else{ strcpy( ptr,"12345ABCD" ); //将"12345ABCD"拷贝到ptr的数组里;
printf("Array address is %p\n",&ptr ); //输出:"Array address is x:0000"
printf( "String is %s\n",&ptr ); //输出:"String is 12345ABCD"
}
free(ptr); //将ptr所指向的外部RAM空间释放出来;
}
//函数功能:测试realloc()和free()函数;
void test_realloc()
{ char xdata *ptr; //在外部RAM区,声明指针ptr,用来指向外部RAM的地址;
char xdata *p;
p=malloc(10); //分配10个字节空间;
//在外部RAM中,分配10个字节空间,若允许分配,则返回首地址,且所分配RAM不用初始化,否则返回
//NULL;
//使用软件模拟仿真外部RAM,必须另外添加零件库才可以;
if(p!=NULL)
{ strcpy( p,"123456789" ); //将"123456789"拷贝到ptr的数组里;
ptr=realloc(p,5);
//将p所指向的外部RAM空间改变为5个字节,小于5的部分不变,多于5的部分也不用初始化;
//当外部RAM空间没有5个字节大时,则保持原存储空间不变;
if(ptr==NULL) printf( "There is no space for *ptr\n"); //输出:"There is no space for *ptr"
else printf( "String is %s\n",&ptr );
}
else printf( "There is no space for *P\n");
}
//函数功能:测试init_mempool()函数;
void test_init_mempool()
{ char xdata *ptr; //在外部RAM区,声明指针ptr,用来指向外部RAM的地址;
ptr=calloc( 1,10 ); //分配个字节空间;
//在外部RAM中,分配len*size个字节空间,若允许分配,则返回首地址,且所分配RAM区域用0进行初
//始化,否则返回NULL;
//使用软件模拟仿真外部RAM,必须另外添加零件库才可以;
if(ptr==NULL) printf( "There is no space\n");
else{ strcpy( ptr,"123456789" ); //将"123456789"拷贝到ptr的数组里;
printf("Array address is %p\n",&ptr ); //输出:"Array address is x:0000"
printf( "String is %s\n",&ptr ); //输出:"String is 123456789"
init_mempool(ptr,10);
//对外部RAM进行初始化,地址范围:ptr to ptr+10;
//初始化的外部RAM区必须是函数calloc(),free(),malloc(),realloc()可以管理的区域;
}
free(ptr); //将ptr所指向的外部RAM空间释放出来;
}
//函数功能:测试abs()函数;
void test_abs()
{ int int_value;
int_value=abs(-100);
//计算双字节型数据val的绝对值,输入参数val为双字节型数据,返回值为双字节型数据;
printf( "abs(-100)=%d\n",int_value ); //输出:"abs(-100)=100"
int_value=abs(150);
//计算双字节型数据val的绝对值,输入参数val为双字节型数据,返回值为双字节型数据;
printf( "abs(150)=%d\n",int_value ); //输出:"abs(150)=150"
}
//函数功能:测试labs()函数;
void test_labs()
{ long long_value;
long_value=labs(-1000);
//计算4字节型数据val的绝对值,输入参数val为4字节型数据,返回值为4字节型数据;
printf( "labs(-1000)=%ld\n",long_value ); //输出:"labs(-1000)=1000"
}
//函数功能:初始化串口,设置波特率为1200bps@16MHz,使能接收,使用8位UART;
void Serial_Port_Initialization()
{ SCON = 0x50; //串行控制寄存器: SM0,SM1,SM2,REN,TB8,RB8,TI,RI
//SM1:SM0=01,选择方式1,SM2=0,表示非多机通讯,8-bit UART;
//REN=1,使能接收;
TMOD |= 0x20; //定时器方式控制寄存器:GATE1,C/T1,M11,M10,GATE0,C/T0,M01,M00
//GATE=0,TR置1便可以启动Timer;GATE=1,TR置1,且INT脚输入高电平,才
//可以启动Timer;
//M11:M10=10,选择方式2,8位自动重装载;
TH1 = 221; //TH1: reload value for 1200 baud @ 16MHz
TR1 = 1; //启动Timer1;
TI = 1; //发送UART的第一个字节,为下次发送做准备;
}
void main(void)
{
Serial_Port_Initialization(); //初始化串口,设置波特率为1200bps@16MHz,使能接收,使用8位UART;
for(;;)
{ test_atof(); //测试atof()函数;
test_atol(); //测试atol()函数;
test_atoi(); //测试atoi()函数;
test_abs(); //测试abs()函数;
test_labs(); //测试Labs()函数;
test_strtod(); //测试strtod()函数;
test_strtol(); //测试strtol()函数;
test_strtoul(); //测试strtoul()函数;
test_calloc(); //测试calloc()和free()函数;
test_malloc(); //测试malloc()和free()函数;
test_realloc(); //测试realloc()和free()函数;
test_init_mempool(); //测试init_mempool()函数;
}
}