如何编写高效清晰的嵌入式C程序

简介: 如何编写高效清晰的嵌入式C程序

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

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

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

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

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

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

程序分为三大部分:

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

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

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

用C语言进行逻辑实现

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

/* 读入问题条件 */printf("input total num:");scanf("%d", &n);printf("from which num begin:");scanf("%d", &k);if(k>n||k==0){printf("please input the right begin num");return 1; }printf("input the out num:");scanf("%d", &m);if(m>n||m==0){ printf("please input the right del num");return 2; }

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

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

typedef struct node{int data;struct node *next;}linklist;

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

/* 创建循环链表,头节点也存信息 */head = (linklist*) malloc(sizeof(linklist));p = head;p->data = 1;p->next = p;/* 初始化循环链表 */for (i = 2; i <= n; i++){s = (linklist*) malloc(sizeof(linklist));s->data = i;s->next = p->next;p->next = s;p = p->next;}

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

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

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

p = head;for (i = 1; i <= k; i++){p = p->next;}

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

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

/* 保存节点总数 */total = n;printf("\nthe out num:");q = head;

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

b、 猴子查数。

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

/* 只剩一个节点时停止循环 */while (total != 1){/* 报数过程,p指向要删除的节点 */for (i = 1; i < m; i++){p = p->next;}/* 打印要删除的节点序号 */printf("[%d] ", p->data);/* q 指向 p 节点的前驱 */while (q->next != p){q = q->next;}/* 删除 p 节点 */q->next = p->next;/* 保存被删除节点指针 */s = p;/* p 指向被删除节点的后继 */p = p->next;/* 释放被删除的节点 */free(s);/* 节点个数减一 */total--;}/* 打印最后剩下的节点序号 */printf("\n\nthe last num:[%d] \n\n", p->data);free(p);}

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

使用C语言的指针

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

linklist *head, *p, *s, *q;

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

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

目录
相关文章
|
人工智能 自然语言处理 IDE
通义灵码使用指南
一款不用充钱也能让你变强的插件 通义灵码(TONGYI Lingma),可以称之为中国copilot 的平替品。我们一起看看如何使用安装,功能介绍,常用问题,客户测评等。
7107 12
通义灵码使用指南
|
机器学习/深度学习 人工智能 算法
|
Java API 调度
掌握Java线程状态:从NEW到TERMINATED
本文探讨了操作系统与Java中线程的状态及其转换。操作系统层面,线程状态包括初始、就绪、运行、阻塞和终止。Java线程状态则细分为NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,并详细介绍了各状态的特性和转换条件。此外,还列举了Java中常用的线程方法,如`wait()`、`notify()`、`start()`和`join()`等,帮助理解线程控制机制。
288 3
掌握Java线程状态:从NEW到TERMINATED
|
11月前
|
监控 小程序 JavaScript
讯飞-微信小程序-语音助手
讯飞-微信小程序-语音助手
321 1
讯飞-微信小程序-语音助手
|
存储 缓存 IDE
CAN通信的基本原理与实现方法
CAN通信的基本原理与实现方法
1873 1
|
运维 Kubernetes Devops
构建高效自动化运维体系:DevOps与容器化技术融合实践
【5月更文挑战第6天】随着企业IT架构的复杂化以及快速迭代的市场需求,传统的运维模式已难以满足高效率和高质量的交付标准。本文将探讨如何通过结合DevOps理念和容器化技术来构建一个高效的自动化运维体系,旨在实现持续集成、持续部署和自动化管理,提升系统的可靠性、可维护性和敏捷性。
|
数据挖掘 iOS开发 MacOS
Python数据分析:从导入数据到生成报告的全面指南
随着数据科学和人工智能的迅速发展,Python 已经成为了最受欢迎的数据分析语言之一。Python 具有简单易学、灵活性强、可扩展性高等优点,使其在数据分析领域具有广泛的应用。本文将介绍 Python 数据分析的基本步骤,帮助你了解如何使用 Python 进行数据分析。
|
机器学习/深度学习 算法 数据挖掘
4小时学完!15年技术大牛用247个实战案例剖析的Python教程
今天给小伙伴们分享一份15年技术大牛用247个实战案例剖析的Python教程,这份教程全程彩图讲解,告别枯燥!60秒学会⼀个⼩例⼦,带你系统学习Python,从⼊门到⼤师。 涵盖了Python基础、Python字符串和正则、Python⽂件和⽇期、Python三⼤利器、Python绘图、Python之坑、Python第三⽅包、机器学习和深度学必知算法、Python实战、Pandas数据分析案例实战十大篇幅的精品案例教程
|
XML 数据格式
Karl_Albright:Rougamo、Fody 实现静态Aop
4. Fody 有很多其他的“插件”,大家可以多试试 AutoProperties.Fody: 这个外接程序为您提供了对自动属性的扩展控制,比如直接访问backing字段或拦截getter和setter。 PropertyChanged.Fody: 将属性通知添加到实现INotifyPropertyChanged的所有类。 InlineIL.Fody: 在编译时注入任意IL代码。 MethodDecorator.Fody:通过IL重写编译时间装饰器模式。 NullGuard.Fody: 将空参数检查添加到程序集。
153 4