【C语言】文科普通211如何转行做开发

【C语言】自力更生谢谢

文科生,本科与硕士都是商科211,前几个月还在券商实习(债券承做),现在接触了一个我以前没了解过的领域,C语言,然后深深被它吸引。在接触C语言之前,由于学术研究的需要,我也学习过Python与R语言的粗浅知识。但当时均没有感受到此时学习C语言的快乐。
所以我开始记录自己学习的一个路线图。因为相对于专业出身(比如计算机及相关专业)的朋友们而言,我这个属于盆地起步。但是,也许是年轻给了我一点勇气,让我开始不再顾及其他。
今天看了启舰老师的文章,https://blog.csdn.net/harvic880925/article/details/102774769
我觉得深有感悟。认为学校、经验都非常重要。然而我的专业(工商管理)与学校(上海某211)估计对我求职是不能帮什么忙。但是我不是一个人在奋斗,很多人都不是一开始就清楚自己喜欢干什么,能够为什么事物奉献青春,只要明白的那一刻开始行动,我就是对的,我认为这没问题。
在自学的过程中,我会努力坚持做博客。希望后面能认识一些朋友一起进步,比如一些像我一样不是计算机专业,但是后期意识到自己很喜欢计算机的人嘻嘻。

学习C语言第11天20200703-链表详解(一)

C,C++,计算机网络结构。我觉得要入门可以先系统学习这几门课,因为大学课程也都是浅浅掠过所以不用以大学模式来进行,按自己的进度来走。C语言学习第11天,完成指针、链表初步学习。

先来说一下前几周学习C语言的感受:
因为我现在这么菜并没有真知灼见,就谈一下感受。有两个内容非常非常有意思,一是递归,二是链表。
以前学经管模型更适用于长期与模糊问题的研究,也就是一般理论的研究,我没有太大的兴趣。。。。反之编程就可以更灵活地模拟实际情况,模拟一些没那么可能看到的情况。递归就是很好的例子,可以从始至终地输出问题的结果,每一步跟着特定的参数,中间添加或删减变量。还可以模拟如永远无法得出结果的问题、以及极端情况。

然后另外一个是链表。这个也是大把人写博客,我就总结一下自己的想法。
链表的作用主要在于节约内存,只要会用连接节点的方法,基本上可以搭建任何种类的链表,来代替已有的结构。

附上MOOC北京理工大学C语言程序设计(下)的代码。

#include<stdio.h>
#include<stdlib.h>
struct  node
{  char name[20],address[20],phone[15];
    struct node  * link;       /*定义node型结构指针 */
};                               /* 定义结构 */
typedef node NODE;       /* 定义结点类型 */

main() 
{
    NODE * head ;
    NODE * p;
    p = ( NODE * ) malloc ( sizeof (NODE) ) ;  /* 开辟新存储区,申请表头节点 */
    p->link = NULL;    /* 将表头节点的link置为NULL*/
    head = p;
    int create ( NODE * head , int n );
    create ( head , 2 );
    int insert_node ( NODE * head , NODE * p , int i );
     
    p = ( NODE * ) malloc ( sizeof (NODE) ) ; 
    gets(p->name);
    insert_node(head, p, 1);
 
     
    int output ( NODE * head );
    output(head);
     
    int delete_node ( NODE * head , int i );
    delete_node(head,2);
 
    output(head);
 
    getchar();
}
 
int create ( NODE * head , int n )
{   NODE * p;
    for ( ;  n>0 ;  n-- )
    { p = ( NODE * ) malloc ( sizeof(NODE)) ;
      gets ( p->name);
      p->link = head->link;   
      head->link = p;
    }
    return 0;
}
 
int output ( NODE * head )
{ 
    NODE * p;
    p = head->link;             /* p 指向第一个数据节点 */
    while ( p!=NULL )
    {   puts (  p->name ) ;   /* 输出 p 所指向节点的数据 */
        p = p->link ;     /* p 指向下一个数据节点 */
    }
    return 0;
}
 
int insert_node ( NODE * head , NODE * p , int i )
{ 
    NODE * q;
      int n=0;
      for ( q = head;  n<i && q->link!=NULL; ++n )
        q = q->link;   /* ① 定位 */
      p->link = q->link;    /* ② 链接后面指针 */
      q->link = p;       /* ③ 链接前面指针 */
    return 0;
}
 
int delete_node ( NODE * head , int i )
{
    NODE * q, * p;
   int n;
    for ( n=0, q = head;  n<i-1 && q->link!=NULL; ++n )
       q = q->link;                /* ① 定位 */
    if  ( i>0 && q->link != NULL )   
    { 
        p = q->link;             /* p 指向被删除节点 */
        q->link = p->link;  /* ② 摘链 */
       free ( p );      /* ③ 释放 p节点 */
    }
}

(此代码来源于中国大学MOOC北京理工大学课程)
插入节点流程图解析(左上画错了)
(此图借鉴于中国大学MOOC北京理工大学课程)

从上图可以看到节点中,p作为指针起到一个搭桥的作用。每次新创建一个节点都会有一个相应的指针p出现,创建完了这个p就没用了与此同时留下的是一个NODE类型的结构,里面带有数据域(比如放一个name),以及指针域。在这个代码示例中指针域用 *link,有的地方用 *next,本质上都是一样的,都是用来指向下一个指针。

如果还觉得理解不了,可以这么想。head和p分别指向一个结构体的地址,而head->link,其实就是head所指的这一个NODE结构体中的指针域,所指向的下一个结构体的地址。p->link指的就是指针p所指的NODE结构体中的指针域,所指向的下一个结构体的地址。

学习C语言第12天@20200704-链表详解逐条分析(二)

本人立志不肝,虽盆地起步,仍该睡就睡,今天继续完善链表的话题,我们来逐字逐句分析上面这串代码(初学者的苦,大佬们不懂),这个MOOC视频里说得非常简略,我听的时候是不懂的,所以才有必要这样分析。我后面分享的话题都会按照自己一下子听不懂的来走。

(1)创建结构

struct  node
{  char name[20],address[20],phone[15];
    struct node  * link;       /*定义node型结构指针 */
};                               /* 定义结构 */
typedef node NODE;       /* 定义结点类型 */

这个简单,插入一个名为node的结构,其中指针域名为link,指向node型结构,以后建立的节点的数据域都是按这个格式来的。然后用typedef来命名node结构为NODE,可能是为了配合其他语言吧,因为不这么做也可以。

(2)创建不含数据的空链表

    NODE * head ;
    NODE * p;
    p = ( NODE * ) malloc ( sizeof (NODE) ) ;  /* 开辟新存储区,申请表头节点 */
    p->link = NULL;    /* 将表头节点的link置为NULL*/
    head = p;

这个就是我给的结构图上面说的不含数据的空链表,是一个创建链表的初始环节。p是指向初始节点地址的指针,p->link=NULL说明这个结构体中的指针域没有下家。head=p是说head所指的地址和p是一样的。

(3)创建链表框架

    int create ( NODE * head , int n );
    create ( head , 2 );

这里需要和我们自己定义的create函数的代码结合起来看。这个函数是用来建立这个单链链表的框架的,输入为头指针以及需要的节点的个数。这里函数也可以定义成void格式,如果是void就要把return 0删掉。

int create ( NODE * head , int n )
{   NODE * p;
    for ( ;  n>0 ;  n-- )
    { p = ( NODE * ) malloc ( sizeof(NODE)) ;
      gets ( p->name);
      p->link = head->link;   
      head->link = p;
    }
    return 0;
}

这个就是定义create函数的代码。建立一个在函数内部用的p指针,前面提到过,这个p只是用来搭桥的,所以可以在函数内部定义,函数运行完就扔
然后来一个for循环,这样你想建几个节点就建几个。p = ( NODE * ) malloc ( sizeof(NODE))是用来创建节点的。*malloc是在<stdlib.h>下的一个,指向既定大小内存空间的指针,用来创建一个节点。内存大小是malloc函数的变量,sizeof(NODE)就是根据我们定义的NODE结构需要的内存。前面( NODE*)就是将malloc创建的指针转化成一个指向NODE结构的指针(就是经常被提到的强制转化)。
合起来理解为,p = ( NODE * ) malloc ( sizeof(NODE))让我们有了一个指向有NODE结构空间的指针。(我是不是有点啰嗦?)
然后就可以在这个空间里增加数据。比如这里很简单第加了条name数据,从(1)可以知道name是一个长度为20的字符串,所以我们按顺序输入字符串就好了。与此同时也可以加两条语句,比如gets(p->address); gets(p->phone); 或者修改(1)中的结构,我们就能够拥有存储了更丰富数据的链表。

然后**p->link=head->link;**这个其实很不好理解,会者不难难者不会,老师就讲三句话我真滴不懂。不过其实自己再思索一下还是可以理解的。使p指向的结构体中的指针域的指向,与head指向的结构体中的指针域的指向相同。意思就是让新建立的节点的指针指向head所指的结构体的指针指向的那个结构体(头部节点指向的节点)。下面head->link = p修改了head所指的结构体的指针的指向,使其指向指针p。按照我下面这个步骤对照图来理解,我图上画斜线和叉叉的部分也是有意义的(除了左上角画错了)。

第一步:p = ( NODE * ) malloc ( sizeof(NODE));创建第一个节点
第二步:gets ( p->name);输入数据
第三步:p->link = NULL ( head->link = NULL) ;第一个节点链接到无
第四步:head->link = p; 表头节点链接到新节点
第五步:p = ( NODE * ) malloc ( sizeof(NODE)); 创建第二个节点
第六步:gets ( p->name);输入数据
第七步:p->link = head->link; 第二个节点链接到表头节点后面那个节点
第八步:head->link = p; 表头节点链接得到新节点

从此以后,你想设置n多大都行,这个程序会逐步在表头后面建立新的节点,放入你输入的数据。但是有可能输出的时候就是你最后输入的最先输出,后进先出。有具体需求再改源代码把,我们先理解这个思想。

(4)插入节点

    int insert_node ( NODE * head , NODE * p , int i );
     p = ( NODE * ) malloc ( sizeof (NODE) ) ; 
    gets(p->name);
    insert_node(head, p, 1);

这一条说明了insert_ node这个函数类型及参数。上面那一段已经建立了一个链表的框架,这个函数用于在链表的特定位置插入一个节点,需要输入表头指针head,刚刚建立的节点的指针p,以及位置i。

int insert_node ( NODE * head , NODE * p , int i )
{ 
    NODE * q;
      int n=0;
      for ( q = head;  n<i && q->link!=NULL; ++n )
        q = q->link;   /* ① 定位 */
      p->link = q->link;    /* ② 链接后面指针 */
      q->link = p;       /* ③ 链接前面指针 */
    return 0;
}

首先再定义一个用于搭桥的指针q,以及一个用于循环的整数n。以head指针为起点,在还没有到达位置i之前,并且这个链表没有结束之前,持续一个for循环。(注意,这里的for,只针对后面第一行代码循环)。最终后面两行代码将会在最终定位到的节点后面插入一个新的节点。如下图所示:
在这里插入图片描述
(5)输出链表

int output ( NODE * head );
   output(head);

现在说明一个整型的函数output来输出链表,输入变量为表头指针。

int output ( NODE * head )
{ 
    NODE * p;
    p = head->link;             /* p 指向第一个数据节点 */
    while ( p!=NULL )
    {   puts (  p->name ) ;   /* 输出 p 所指向节点的数据 */
        p = p->link ;     /* p 指向下一个数据节点 */
    }
    return 0;
}

定义这个函数,p为搭桥的指针,先让p指向第一个数据节点(这一步看不懂再看回前文,真的很清楚辽)。然后在后面的while循环里面,首先puts ( p->name )输出第一个数据节点的内容,这里可以根据所定义的结构来调整。然后让p指向下一个数据节点,判断下一个节点是不是NULL(只有在puts出了最后一个节点数据之后,p才会指向NULL)。循环这个结构直到输出了所有的节点,结束。

(6)删除节点

 int delete_node ( NODE * head , int i );
    delete_node(head,2);

说明一个删除节点的函数,输入表头指针head以及位置i。

int delete_node ( NODE * head , int i )
{
    NODE * q, * p;
   int n;
    for ( n=0, q = head;  n<i-1 && q->link!=NULL; ++n )
        q = q->link;                /* ① 定位 */
    if  ( i>0 && q->link != NULL )   
    { 
        p = q->link;             /* p 指向被删除节点 */
        q->link = p->link;  /* ② 摘链 */
       free ( p );      /* ③ 释放 p节点 */
}

定义两个桥指针,q以及p。首先q指向需要摘链的前一个节点,这个很好理解。
然后p指向需要摘链的节点(这个看不懂,同样可以看一下前面(4)插入节点)。
q->link = p->link; 表示,q所指向的节点,直接跳过p所指向的节点,指向p的下一个节点。
然后p就free,free和malloc是一组打包操作,通过malloc建立的内存只有通过free来释放。

关于我的起步,还有链表一些基础的内容就到这里。今天继续弄其他的

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值