C语言求助,这个函数能有简单点的写法吗?想蒙住了. 求指点.
目的是用在单片机数码管显示,高位清零,本来的代码能用,但是一个数如果是980,转换后是00000980,就想把高位是零的消掉.这是很笨的办法.所以请教高手能否简化写法.uint32 定义为 无符号32位整数.
void BCDDataConversion(uint32 Bign)
{
if (0<=Bign<10){//
ledcache= leddatacl;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
}
else if (10<=Bign<100){
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
} else if (100<=Bign<1000){
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
}else if (1000<=Bign<10000){
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
}else if (10000<=Bign<100000){
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= 0x00;
ledcache= 0x00;
ledcache= 0x00;
}else if (100000<=Bign<1000000){
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= 0x00;
ledcache= 0x00;
}else if (1000000<=Bign<10000000){
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= 0x00;
}else if (10000000<=Bign<100000000){
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
ledcache= leddatacl;
}
else Bign=0;
}
这个函数能有简单点的写法吗?想蒙住了.求指点.
补上开发板图片
用一个for或是while循环求出这个数有多少位,同时可以求出这个数的每一位,然后就可以实现了,个人看法 谢谢.这个是一种办法, 但是我希望只在转换时处理. 这样的可移植性强点. 显示的时候就直接按照原来的时序显示. 本帖最后由 eduhf_123 于 2012-11-7 01:47 编辑
LZ你是要代码写起来简单?还是要运行时简单?
1、如果要求写起来简单,可以使用sprintf库函数配合格式控制字符。
2、如果要求运行时简单,可以这样:void BCDDataConversion(uint32 Bign)
{
unsigned char i = 6; //只填充前7个字符位置,因为第8个位置上至少要显示一个“0”,不需要进行预填充
do
{
ledcache = leddatacl; //这里表示“空白”字符,即消隐控制码
}while(i--);
i = 7;
do
{
ledcache = leddatacl;
Bign /= 10;
}while(Bign && i--); //防止传入的参数超过99,999,999而造成内存访问越界
}3、如果要两者的折中,那么可以在保证传入的参数不大于99,999,999的前提下使用itoa,然后用strlen得到长度,再用一个循环把字符串进行右对齐。 eduhf_123 发表于 2012-11-7 01:41 static/image/common/back.gif
LZ你是要代码写起来简单?还是要运行时简单?
1、如果要求写起来简单,可以使用sprintf库函数配合格式控制 ...
谢谢,你的代码思想不错.
如果不是ASCII码的话就不要加0x30 void cccc(uint32 Bign)
{
unsigned char i,b0,dat;
b0 = 0;
for (i=7; i; )
{
i--;
dat = Bign%10;
Bign /= 10;
if (dat || (i==0))b0=1; //有效数开始标志
if (b0) ledcache = leddatacl;
else ledcache = 0xFF; //有效数之前的 0 消隐
}
} 我怎么从没看到过这样的代码,表示看不懂 BXAK 发表于 2012-11-7 11:53 static/image/common/back.gif
void cccc(uint32 Bign)
{
unsigned char i,b0,dat;
谢谢l, 你的代码不错. nihao_x 发表于 2012-11-8 00:44 static/image/common/back.gif
谢谢l, 你的代码不错.
他的代码问题很严重,数组的下标和循环边界有问题,最后只能访问到数组下标为0~6的元素,而下标为7的元素将没有办法访问到,直接使用将引发非预料的结果。
如果要使用他的代码,需要你自己重新设计循环控制部分。 nihao_x 发表于 2012-11-8 00:44 static/image/common/back.gif
谢谢l, 你的代码不错.
感谢10楼提醒。
没注意看,写成7位数码管了,而你是8位数码管,把 i=7 改成 i=8 就好 eduhf_123 发表于 2012-11-8 00:59 static/image/common/back.gif
他的代码问题很严重,数组的下标和循环边界有问题,最后只能访问到数组下标为0~6的元素,而下标为7的元素 ...
呵呵. 这问题自己解决了,没反应上来. eduhf_123 发表于 2012-11-8 00:59 static/image/common/back.gif
他的代码问题很严重,数组的下标和循环边界有问题,最后只能访问到数组下标为0~6的元素,而下标为7的元素 ...
高手不要把这个小问题说得那样严重,吓到我这个菜鸟! 2、如果要求运行时简单,可以这样:
You can simplify it further by combining the two loops into one: void BCDDataConversion(uint32 Bign)
{
unsigned char i = 8; //只填充前7个字符位置,因为第8个位置上至少要显示一个“0”,不需要进行预填充
do
{
i = i-1;
if(Bign) ledcache = leddatacl;
else ledcache = leddatacl; //这里表示“空白”字符,即消隐控制码
Bign /= 10;
}while(i); //防止传入的参数超过99,999,999而造成内存访问越界
} millwood0 发表于 2012-11-9 02:37 static/image/common/back.gif
You can simplify it further by combining the two loops into one:
您的代码在参数Bign值为0时无法正常工作——本应该显示“ 0”而您的代码将显示“ ”。
基于运行时效率/Cache/流水线/编译器优化等因素,我个人习惯于不在短小的循环中使用分支。
空闲时想过这段代码的进一步优化:void BCDDataConversion(uint32 Bign)
{
unsigned char i;
//从右端开始填充每个数位上的数值
i = 8;
do
{
ledcache[--i] = leddatacl;
Bign /= 10;
}while(Bign && i);
//如果有必要,继续填充左边的“空白”
while(i)
{
ledcache[--i] = leddatacl; //这里表示“空白”字符,即消隐控制码
};
} millwood0 发表于 2012-11-9 02:37 static/image/common/back.gif
You can simplify it further by combining the two loops into one:
不管怎么说,您有兴趣改良我随手写下的代码,我是深感荣幸的!
{:smile:} That's easy to solve:void BCDDataConversion(uint32 Bign)
{
unsigned char i = 7; //只填充前7个字符位置,因为第8个位置上至少要显示一个“0”,不需要进行预填充
ledcache = leddatacl;
Bign / = 10;
do
{
i = i-1;
if(Bign) ledcache = leddatacl;
else ledcache = leddatacl; //这里表示“空白”字符,即消隐控制码
Bign /= 10;
}while(i); //防止传入的参数超过99,999,999而造成内存访问越界
} 本帖最后由 eduhf_123 于 2012-11-9 15:20 编辑
millwood0 发表于 2012-11-9 09:29 static/image/common/back.gif
That's easy to solve:
您的代码中,参数Bign与0的比较以及除以10的操作在每次循环都要进行,总共各执行了8次,实际上它们都各只需要执行N次(N为参数Bign的有效数字个数,且N<=8),在51这样的系统中,能优化掉几次32位的除法操作,对运行时效率影响比较大,还是很有意义的。
另外,Line 5、Line 6的代码与Line 10、Line 12的代码重复了,ROM占用有浪费,还有优化的空间。 真的不错。感谢了。 刚学单片机时,写过这种代码.{:sweat:}
楼上几位写得都比较好呀.感觉单片机中,LZ这种写法特费空间呀 BXAK 发表于 2012-11-7 11:53 static/image/common/back.gif
void cccc(uint32 Bign)
{
unsigned char i,b0,dat;
为什么我觉得这个函数有点看不懂啊?
如果数据刚好是10的倍数,比如说是12000000,那最后显示只能是:“1 2 _ _ _ _ _ _”而不是应该显示的“12000000”。
其中,“_ ”代表消隐。
感觉问题很严重,不知道是我没分析明白还是确实有问题。 同LS指出一个问题, LZ是不是要消隐高位0但是哟保留低位0?
上面的几个程序段都是把0全干掉啊,
本帖最后由 eduhf_123 于 2012-11-19 18:36 编辑
longwu537 发表于 2012-11-19 16:00 static/image/common/back.gif
为什么我觉得这个函数有点看不懂啊?
如果数据刚好是10的倍数,比如说是12000000,那最后显示只能是:“1 2 _ _ _ _ _ _”而不是应该显示的“12000000”。
其中,“_ ”代表消隐。
感觉问题很严重,不知道是我没分析明白还是确实有问题。
把对标志“b0”赋值的语句放入循环体内的开始处、再把“ if (dat || (i==0))”改为“ if (dat || (i==7))”就好。 lin33544889 发表于 2012-11-19 17:55 static/image/common/back.gif
同LS指出一个问题, LZ是不是要消隐高位0但是哟保留低位0?
上面的几个程序段都是把0全干掉啊,
请注意分析本帖中出现的所有代码,除7楼外任何一楼中所出现的代码都不会把有效位上的“0”给消隐、而只会消隐高位无效“0”。 longwu537 发表于 2012-11-19 16:00 static/image/common/back.gif
为什么我觉得这个函数有点看不懂啊?
如果数据刚好是10的倍数,比如说是12000000,那最后显示只能是:“1 2 _ _ _ _ _ _”而不是应该显示的“12000000”。
其中,“_ ”代表消隐。
感觉问题很严重,不知道是我没分析明白还是确实有问题。
按照7楼的代码来执行(把代码中赋给 i 的初值由7改为8之后),结果将会是如下两种情况:
参数为0,则8个数码管均不显示;
参数非0,则8个数码管均有显示,低位显示有效数字、高位显示无效“0”。 eduhf_123 发表于 2012-11-19 18:44
按照7楼的代码来执行(把代码中赋给 i 的初值由7改为8之后),结果将会是如下两种情况:
参数为0,则8个 ...
随手写的问题就是多
void cccc(uint32 Bign)
{
unsigned char i,b0,dat;
for (i=8; i; )
{
i--;
ledcache = Bign%10;
Bign /= 10;
}
for (b=0, i=0; i<8; i++)
{
dat = ledcache;
if (dat || (i==7)) b0=1; //有效数开始标志
if (b0) ledcache = leddatacl;
else ledcache = 0xFF; //有效数之前的 0 消隐
}
} BXAK 发表于 2012-11-19 23:54 static/image/common/back.gif
随手写的问题就是多void cccc(uint32 Bign)
{
unsigned char i,b0,dat;
for (i=8; i; )
{
i--;
ledcache = Bign%10;
Bign /= 10;
}
for (b=0, i=0; i<8; i++)
{
dat = ledcache;
if (dat || (i==7))b0=1; //有效数开始标志
if (b0) ledcache = leddatacl;
else ledcache = 0xFF; //有效数之前的 0 消隐
}
}
第一个循环中做那么多次的除法和求余操作,可能不是必须的。 还是15楼的代码效率高些啊 eduhf_123 发表于 2012-11-19 18:35 static/image/common/back.gif
请注意分析本帖中出现的所有代码,除7楼外任何一楼中所出现的代码都不会把有效位上的“0”给消隐、而只会 ...
嗯 又看了遍
是先消隐,后置位吧,生疏1年就见笑了……
页:
[1]