void Value2String(unsigned char value,char *str)
{
char *Hex_Char_Table="0123456789ABCDEF";
str[0] = '0';
str[1] = 'X';
str[4] = 0;
str[2]=Hex_Char_Table[value>>4];
str[3]=Hex_Char_Table[value&0X0F];
}
字符串常量实质是内存中的字节序列,如下图所示:
void Value2String(unsigned char value,char *str)
{
str[0]='0';str[1]='X';str[4]=0;
str[2]="0123456789ABCDEF"[value>>4];
str[3]="0123456789ABCDEF"[value&0X0F];
}
Hex_Char_Table 这个指针变量其实是多余的,“字符串本身就是指针”,所以它后面可以直接用 [] 配合下标来取出其中的字符。凡是实质上为指针类型(即表达的是地址意义)的变量或常量,都可以直接用[]或*来访问它所指向的数据序列中的数据元素。
const unsigned char array[10]={0,1,2,3,4,5,6,7,8,9};
char *array="\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09";
char *str="ABCDEFG";
char *str="\x41\x42\x43\x44\x45\x46\x47";
上面程序中的两种写法,是完成等价的。
printf("A:%d B:%d C:%d D:%d E:%d F:%d\r\n",1,2,3,4,5,6);
printf("A:%d " \
"B:%d " \
"C:%d " \
"D:%d " \
"E:%d " \
"F:%d\r\n",1,2,3,4,5,6);
char * substr(char *str,n)
{
unsigned char len=strlen(str);
for(;len>0;len--) {if(str[len-1]==' ') str[len-1]=0;}
for(;n>0;n--)
{
str+=(strlen(str)+1);
}
return str;
}
unsigned char substr(unsigned char \*pos,char \*str)
{
unsigned char len=strlen(str);
unsigned char n=0,i=0;
for(;i<len;i++)
{
if(str[i]==' ')
{
str[i]=0;pos[n++]=(i+1);
}
}
return n;
}
unsigned char pos[10];
char str[30];
strcpy(str,"abc 1000 50 off 2500");
substr(pos,str);
str+pos[0]; //"abc"
str+pos[2]; //"50"
str+pos[3]; //"off"
void getdigi(unsigned char *digi,unsigned int num)
{
digi[0]=(num/10000)%10;
digi[1]=(num/1000)%10;
digi[2]=(num/100)%10;
digi[3]=(num/10)%10;
digi[4]=num%10;
}
其实一样的道理,请看下面函数(我们默认整数与小数部分均取4位)。
void getdigi(unsigned char *digi1,unsigned char *digi2,unsigned float num)
{
unsigned int temp1=num;
unsigned int temp2=((num-temp1)\*10000);
digi1[0]=(temp1/1000)%10;
digi1[1]=(temp1/100)%10;
digi1[2]=(temp1/10)%10;
digi1[3]=(temp1)%10;
digi2[0]=(temp2/1000)%10;
digi2[1]=(temp2/100)%10;
digi2[2]=(temp2/10)%10;
digi2[3]=(temp2)%10;
}
char digi[10];
sprintf(digi,"%d",num); //**整型
char digi[10];
sprintf(digi,"%f",num); //**浮点
没问题。但在嵌入式平台上使用sprintf函数,通常代价是较大的。
int fputc(int ch, FILE \*f)
{
while((USART1->SR&0X40)==0);
{
USART1->DR = (u8) ch;
}
return ch;
}
fputc中将ch通过USART1发出。这样,我们在调用printf的时候,相应的信息就会从USART1打印出来。
int fputc(int ch, FILE *f)
{
LCD_DispChar(x,y,ch);
x++;
if(x>=X_MAX)
{
x=0;y++;
if(y>=Y_MAX)*
{
y=0;
}
}
return ch;
}
这个fputc将字符显示在了液晶上(同时维护了字符的显示位置信息),这样当我们调用printf的时候,信息会直接显示在液晶上。
unsigned char us=0;
int fputc(int ch,FILE *f)
{
switch(us)
{
case 0:
while((USART1->SR&0X40)==0);
USART1->DR=(u8)ch;
break;
case 1:
while((USART2->SR&0X40)==0);
USART2->DR=(u8)ch;
break;
case 2:
while((USART3->SR&0X40)==0);
USART3->DR=(u8)ch;
break;
}
return ch;
}
#define U_TO_DEBUG us=0;
#define U_TO_ESP8266 us=1;
#define U_TO_SIM800 us=2;
U_TO_DEBUG
printf("hello world!");
U_TO_ESP8266
printf("AT\r\n");
U_TO_SIM800
printf("AT\r\n");
unsigned short a=0X1234;
UART_Send_Byte(((unsigned char *)&a)[0]);
UART_Send_Byte(((unsigned char *)&a)[1]);
unsigned char buf[2];
usnigned short a;
UART_Receive_Byte(buf+0);
UART_Receive_Byte(buf+1);
a=(*(usnigned short *)buf);
float a=3.14;
char str[10]={0};
ftoa(str,a); //**浮点转为字符串* *即3.14**转为"3.14"
UART_Send_Str(str); //**通过串口将字符串发出
还有人问我:“浮点小数字前后的数字可以发送,但是小数点怎么发?”这赤裸裸的体现了他对浮点类型的误解。
不要被float数值的表象迷惑,它实质上只不过是4个字节而已,如下图所示:
所以,正确的发送浮点数的方法是这样的:
float a=3.14;
UART_Send_Byte(((unsigned char *)&a)[0]);
UART_Send_Byte(((unsigned char *)&a)[1]);
UART_Send_Byte(((unsigned char *)&a)[2]);
UART_Send_Byte(((unsigned char *)&a)[3]);
unsigned char buf[4];
float a;
UART_Receive_Byte(buf+0);
UART_Receive_Byte(buf+1);
UART_Receive_Byte(buf+2);
UART_Receive_Byte(buf+3);
a=*((float *)buf);
其实我们应该发现数据类型的实质:不论是什么数据类型,它的基本组成无非就是内存中存储的若干个字节。只是我们人为的赋予了这些字节特定的编码方式或数值表达。看穿了这些,我们就认识到了数据的本质了,我们甚至可以直接操作数据。
int a=10;
int b=-a; //-1*a;
int a=10;
int b=(~a)+1;
float a=3.14;
float b=a*-1.0;
float a=3.14;
float b;
((unsigned char *)&a)[3]^=0X80;
b=a;
没错,我们可以直接修改浮点在内存中的高字节的符号位。这比乘以-1.0的方法要高效的多。
float a,b;
if(a==b)
... //**错误
if(fabs(a-b) <= 0.000001)
...//**正确
int i;
for(i=0;i<100;i++)
{...}
但是,如果我们对for循环的本质有更深刻的理解的话,就可以把它用得出神入化。
for(1;1;1) //1**本身就是一个表达式:常量表达式
{
...
}
for(;;)
{
...
}
int i=0;
for(printf("Number:\r\n");i<10;i++)
{
printf(" %d\r\n",i);
}
if(strstr("hello world!","abc"))
{
printf("Find Sub-string");
}
char *p;
for(p=strstr("hello world!","abc");p;p=NULL)
{
printf("Find Sub-string");
}
以上的例子可能有些鸡肋,“一个if能搞定的事情,我为什么要用for?”,没错。我们这里主要是为了解释for循环的灵活用法。深入理解了它的本质,有助于我们在实际开发中让工作事半功倍,以及看懂别人的代码。
char *p;
for(p="abcdefghijklmnopqrstuvwxyz"; printf(p); p++)
printf("\r\n");
提示:printf我们太熟悉了,但有几个人知道printf是有返回值的?输出应该是怎样的?
char *p;
unsigned char n;
for(p="ablmnl45ln",n=0;((\*p=='l')?(n++):0),\*p;p++);
例3:
unsigned char *index="C[XMZA[C[NK[RDEX@";
char *alphabet="EHUIRZWXABYPOMQCTGSJDFKLNV ";
int i=0;
for(;(('@'!=index[i])?1:(printf("!!Onz\r\n"),0));i++)
{
printf("%c",alphabet[index[i]-'A']);
}
END
→点关注,不迷路←
文章引用微信公众号"嵌入式微处理器",如有侵权,请联系管理员删除!