发 帖  
原厂入驻New
实战多通道高速精密测温仪的全系列设计教程,以实际项目为依托,提升工程师核心竞争力!→点击立即抢购←

[经验] 朱兆祺教你如何攻破C语言学习、笔试与机试的难点(连载)

2013-7-31 08:47:54  183047 C语言 C语言 C语言 C语言 C语言
分享
341
本帖最后由 zzq宁静致远 于 2014-2-27 19:42 编辑

    再过1个月又是一年应届毕业生应聘的高峰期了,为了方便应届毕业生应聘,笔者将大学四年C语言知识及去年本人C语言笔试难点进行梳理,希望能对今年应届毕业生的应聘有所帮助。

2013年10月18日更新-->    攻破C语言这个帖子更新到这里,我不仅仅是为了补充大学学生遗漏的知识,我更重要的是希望通过我的经验,你们实际项目中的C语言写得漂亮,写出属于你的风格。“朱兆祺STM32手记”(http://bbs.elecfans.com/jishu_385613_1_1.html)一帖中我就多次强调过编程的模块化,要考虑到可移植性和别人的可阅读性。我在某公司实习的时候,拿到一个程序,我当时就想吐槽,我想除了这个程序的当时写作者能够看懂之外,其他人有谁还能看懂,程序构架、可移植性性就更是一塌糊涂。结果我全部推到重写。因此明志电子科技工作室从承接第一个项目做开始,我便和搭档说,我们必须制定我们工作室的编程规范和编程风格,这样就算给谁,换成谁,拿到项目都能马上接下去做。
    朱兆祺在这个帖子将会不断更新,明志电子工作室的项目经验也将在电子发烧友论坛不断贴出,我希望能用我们仅有的力量,将我们的经验毫不保留传授给大家。我只希望在未来某一天,有那么几个人会竖着大拇指说:明志电子科技工作室的经验受益匪浅就够了。我相信,在深圳,明志电子科技工作室的影响力会日益增长,因为我们已经规划好了未来脚步。
    C语言是一门技术,但更是一门艺术。写一个C语言代码不难,写一个高水平、漂亮的代码很难。朱兆祺将在此帖不断为大家攻破C语言。

<--朱兆祺于2013年10月18日

-->朱兆祺更新于2014年2月21日:
    深圳市馒头科技有限公司于2014年2月注册成立,当初命名为馒头科技,不管是吴坚鸿所说亲切还是谢贤斌所说草根。馒头科技永远以用户满意为我们的追求,馒头科技不追求锦上添花,但是我们很愿意为每一位客户雪中送炭。因为锦上添花每一个人都会做,但是雪中送炭却不是每一个人愿意去做。
    馒头科技往后将为每一位读者送上更为精美的学习资料。敬请期待。



第一节  C语言编程中的几个基本概念
http://bbs.elecfans.com/jishu_354666_1_1.html

第二节  数据存储与变量
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2088253&fromuid=222350

第三节  数学算法解决C语言问题
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2088283&fromuid=222350

第四节  关键字、运算符与语句
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2088352&fromuid=222350

第五节    C语言中的细节
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2088375&fromuid=222350

第六节  数组与指针
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2088417&fromuid=222350

第七节  结构体与联合体
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2088582&fromuid=222350

第八节  内存分配与内存释放
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2088596&fromuid=222350

第九节   笔试中的几个常考题
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2088606&fromuid=222350

第十节  数据结构之冒泡排序、选择排序
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2092632&fromuid=222350

第十一节   机试题之数据编码
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2096393&fromuid=222350

第十二节  机试题之十进制1~N的所有整数中出现“1”的个数
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2097513&fromuid=222350

第十三节  机试题之  遍历单链表一次,找出链表中间元素
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2103563&fromuid=222350

第十四节  机试题之全排序
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2105648&fromuid=222350


第十五节 机试题之大整数运算
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2109737&fromuid=222350


第十六节  机试题之大整数减法与乘法
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2115675&fromuid=222350

第十七节  算法之二分查找
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2128027&fromuid=222350

第十八节  数据结构之单向链表(颠覆你手中数据结构的三观)
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2139670&fromuid=222350

第十九节  数据结构之双向链表(接着颠覆你手中的数据结构三观)
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2156978&fromuid=222350

第二十节 数据结构之栈
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2193337&fromuid=222350


C语言技术公开课第一讲——编译环境给C语言带来的困扰,网络课程讲义
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2230571&fromuid=222350

第二十一节  通过加减法高效的求出两个无符号整数的商和余数
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2252461&fromuid=222350

第二十二节  表达式计算器(1)
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2280837&fromuid=222350

第二十三节  表达式计算器(2)
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2325485&fromuid=222350

第二十四节  表达式计算器(3)
http://bbs.elecfans.com/forum.ph ... 4547&fromuid=222350

第二十五节  表达式计算器(4)
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2395966&fromuid=222350

C语言技术公开课第三讲  const问题
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2434706&fromuid=222350

第二十六节  序列差最小
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2466868&fromuid=222350

第二十七节  sizeof与strlen的深入
http://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=354666&pid=2676569&fromuid=222350

第二十八节  C与C++中的const

第二十九节 do、while
第三十节 变量的生命周期

第一节  C语言编程中的几个基本概念
1.1      include< >与#include" "


1.   #include< >和#include" "有什么区别?
这个题目考查大家的基础能力,#include< >用来包含开发环境提供的库,
#include" "用来包含.c/.cpp文件所在目录下的头文件。注意:有些开发环境可以在当前目录下面自动收索(包含子目录),有些开发环境需要指定明确的文件路径名。
1.2      switch()
1.   switch(c) 语句中 c 可以是 int, long, char, float, unsigned int 类型?
其实这个题目很基础,c应该是整型或者可以隐式转换为整型的数据,很明显不能是实型(float、double)。所以这个命题是错误的。
1.3      const
1.   const有什么用途?
虽然const很常用,但是我相信有很多人仍然答不上来。
(1) 欲阻止一个变量被改变,可以使用const 关键字。在定义该 const 变量时,通常需要对它进行初 始化,因为以后就没有机会再去改变它了;
(2) 对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指定为 const;
(3) 在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4) 对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成员变量;
(5) 对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左值”。
1.4      #IFndef/#define/#endif
1.   头文件中的 #ifndef/#define/#endif 干什么用?
其实#ifndef、#define、#endif这些在u-boot、linux内核文件中经常见到,在这么大型的程序中大量使用,可见它的作用不可小觑。
这些条件预编译多用于对代码的编译控制,增加代码的可裁剪性,通过宏定义可以轻松的对代码进行裁剪。
#ifndef/#define/#endif最主要的作用是防止头文件被重复定义。
1.5      全局变量和局部变量
times New Roman">1.         全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
全局变量储存在静态数据库,局部变量在堆栈。 其实,由于计算机没有通用数据寄存器,则函数的参数、局部变量和返回值只能保存在堆栈中。提示:局部变量太大可能导致栈溢出,所以建议把较大数组放在main函数外,防止产生栈溢出。
思考:如程序清单1. 1所示。会出现怎样的情况?
程序清单1. 1  大数组放在main函数中导致堆栈溢出
int main(int argc, char *argv[])
{
    int iArray[1024 * 1024];
    return 0;
}






评分

参与人数 3威望 +7 +7 积分 +10 收起 理由
eminjie + 2 + 2
A670521546 + 5 + 5 很精彩,期待您更多的分享
冰葑世纪 + 5 + 5 您的付出是论坛的动力,感谢您一直支持!.

查看全部评分

zzq宁静致远 2013-8-14 14:20:33
第十八节  数据结构之单向链表
链表在数据结构中讲得太多,但是都是炒来炒去没有一个是具有高移植性、易理解性等,以至于很多学习C语言的学生看到C语言都是畏惧三分,
朱兆祺这节带着你且看如何写出高效率、通俗易懂的单向链表,看完这节,你要是没有撕掉你手中的数据结构书本,那就是我写得还不够好,那么
请你联系我,我再改,直到你有撕掉你手中数据结构书本的感觉为止。
typedef   unsigned int     ElementType ;
/* 数据类型定义 */
typedef   struct   _SingleListNode {
          ElementType               data  ;
          struct _SingleListNode       *next ;
}SingleListNode;
typedef   SingleListNode*   SingleList  ;
typedef   SingleListNode*   Position   ;

首先要创建一个头节点,并在内存中为头节点动态分配存储空间。

/* 申请存储空间,建立头节点 */
SingleListNode *pHead = (SingleListNode*)malloc( sizeof(SingleListNode) ) ;
pHead定义为(SingleListNode *)类型,malloc函数的原型为void *malloc( size_t size ); 函数指向一个大小为size的空间,存储空间的指针必须为堆,不能是栈。因为不知道开辟的空间是什么类型,所以malloc函数返回的是(void*)类型,再通过强制转换为我们想要的类型。由于data4个字节,next4个字节,所以sizeof(SingleListNode) = 8。所以*pHead所指向的数据类型(即为链表节点)占用8个字节。
#if 1
    printf("sizeof(SingleListNode) = %d \n" , sizeof(SingleListNode) ) ;
    printf("sizeof(*pHead)       = %d \n" , sizeof(*pHead) ) ;
         printf("sizeof(pHead)       = %d \n" , sizeof(pHead) ) ;
#endif
输出结果为:8,8,4
创建链表即要将data和next置空。
pHead->next = NULL ;                         //将头节点指针域置空
pHead->data = NULL ;                         //将头节点数据域置空
在将节点插入到链表之前,首先得为这个待插入的节点申请存储空间,并且建立该节点的指针ptr。
SingleListNode *ptr = (SingleListNode *)malloc( sizeof(SingleListNode) ) ;
这里ptr为待插入节点的指针,ptr的值即为待插入链表的节点的地址。*ptr即为节点中存储的数据:datanext,共占8个字节。
待插入节点插入链表第一步,将数据x保存到ptr->data
ptr->data = x ;
待插入节点插入链表第二步,将pos->next赋给ptr->next。
ptr->next = pos->next ;
待插入节点插入链表第三步,将pos->next指向待插入节点。
pos->next = ptr ;
这样我们就完成了将数据x的节点插入到链表中。
#if 1
     printf(" x    = %c \n" , x ) ;
         printf("&x   = %#x \n" , &x ) ;
         printf(" ptr   = %#x \n" , ptr ) ;
         printf("&ptr  = %#x \n" , &ptr ) ;
         printf("(pos->next) = %#x \n" , (pos->next) ) ;
         printf("(ptr->next) = %#x \n\n" , (ptr->next) ) ;
#endif
在插入节点函数中加入调试代码,运行程序,输入abc,调试结果。
请输入链表节点数据:  abc
x    = a
&x    = 0x12fe3c
ptr  = 0x392920
&ptr  = 0x12fe24
(pos->next) = 0x392920
(ptr->next) = 0
x    = b
&x    = 0x12fe3c
ptr  = 0x392958
&ptr  = 0x12fe24
(pos->next) = 0x392958
(ptr->next) = 0
x    = c
&x    = 0x12fe3c
ptr  = 0x392990
&ptr  = 0x12fe24
(pos->next) = 0x392990
(ptr->next) = 0
ListData:  abc
ListAddress:  0x394b48  0x392920  0x392958  0x392990
通过上面的调试,我们将数据和地址放进节点,便于我们明白链表的储存。
可以看到pos->next是和ptr相等的,因为两者都是指向待插入节点,而ptr->next始终是为0,因为ptr->next是指向NULL
从中我们还可以看出,链表的存储空间是间断的,而不是像数组元素存储空间是连续的。
/*************************************************************************
** 函数名称 sll_FindPrevious
** 函数功能 :单向链表按值搜索位置的前驱算法函数
** 入口参数 pList ,
** 出口参数 pCur
*************************************************************************/
Position sll_FindPrevious(SingleList pList , ElementType x)
上面这个函数得明白什么叫做函数指针,什么叫做指针函数。
void  *Func ()  :指针类型的函数
void  (*Func)() :一个指向void型函数的指针
定义一个结构体指针pCur,使其总是指向当前搜索节点的前一个节点。初始状态下pCur是指向头结点。
Position pCur ;
pCur = pList ;                               //pCur的初值指向头节点
从第一个节点开始比较pCur指向下一个节点的数据域和数据x的值,如果两者相等,则返回pCur;否则pCur重新指向下一个节点。
while ( (pCur->next) && (pCur->next->data) != x) {
                   pCur = pCur->next ;                      //pCur重新指向下一个节点
         }
return pCur ;                                     //返回已找到元素x所在节点的地址
删除节点和插入节点是相对应的,在删除节点之前,我们先要找到需要删除节点的位置,此时,我们就可以使用按值搜索节点位置的前去算法找到需要删除的节点位置。
/*************************************************************************
** 函数名称 sll_delete
** 函数功能 :删除节点函数
** 入口参数 pList x
** 出口参数 void
*************************************************************************/
void sll_delete(SingleList pList , ElementType x)
Position pCur , temp ;                       //pCur指向要删除节点的上一个节点,temp指向删除的节点
pCur = sll_FindPrevious(pList , x) ;            //返回需要删除的节点的上一个节点地址
如果sll_FindPrevious能返回删除节点的位置(即pCur不为NULL),那么执行删除该节点的操作。
if ( pCur && (pCur->next) )
删除操作第一步,让temp指向待删除的节点。
temp       = pCur->next ;
删除操作第二步,让pCur->next指向待删除节点的下一个节点,这样就把待删除节点*temp删除。
pCur->next = temp->next ;
最后将已经删除了的节点temp的存储空间释放掉。
free(temp)              ;  
在删除节点函数中添加调试代码,在删除节点前和删除节点后都加入,进行前后对比。
#if 1
         printf("pCur       = %#x \n" , pCur) ;
         printf("pCur->next = %#x \n" , pCur->next) ;
         sll_printAddress(pList) ;
         printf("\n\n") ;
#endif
         if ( pCur && (pCur->next) ) {
                   temp       = pCur->next ;               
                   pCur->next = temp->next ;               
                   free(temp)              ;            
         }
#if 1
         printf("pCur       = %#x \n" , pCur) ;
         printf("pCur->next = %#x \n" , pCur->next) ;
         sll_printAddress(pList) ;
         printf("\n\n") ;
#endif
调试代码的输出。
请输入链表节点数据:  abc
ListData:  abc
ListAddress:  0x394b48 0x392920 0x392958 0x392990
输入要删除的字符:  b
pCur       = 0x392920
pCur->next  = 0x392958
0x394b48  0x392920  0x392958  0x392990
pCur       = 0x392920
pCur->next  = 0x392990
0x394b48  0x392920  0x392990
ListData:  ac
请按任意键继续. . .
通过前后比较可以知道,我们删除了0x392958这个地址的节点,即为储存b的节点。
如果这个链表不再需要使用,则要把这个链表销毁掉。销毁办法是一个一个节点释放掉。
销毁链表第一步,让待销毁的节点指针(ptr)指向头节点(初始时,pList是指向头结点)。
SingleListNode *ptr = pList ;
销毁链表第二步,让现在pList所指的节点的下一个节点成为头节点,因为现节点将要被删除,直到所指节点为空为止。
pList = pList->next ;
销毁链表第三步,释放掉待销毁节点。
free(ptr)           ;

销毁链表第四步,让下一个节点(即为pList现在所指节点)成为待删除节点。
ptr   = pList ;
这样往复循环,直到ptr指向NULL为止。这样就成功把一个链表销毁了。
在销毁链表函数中加入调试代码,运行。
#if 1
                   printf("ptr       = %#x \n" , ptr) ;
                   sll_printAddress(pList) ;
                   printf("\n\n") ;
#endif
运行结果,
ptr       = 0x394b48
0x392920  0x392990  0x3929c8
ptr       = 0x392920
0x392990  0x3929c8
ptr       = 0x392990
0x3929c8
ptr       = 0x3929c8
请按任意键继续. . .
我们可以看到当前删除的节点地址ptr,和删除节点之后各节点的地址。
回复

举报

zjdzjw195210 2013-8-14 14:23:16
学习。。。。。
回复

举报

zjdzjw195210 2013-8-14 14:41:03
谢谢给一份:1543905886@qq.com
回复

举报

liyang1020 2013-8-14 17:00:00
楼主的大恩大德无以言谢。
回复

举报

langlibaidi 2013-8-14 22:02:21
收藏了!!!!!!!!!!!!!!
回复

举报

effort080622 2013-8-14 22:37:38
good,非常好的教程啊
努力学习啊
回复

举报

Naga1991 2013-8-15 08:35:57
确实不错啊看了一下   有基础  都是单片机所用的基础知识 很不错
回复

举报

190471306 2013-8-15 10:09:00
好好。。。。。。。。。。。。。。。{:23:}{:23:}
回复

举报

美丽心灵宗 2013-8-15 11:39:02
好东西,别忘了顶一下!
回复

举报

mikeboy 2013-8-15 15:42:39
谢谢楼主,很好的讲解,麻烦发一份给我好吗?241761140@qq.com
回复

举报

生无所息1 2013-8-15 16:08:08
老师啊,好人啊
回复

举报

xinyi61 2013-8-15 16:27:42
好东西  学习了  谢谢分享
回复

举报

aailong 2013-8-15 16:28:02
顶一个!!!!!!!!!1
回复

举报

xinyi61 2013-8-15 16:31:39
好东西  学习了  谢谢分享
回复

举报

聂敏林 2013-8-15 17:20:49
好东西 啊   谢谢学长 啊
回复

举报

infiniti 2013-8-15 18:16:42

不错的C语言初级学习和面试
回复

举报

社区化 2013-8-15 18:18:40
谢谢学长 啊
回复

举报

吟啸徐行 2013-8-15 18:34:58
哈哈,好帖。正好过几个月就要考二级了。
回复

举报

语诺 2013-8-16 00:12:36
真正的牛人                           
回复

举报

m_tly! 2013-8-16 13:46:31
很好。收藏啦。
回复

举报

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

发经验
课程
    关闭

    站长推荐 上一条 /10 下一条

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