• 注册 / 登录
  • 切换到窄版
  • 查看: 1559|回复: 0

    高效清晰的嵌入式C程序示例

    [复制链接]

    676

    主题

    690

    帖子

    6808

    积分

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    6808
    发表于 2023-12-21 13:38:17 | 显示全部楼层 |阅读模式

    路线栈欢迎您!

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    前言

    作为嵌入式工程师,怎么写出效率高、思路清晰的C语言程序呢?

    • 要用C语言的思维方式来进行程序的构架构建
    • 要有良好的C语言算法基础,以此来实现程序的逻辑构架
    • 灵活运用C语言的指针操作

    虽然看起来以上的说法很抽象,给人如坠雾里的感觉,其实就是用C语言进行遇到问题、分析问题和解决问题的过程。

    嵌入式工程师在编写C语言程序的时候,要针对遇到的问题进行程序构架构建。

    比如我们要处理“猴子选大王”的经典问题:一群猴子,手拉手排成一个圆,从任意一只猴子开始从1开始报数,当遇到要排除的数(预先设定)时该猴子退出该圈,从下一只猴子开始继续从1报数,如此反复,最终剩下的猴子便是猴子的大王。

    用C语言的思维方式进行程序构架构建

    程序分为三大部分:

    a、数据获取,为了程序的运行,上面的问题要获得猴子的总数,从那只猴子开始和剔除的个数;

    b、数据运算,需要从一堆数据中剔除相应的数据,注意逻辑的正确;

    c、提高程序的运行速率,少用循环多用指针。

    用C语言进行逻辑实现

    a、 数据获取,通过printf和scanf进行参数的获取。

    1. /* 读入问题条件 */
    2. printf("input total num:");
    3. scanf("%d", &n);
    4. printf("from which num begin:");
    5. scanf("%d", &k);
    6. if(k>n||k==0)
    7. {
    8. printf("please input the right begin num");
    9. return 1;
    10. }
    11. printf("input the out num:");
    12. scanf("%d", &m);
    13. if(m>n||m==0)
    14. {
    15. printf("please input the right del num");
    16. return 2;
    17. }
    复制代码

    同时注意异常时的处理,比如上面两个if语句就是异常情况的判断,每种异常情况对应不同的返回值,这样便于程序过程的调试和数据的合法性。

    b、 /* 定义链表节点类型 */


    1. typedef struct node
    2. {
    3. int data;
    4. struct node *next;
    5. }linklist;
    复制代码

    构建循环链表进行“猴子”的圆圈建设。

    1. /* 创建循环链表,头节点也存信息 */
    2. head = (linklist*) malloc(sizeof(linklist));
    3. p = head;
    4. p->data = 1;
    5. p->next = p;
    6. /* 初始化循环链表 */
    7. for (i = 2; i <= n; i++)
    8. {
    9. s = (linklist*) malloc(sizeof(linklist));
    10. s->data = i;
    11. s->next = p->next;
    12. p->next = s;
    13. p = p->next;
    14. }
    复制代码

    通过该步骤后,head和p(present)都成了一个“猴子圈”的链表。在该链表的构建过程中需要注意以下几点:内存的开辟,此时遵守使用多少开辟多少的原则。

    如果一下开辟过多,会引起内存泄露的问题,但是,这个小程序是不会遇到这种问题了。其次是熟悉循环链表的构建方法:链表的尾巴指向链表的头。这个时候有心的话还会联想到双向链表的情况。

    c、 /* 找到第 k 个节点 */

    1. p = head;
    2. for (i = 1; i <= k; i++)
    3. {
    4. p = p->next;
    5. }
    复制代码

    找到从第几个位置开始计数。此时,p指向开始的“猴子”。因为采用了链表方法,这个过程只需要关注p指针的next指向即可。

    d、 保存初始的“猴子”圆圈参数。

    1. /* 保存节点总数 */

    2. total = n;
    3. printf("\nthe out num:");
    4. q = head;
    复制代码

    为什么要保留这个呢?首先要控制猴子数目,所以保留了全部的数目。其次用q(qurry)来保留剔除猴子前面的链表,并连接剔除猴子后的链表。这样,完成了循环链表的元素删除。

    e、 猴子查数。

    猴子查数是整个程序的关键,需要完成以下任务:a、找到开始的“猴子”数;b、删除该“猴子”;c、将删除掉的循环链表首尾连接起来。

    1. /* 只剩一个节点时停止循环 */
    2. while (total != 1)
    3. {
    4. /* 报数过程,p指向要删除的节点 */
    5. for (i = 1; i < m; i++)
    6. {
    7. p = p->next;
    8. }
    9. /* 打印要删除的节点序号 */
    10. printf("[%d] ", p->data);
    11. /* q 指向 p 节点的前驱 */
    12. while (q->next != p)
    13. {
    14. q = q->next;
    15. }
    16. /* 删除 p 节点 */
    17. q->next = p->next;
    18. /* 保存被删除节点指针 */
    19. s = p;
    20. /* p 指向被删除节点的后继 */
    21. p = p->next;
    22. /* 释放被删除的节点 */
    23. free(s);
    24. /* 节点个数减一 */
    25. total--;
    26. }
    27. /* 打印最后剩下的节点序号 */
    28. printf("\n\nthe last num:[%d] \n\n", p->data);
    29. free(p);
    30. }
    复制代码

    通过以上数据运算,可以完成相应链表元素的删除,这或许就是C语言程序的魅力所在。

    使用C语言的指针

    比如本程序的链表指针的定义,p,s,q。

    1. linklist *head, *p, *s, *q;
    复制代码

    我们知道,指针操作不但可以减少数据操作需要的内存,还可以提高程序的运行速度。

    指针的优势,或许在本程序中表现的不明显,在大量数据和对操作速度要求比较敏感的情况下会很明显,比如Linux内核中,就会有很好的体现。

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|路丝栈 ( 粤ICP备2021053448号 )

    GMT+8, 2024-12-22 15:09 , Processed in 0.042014 second(s), 18 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表