由于python语法的简洁,所以在写c代码的时候,有时候也会想能不能把C代码写的更简练一点,这几天遇到一个,给大家分享一下。
比如我们要用C写一个判断语句,然后根据不同的值返回不同的内容。

如果判断的逻辑很多,代码就会显得很臃肿(文中的例子用switch也可以,但是也还是很难看),如果用python,就会这样写(为了和C类比,这里没有用字典):

那在c里面是否能同样的方法实现呢,是可以的:

附:
有人可能想到用stl的map,查找速度会快一些,不过想到定义一个map,然后调用一堆insert其实也挺麻烦的,而且例子中用的是int,但是并不是所有的类型都是可hash的,所以有些情况下map并不能胜任。

最近的一些技术整理(20120109)

前段时间一直没写博客,昨天更新了一篇,今天突然又来了兴致,那就再更新一篇吧(所以说啊,治疗拖延症最好的方法就是现在开始做) 这篇还是一些技术的整理,...

阅读全文

C++模板的几个应用

C++的模板其实是个挺纠结的东西,用的不好的话,编译的一堆错误够你调到崩溃,但要是用的好呢,又确实非常方便,我们来看看 一.获取数组长度 比如 ...

阅读全文

又见C++诡异问题

用C++越久,越是觉得C++太多陷阱,真是防不胜防。 我们看这样一段代码: C++ #include <stdio.h> using namespace std; ...

阅读全文

34则回应给“参考python来简写C代码”

  1. miles说道:

    我觉得还不如原来的写法呢。。。

    [回复]

    Dante 回复:

    呃,这个。。。你可以想想一下有10个返回码,分别要来返回不同的值。。
    就需要写10个if else,而且很不容易维护。

    [回复]

    miles 回复:

    好吧。。。。

    [回复]

  2. Pinepara说道:

    这是一种很常用的设计模式,有一个名字叫做 “table-driven”——表驱动法

    [回复]

    Dante 回复:

    原来如此,在python里面经常这样写,不知道原来还有这样一个定义。

    [回复]

    Pinepara 回复:

    《Code Complete》(代码大全)里面有详细的介绍

    [回复]

    Dante 回复:

    看来有必要好好读一下。。一直放在硬盘里。。

    [回复]

    madper 回复:

    lisp常用表驱动法的…抽空看看sicp应该也挺好的, 虽然我没看这本…

    [回复]

  3. dormouse说道:

    这样的比较有什么实际用途吗?Python是不是用C写出的?如果是,那么Python的任何用法都可以用C来实现。盘古开天据说用的是C,你信不:-》

    [回复]

    Dante 回复:

    呵呵,言重了,我python和C都用,还用php,只是个人喜好而已~ 大家选择自己喜欢的就行~

    [回复]

  4. lihex说道:

    用map我会这么写,光初始化就很麻烦,呵呵
    map amap;
    string str[3]={“333″,”222″,”444″}
    int i=0;
    while(i<3)
    {
    amap[i]=str[i++];

    }

    [回复]

  5. greatghoul说道:

    除了维护外,语法和逻辑上似乎都变复杂了。这种写法可不可取,还得两说。

    如果情况比较少,感觉没有必要这么折腾,如果情况比较多,这么多重复的事,干嘛不写成函数。

    我个人觉得没有必要为了简化而简化。用爱因思坦那货的话来说”Make everything as simple as possible, but not simpler.” 过犹不及

    [回复]

    Dante 回复:

    这是我用这个方法写的统计时间段的函数:
    string get_maptime(int time_ms)
    {
    struct
    {
    int iTime;
    string strTimeKey;
    }arr_times[]={
    {5,”[0,5]“},
    {10,”(5,10]”},
    {50,”(10,50]”},
    {100,”(50,100]”},
    {200,”(100,200]”},
    {500,”(200,500]”},
    {1000,”(500,1000]”},
    {-1,”(1000,~)”},
    };
    int count = sizeof(arr_times) / sizeof(arr_times[0]);

    for (int i = 0; i < count; i++) { if (arr_times[i].iTime == -1 || time_ms <= arr_times[i].iTime) { return arr_times[i].strTimeKey; } } return “(1000,~)”;//实际上到不了这一步 }

    [回复]

    madper 回复:

    逻辑上会变得比较简单吧, 如果是老一辈的程序员, 应该会很喜欢表驱动的方法.

    [回复]

  6. iCyOMiK说道:

    谢谢,分享,不错。

    [回复]

  7. osily说道:

    如果val只是从1到n这样的,一个元组就可以了,如果不是显然用字典好些,不然凭空提到复杂度,代码也不简洁。
    c中也是,应该先考虑数组。其实这总情况用switch就很正常的,没人会说用switch臃肿。
    c++中除了数组,map可以应对更多情况。stl里的map不是用hash实现的,而是红黑树,是基于比较排序的。而python的map是用hash实现的。

    [回复]

    Dante 回复:

    这是我用这个方法写的统计时间段的函数:
    string get_maptime(int time_ms)
    {
    struct
    {
    int iTime;
    string strTimeKey;
    }arr_times[]={
    {5,”[0,5]“},
    {10,”(5,10]”},
    {50,”(10,50]”},
    {100,”(50,100]”},
    {200,”(100,200]”},
    {500,”(200,500]”},
    {1000,”(500,1000]”},
    {-1,”(1000,~)”},
    };
    int count = sizeof(arr_times) / sizeof(arr_times[0]);

    for (int i = 0; i < count; i++) { if (arr_times[i].iTime == -1 || time_ms <= arr_times[i].iTime) { return arr_times[i].strTimeKey; } } return “(1000,~)”;//实际上到不了这一步 } 其实主要是因为这个函数而写了这篇文章,可能文中的例子没有举好,让大家偏向map进行讨论了

    [回复]

  8. fleurer说道:

    喜欢这种写法。似乎在minix的源码里见过这种风格

    [回复]

    Dante 回复:

    哈哈,同好~

    [回复]

  9. 雨忆说道:

    可以用jump table 来代替switch吧。
    table driven 法?

    [回复]

    Dante 回复:

    咱俩其实一个意思,呵呵~

    [回复]

  10. Nona Mills说道:

    喜欢这种写法。似乎在minix的源码里见过这种风格

    [回复]

  11. Barbara Chavez说道:

    这是我用这个方法写的统计时间段的函数: string get_maptime(int time_ms) { struct { int iTime; string strTimeKey; }arr_times[]={ {5,”[0,5]“}, {10,”(5,10]”}, {50,”(10,50]”}, {100,”(50,100]”}, {200,”(100,200]”}, {500,”(200,500]”}, {1000,”(500,1000]”}, {-1,”(1000,~)”}, }; int count = sizeof(arr_times) / sizeof(arr_times[0]); for (int i = 0; i < count; i++) { if (arr_times[i].iTime == -1 || time_ms <= arr_times[i].iTime) { return arr_times[i].strTimeKey; } } return "(1000,~)";//实际上到不了这一步 }

    [回复]

  12. Keisha Carver说道:

    看来有必要好好读一下。。一直放在硬盘里。。

    [回复]

  13. 刺猬说道:

    这个实例比较简单,如果有很多case的话用表驱动法更清晰一些。
    不过对于只有几种情况的case,if-else我觉得更清晰

    [回复]

    Dante 回复:

    哈哈,同感!~

    [回复]

  14. zap说道:

    if或者switch的方法虽然代码比较繁琐,但是执行效率和代码体积都有优势,对嵌入式c来说,这个是更关键的。

    [回复]

  15. 李立强说道:

    其实可以这样
    char *print[] = {“this is one”, “this is two”, “this is three”}
    return print[val-1]; //或者加一项空串,然后就不用减去1了

    [回复]

    Dante 回复:

    呃。。不是想实现数组。。只是文中的例子数字恰好是连续的。。

    [回复]

    李立强 回复:

    那就做个转移表啊,用一个函数来返回下标,虽然效果差不多的但是看代码就爽多了,这两个方法我都是从《C和指针》中学的

    [回复]

  16. null说道:

    struct
    {
    int key;
    string strdata;
    }arr_datas[]={
    {1,”this is one”},
    {2,”this is two”},
    {3,”this is three”},
    };
    if (val>0 && val<4)
    return arr_datas[val].strdata;

    这样不是省去了for循环了.

    [回复]

    arthur 回复:

    如果传入的所以不是简单的自然数,可不是随便比较一下的问题。

    如果
    typedef enum{

    S_A = 178 <<16 | 1,
    S_B = 178 << 16 | 2
    ….
    S_C= 192 << 16 | 1,
    S_D = 192 << 16 |2,

    }e_idx;

    void get _value(e_idx idx)
    {
    if (idx == S_A)
    printf(…);
    else if (…)

    }
    试问,有简单的方法吗?加入enum有好几百,这个if就要好几百,可见用if会疯掉,用case可能更好,但是用table好解决吗? 呵呵

    [回复]

  17. endle说道:

    为啥我觉得 switch 搭配 define 和 enum 更简洁?

    [回复]

  18. sarrow104说道:

    其实“表驱动”只不过是“数据驱动”的前奏。

    这是把逻辑用数据来表现的需求。

    内嵌的脚步语言,也属于“表驱动”。一点小见解。

    [回复]

发表评论