nihao_x 发表于 2012-11-7 00:51:19

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;
}


这个函数能有简单点的写法吗?想蒙住了.求指点.
补上开发板图片

ijlc1314 发表于 2012-11-7 00:57:45

用一个for或是while循环求出这个数有多少位,同时可以求出这个数的每一位,然后就可以实现了,个人看法

nihao_x 发表于 2012-11-7 01:33:11

谢谢.这个是一种办法, 但是我希望只在转换时处理. 这样的可移植性强点. 显示的时候就直接按照原来的时序显示.

eduhf_123 发表于 2012-11-7 01:41:30

本帖最后由 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得到长度,再用一个循环把字符串进行右对齐。

nihao_x 发表于 2012-11-7 10:52:06

eduhf_123 发表于 2012-11-7 01:41 static/image/common/back.gif
LZ你是要代码写起来简单?还是要运行时简单?

1、如果要求写起来简单,可以使用sprintf库函数配合格式控制 ...

谢谢,你的代码思想不错.

amazing030 发表于 2012-11-7 11:31:22


如果不是ASCII码的话就不要加0x30

BXAK 发表于 2012-11-7 11:53:42

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 消隐
      }                        
}

uli123 发表于 2012-11-7 19:25:43

我怎么从没看到过这样的代码,表示看不懂

nihao_x 发表于 2012-11-8 00:44:05

BXAK 发表于 2012-11-7 11:53 static/image/common/back.gif
void cccc(uint32 Bign)
{
      unsigned char i,b0,dat;


谢谢l, 你的代码不错.

eduhf_123 发表于 2012-11-8 00:59:17

nihao_x 发表于 2012-11-8 00:44 static/image/common/back.gif
谢谢l, 你的代码不错.

他的代码问题很严重,数组的下标和循环边界有问题,最后只能访问到数组下标为0~6的元素,而下标为7的元素将没有办法访问到,直接使用将引发非预料的结果。

如果要使用他的代码,需要你自己重新设计循环控制部分。

BXAK 发表于 2012-11-8 08:33:50

nihao_x 发表于 2012-11-8 00:44 static/image/common/back.gif
谢谢l, 你的代码不错.

感谢10楼提醒。
没注意看,写成7位数码管了,而你是8位数码管,把 i=7 改成 i=8 就好

nihao_x 发表于 2012-11-8 13:35:14

eduhf_123 发表于 2012-11-8 00:59 static/image/common/back.gif
他的代码问题很严重,数组的下标和循环边界有问题,最后只能访问到数组下标为0~6的元素,而下标为7的元素 ...

呵呵. 这问题自己解决了,没反应上来.

downtoearth 发表于 2012-11-9 01:29:21

eduhf_123 发表于 2012-11-8 00:59 static/image/common/back.gif
他的代码问题很严重,数组的下标和循环边界有问题,最后只能访问到数组下标为0~6的元素,而下标为7的元素 ...

高手不要把这个小问题说得那样严重,吓到我这个菜鸟!

millwood0 发表于 2012-11-9 02:37:00

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而造成内存访问越界
    }

eduhf_123 发表于 2012-11-9 03:26:04

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;         //这里表示“空白”字符,即消隐控制码
      };
}

eduhf_123 发表于 2012-11-9 03:34:09

millwood0 发表于 2012-11-9 02:37 static/image/common/back.gif
You can simplify it further by combining the two loops into one:

不管怎么说,您有兴趣改良我随手写下的代码,我是深感荣幸的!
{:smile:}

millwood0 发表于 2012-11-9 09:29:50

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:14:32

本帖最后由 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占用有浪费,还有优化的空间。

xrydt 发表于 2012-11-19 14:35:35

真的不错。感谢了。

laujc 发表于 2012-11-19 14:57:07

刚学单片机时,写过这种代码.{:sweat:}
楼上几位写得都比较好呀.感觉单片机中,LZ这种写法特费空间呀

longwu537 发表于 2012-11-19 16:00:13

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”。
其中,“_ ”代表消隐。
感觉问题很严重,不知道是我没分析明白还是确实有问题。

lin33544889 发表于 2012-11-19 17:55:09

同LS指出一个问题, LZ是不是要消隐高位0但是哟保留低位0?
上面的几个程序段都是把0全干掉啊,

eduhf_123 发表于 2012-11-19 18:34:40

本帖最后由 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))”就好。

eduhf_123 发表于 2012-11-19 18:35:44

lin33544889 发表于 2012-11-19 17:55 static/image/common/back.gif
同LS指出一个问题, LZ是不是要消隐高位0但是哟保留低位0?
上面的几个程序段都是把0全干掉啊,

请注意分析本帖中出现的所有代码,除7楼外任何一楼中所出现的代码都不会把有效位上的“0”给消隐、而只会消隐高位无效“0”。

eduhf_123 发表于 2012-11-19 18:44:15

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”。

BXAK 发表于 2012-11-19 23:54:07

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 消隐
        }            

}

eduhf_123 发表于 2012-11-20 00:52:31

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 消隐
      }            

}

第一个循环中做那么多次的除法和求余操作,可能不是必须的。

longwu537 发表于 2012-11-20 09:40:45

还是15楼的代码效率高些啊

lin33544889 发表于 2012-11-20 11:26:39

eduhf_123 发表于 2012-11-19 18:35 static/image/common/back.gif
请注意分析本帖中出现的所有代码,除7楼外任何一楼中所出现的代码都不会把有效位上的“0”给消隐、而只会 ...

嗯 又看了遍
是先消隐,后置位吧,生疏1年就见笑了……
页: [1]
查看完整版本: C语言求助,这个函数能有简单点的写法吗?想蒙住了. 求指点.