| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1391 人关注过本帖
标题:这个函数不用goto怎么改
只看楼主 加入收藏
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:13 
这个函数不用goto怎么改
程序代码:
static char
mysh_recv_data(char data[], char endata[], unsigned *size,
           unsigned (*recv)(void *, unsigned),
           unsigned (*send)(const void *, unsigned))
{
    unsigned sz, len, n;
    unsigned need, max_size;
    char *p, *e, *begin, c;

    len = sz = 0;
    begin = endata;
    max_size = MYSH_EN_DATA_BLOCK_SIZE;
    goto lab_skip_get_header;

    while(1)
    {
    /* lab_get_header */
        begin = endata;

        c = mysh_send_cmd(C_RETRY, send);
        if (c != C_RETRY) break;
        c = mysh_recv_cmd(C_DATAB, recv);
        if (c == C_STOP) break;
        if (c != C_DATAB) continue;

    lab_skip_get_header:
        need = max_size - len;
        p = endata + len;
        n = recv(p, need);
        if (n < 1) goto lab_skip_get_header;
        len = len + n;
        e = p + n;

    lab_try_find_data_end:
        while(p < e && mysh_is_endata_char(*p))
            ++p;
        c = *p;
        if (p >= e) goto lab_skip_get_header;
        if (c == C_END) goto lab_finded_data;
        if (c == C_STOP) goto lab_return_value;

        while(p < e)
        {
            c = *p++;
            if (c == C_STOP) goto lab_return_value;
            if (c != C_DATAB) continue;
            begin = p;
            goto lab_try_find_data_end;
        }
        /* we re-need a C_DATAB header */
        continue;

    lab_finded_data:
        n = (p - begin);
        sz = mysh_data_decode(data, begin, n);
        /* we re-need a C_DATAB header */
        if (n < 1) continue;
        c = mysh_send_cmd(C_OK, send);
        if (c == C_OK)
        c = C_DATAB;
        break;
    }


 lab_return_value:
    *size = sz;
    return c;
}



[ 本帖最后由 皮天佑 于 2015-7-4 17:02 编辑 ]
2015-07-04 16:58
风清云起
Rank: 1
等 级:新手上路
帖 子:11
专家分:4
注 册:2015-6-27
收藏
得分:0 
你这个函数的功能是什么啊,亲
2015-07-04 17:14
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
收藏
得分:0 
回复 2楼 风清云起
这个函数接受一包数据,然后把这包传输格式的数据转成本地数据,如果转出来的本地数据有误或者接受到的数据有误则重新接收。
mysh_send_cmd 发送一个命令
mysh_recv_cmd 接受一个命令
mysh_data_decode 将传送中的数据解码为本地数据
传输的数据格式为 C_DATAB + 传输中的数据  + 校验 + C_END;
如果接受到C_STOP立即返回,如果接受数据成功者返送C_OK命令。
2015-07-04 17:23
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
收藏
得分:0 
老大要改为没有goto的代码,感觉越改越复杂。
2015-07-04 17:24
erty1001
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:331
专家分:1433
注 册:2014-8-31
收藏
得分:0 
简单说说:
    C语言的习惯是C风格的封装方式:
   用这段来说    lab_skip_get_header:
        need = max_size - len;
        p = endata + len;
        n = recv(p, need);
        if (n < 1) goto lab_skip_get_header;
  这种属于汇编结构衍生体
   虽然这样代码汇编的结果我们能够最大化的掌握 但是失去了C语言特殊结构封装的特色了
  
  C语言是这样处理的
  do{
    commend;
     }while(n<1);
   这样它自己掩藏了如果返回去循环的表现体

  对于下面这样结构的:
        if (p >= e) goto lab_skip_get_header;
        if (c == C_END) goto lab_finded_data;
        if (c == C_STOP) goto lab_return_value;
   属于汇编少分支跳跃经典结构
  C语言是一般这样处理的
   简单无封装的情况设置关键数据为全局变量,通过同级多个子函数去实现 特定功能
   if(p>=e)  f1(接口0,接口1,接口...);
   else if(c == C_END)  f2(接口0,接口1,接口...);
   esle if (c == C_STOP)  f3(接口0,接口1,接口...);
  
都很简单 自己吸收掌握吧
2015-07-04 21:31
erty1001
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:331
专家分:1433
注 册:2014-8-31
收藏
得分:0 
补充一句:
  关于while内部的goto

        while(p < e)
        {
            c = *p++;
            if (c == C_STOP)   
            {
             f2(接口0,接口1,接口...);
              break;
            }

        }
  
  大概是改成
        while(p < e)
        {
            c = *p++;
            if (c == C_STOP)    goto lab_return_value;
            if (c != C_DATAB) continue;
            begin = p;
            goto lab_try_find_data_end;
        }
2015-07-04 21:34
实际应用
Rank: 5Rank: 5
等 级:职业侠客
威 望:2
帖 子:89
专家分:341
注 册:2015-5-30
收藏
得分:0 
5楼说的极是
这段不能改这能重写
否则受制于原思路,越改越复杂
2015-07-04 21:50
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
收藏
得分:0 
回复 6楼 erty1001
现在写这段代码的人走了,老大让我来维护,这个代码我感觉写的很精练。goto是可以去掉,但感觉是为了去掉而增加了代码的复杂性。
while(1)里面的标签是按顺序来的,接受数据的头,接受数据,尝试查找数据的结尾,如果找到数据结尾则尝试解码数据,成功则退出循环。
        need = max_size - len;
        p = endata + len;
        n = recv(p, need);
        if (n < 1) goto lab_skip_get_header;
这里如果该成do while循环是可以,但是下面要还要回到这里,估计得要至少2层循环,
while(1)
{
        while(1)
        {
           while(接收buff中有所数据);
           while(跳过是传输数据的字符)
           如果接收到数据结尾,尝试解码数据为本地数据
           否则是要重新查找数据头
           。。。
        }
        获取数据头
}
好像要加变量来控制2层循环的退出,我改的版本看起来很乱,没原来代码清晰简单。
C_STOP是为了防止停在函数里面,这个命令可以让接收方在任何位置退出接受,在传输过程中即使丢数据都能正确的完成接受。
感觉能改的就是那个lab_skip_get_header标签改为lab_input_data,
不知道老大是怎么想的。
2015-07-04 22:48
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
这段代码完全谈不上精练。逻辑冗余拖沓。

重剑无锋,大巧不工
2015-07-05 01:40
erty1001
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:331
专家分:1433
注 册:2014-8-31
收藏
得分:0 
补充说明:
  那个外层的while(1){}  我给忽略掉了~
  如果是这种情况 重新写类似这样的形式

   while(1)   
   {        
            if(!ExitTest())  break;
            KB=Keydown();
            if(KB == 16)
            Display(c);
            else { Display( F1(a,b)); }   
   }
2015-07-05 08:15
快速回复:这个函数不用goto怎么改
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.049643 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved