⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tc13.dat

📁 C++指令字典 一个方便的软件 用于C++指令的查询
💻 DAT
📖 第 1 页 / 共 2 页
字号:

                                               {“000112”,“王五”,“女”,{1980,3,10}} };

/*主函数main()*/

main()

    { void display();                    /*函数说明*/

        int i=0;

        /*打印表头*/

        printf("No.    Name     Sex Birthday\n");

     /*打印内容*/

     for( ;  i<3;  i++)

          { display( student + i ); 

             printf("\n");

           }

    }

void  display(struct  std_info  *p_std) 

{  printf("%-7s%-9s%-4s",  p_std->no,

               p_std->name,  p_std->sex);

    printf("%4d-%2d-%2d\n",  p_std->birthday.year,

               p_std->birthday.month,  p_std->birthday.day);

}

                      [程序演示]

10.5  链表处理──结构指针的应用

10.5.1  概述

1.链表结构

链表作为一种常用的、能够实现动态存储分配的数据结构,在《数据结构》课程中有详细介绍.为方便没有学过数据结构的读者,本书从应用角度,对链表作一简单介绍.图10-1所示为单链表.

(1)头指针变量head──指向链表的首结点.

(2)每个结点由2个域组成:

1)数据域──存储结点本身的信息.

2)指针域──指向后继结点的指针.

(3)尾结点的指针域置为“NULL(空)”,作为链表结束的标志.

2.对链表的基本操作

对链表的基本操作有:创建、检索(查找)、插入、删除和修改等.

(1)创建链表是指,从无到有地建立起一个链表,即往空链表中依次插入若干结点,并保持结点之间的前驱和后继关系.

(2)检索操作是指,按给定的结点索引号或检索条件,查找某个结点.如果找到指定的结点,则称为检索成功;否则,称为检索失败.

(3)插入操作是指,在结点ki-1与ki之间插入一个新的结点k’,使线性表的长度增1,且ki-1与ki的逻辑关系发生如下变化:

插入前,ki-1是ki的前驱,ki是ki-1的后继;插入后,新插入的结点k’成为ki-1的后继、ki的前驱,如图10-2所示.

(4)删除操作是指,删除结点ki,使线性表的长度减1,且ki-1、ki和ki+1之间的逻辑关系发生如下变化:

删除前,ki是ki+1的前驱、ki-1的后继;删除后,ki-1成为ki+1的前驱,ki+1成为ki-1的后继,如图10-3所示.

3.C语言对链表结点的结构描述
       在C语言中,用结构类型来描述结点结构.例如:
      struct  grade

   { char  no[7];                            /*学号*/

      int  score;                            /*成绩*/

      struct  grade  *next;     /*指针域*/

    };

10.5.2  创建一个新链表

[案例10.7] 编写一个create()函数,按照规定的结点结构,创建一个单链表(链表中的结点个数不限).

基本思路:

首先向系统申请一个结点的空间,然后输入结点数据域的(2个)数据项,并将指针域置为空(链尾标志),最后将新结点插入到链表尾.对于链表的第一个结点,还要设置头指针变量.

另外,案例代码中的3个指针变量head、new和tail的说明如下:

(1)head──头指针变量,指向链表的第一个结点,用作函数返回值.

(2)new──指向新申请的结点.

(3)tail──指向链表的尾结点,用tail->next=new,实现将新申请的结点,插入到链表尾,使之成为新的尾结点.

/*案例代码文件名:AL10_7.C*/

#define   NULL  0

#define   LEN     sizeof(struct grade)       /*定义结点长度*/

/*定义结点结构*/

struct  grade

   { char  no[7];                                     /*学号*/

      int  score;                                     /*成绩*/

      struct  grade  *next;        /*指针域*/

    };

/*create()函数: 创建一个具有头结点的单链表*/

/*形参:无*/

/*返回值:返回单链表的头指针*/

struct grade *create( void )

    { struct grade *head=NULL, *new, *tail;

        int count=0;                                /*链表中的结点个数(初值为0)*/

        for(  ;   ;  )                                 /*缺省3个表达式的for语句*/

                { new=(struct grade *)malloc(LEN); /*申请一个新结点的空间*/

/*1、输入结点数据域的各数据项*/

printf("Input the number of student No.%d(6 bytes): ", count+1);

scanf("%6s", new->no);

if(strcmp(new->no,"000000")==0)    /*如果学号为6个0,则退出*/

      { free(new);                                    /*释放最后申请的结点空间*/

         break;                                          /*结束for语句*/

       }

printf("Input the score of the student No.%d: ", count+1);

scanf("%d", &new->score);

count++;                                        /*结点个数加1*/

/*2、置新结点的指针域为空*/

new->next=NULL;

/*3、将新结点插入到链表尾,并设置新的尾指针*/

      if(count==1)  head=new;  /*是第一个结点, 置头指针*/

      else  tail->next=new;        /*非首结点, 将新结点插入到链表尾*/

       tail=new;                         /*设置新的尾结点*/

     }

   return(head);

}                                                      [程序演示]

思考题:在设计存储学号数据的字符数组时,其元素个数应为学号长度+1.为什么?

10.5.3  对链表的插入操作

[案例10.8] 编写一个insert()函数,完成在单链表的第i个结点后插入1个新结点的操作.当i=0时,表示新结点插入到第一个结点之前,成为链表新的首结点.

基本思路:

通过单链表的头指针,首先找到链表的第一个结点;然后顺着结点的指针域找到第i个结点,最后将新结点插入到第i个结点之后.

/*案例代码文件名:AL10_8.C*/

/*函数功能:在单链表的第i个结点后插入1个新结点*/

/*函数参数:head为单链表的头指针,new指向要插入的新结点,i为结点索引号*/

/*函数返回值:单链表的头指针*/

struct grade *insert(struct grade *head, struct grade *new, int i)

    { struct grade *pointer;

        /*将新结点插入到链表中*/

if(head==NULL) head=new, new->next=NULL;          /*将新结点插入

                                                                                           到1个空链表中*/

else                      /*非空链表*/

       if(i==0) new->next=head,  head=new;       /*使新结点成为 链表

                           新的首结点*/

       else                              /*其他位置*/

          {  pointer=head;

              /*查找单链表的第i个结点(pointer指向它)*/

              for(;  pointer!=NULL && i>1;  pointer=pointer->next,  i--)  ; 

                   if(pointer==NULL)                      /*越界错*/

                        printf("Out of the range, can’t insert new node!\n");

                   else       /*一般情况:pointer指向第i个结点 */

                  new->next=pointer->next, pointer->next=new;

            }

       return(head);

   }          

10.6  共用型和枚举型简介

10.6.1  共用型
       1.概念
       使几个不同的变量占用同一段内存空间的结构称为共用型.
       2.共用类型的定义──与结构类型的定义类似
             union  共用类型名
                 {成员列表;};
       3.共用变量的定义──与结构变量的定义类似

(1)间接定义──先定义类型、再定义变量

例如,定义data共用类型变量un1,un2,un3的语句如下:  union  data  un1,un2,un3;

(2)直接定义──定义类型的同时定义变量

例如,union  [data] 

                 { int i;

                    char ch;

                    float f;

                 }  un1, un2, un3; 

共用变量占用的内存空间,等于最长成员的长度,而不是各成员长度之和.

例如,共用变量un1、un2和un3,在16位操作系统中,占用的内存空间均为4字节(不是2+1+4=7字节).

4.共用变量的引用──与结构变量一样,也只能逐个引用共用变量的成员

例如,访问共用变量un1各成员的格式为:un1.i、un1.ch、un1.f.

5.特点

(1)系统采用覆盖技术,实现共用变量各成员的内存共享,所以在某一时刻,存放的和起作用的是最后一次存入的成员值.

例如,执行un1.i=1, un1.ch='c', un1.f=3.14后,un1.f才是有效的成员.

(2)由于所有成员共享同一内存空间,故共用变量与其各成员的地址相同.

例如,&un1=&un1.i=&un1.ch=&un1.f.

(3)不能对共用变量进行初始化(注意:结构变量可以);也不能将共用变量作为函数参数,以及使函数返回一个共用数据,但可以使用指向共用变量的指针.

(4)共用类型可以出现在结构类型定义中,反之亦然.

10.6.2  枚举型

1.枚举类型的定义

        enum   枚举类型名   {取值表};

例如,enum  weekdays {Sun,Mon,Tue,Wed,Thu,Fri,Sat};

2.枚举变量的定义──与结构变量类似

(1)间接定义

例如,enum  weekdays  workday;

(2)直接定义

例如,enum  [weekdays] 

                 {Sun,Mon,Tue,Wed,Thu,Fri,Sat } workday;

3.说明

(1)枚举型仅适应于取值有限的数据.

例如,根据现行的历法规定,1周7天,1年12个月.

(2)取值表中的值称为枚举元素,其含义由程序解释.

例如,不是因为写成“Sun”就自动代表“星期天”.事实上, 枚举元素用什么表示都可以.

(3)枚举元素作为常量是有值的──定义时的顺序号(从0开始),所以枚举元素可以进行比较,比较规则是:序号大者为大!

例如,上例中的Sun=0、Mon=1、……、Sat=6,所以Mon>Sun、Sat最大.

(4)枚举元素的值也是可以人为改变的:在定义时由程序指定.

例如,如果enum weekdays {Sun=7, Mon=1 ,Tue, Wed, Thu, Fri, Sat};则Sun=7,Mon=1,从Tue=2开始,依次增1.

10.7  定义已有类型的别名

除可直接使用C提供的标准类型和自定义的类型(结构、共用、枚举)外,也可使用typedef定义已有类型的别名.该别名与标准类型名一样,可用来定义相应的变量.
        定义已有类型别名的方法如下:
      (1)按定义变量的方法,写出定义体;
      (2)将变量名换成别名;
      (3)在定义体最前面加上typedef.
       

[案例10.9]  给实型float定义1个别名REAL.
      (1)按定义实型变量的方法,写出定义体:float  f;
      (2)将变量名换成别名: float  REAL;
      (3)在定义体最前面加上typedef:typedef  float REAL;

[案例10.10]  给如下所示的结构类型struct date定义1个别名DATE.

struct date

     { int year,  month, day;

     };

(1)按定义结构变量的方法,写出定义体:struct date {……} d;

(2)将变量名换成别名:                                struct date {……} DATE;

(3)在定义体最前面加上typedef:              typedef struct date {……} DATE;

说明:

(1)用typedef只是给已有类型增加1个别名,并不能创造1个新的类型.就如同人一样,除学名外,可以再取一个小名(或雅号),但并不能创造出另一个人来.

(2)typedef与#define有相似之处,但二者是不同的:前者是由编译器在编译时处理的;后者是由编译预处理器在编译预处理时处理的,而且只能作简单的字符串替换.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -