结构体和它在链表中的使用

一.结构体

由不同类型的数据组合成一个整体,以便引用,这些组合在一个整体中的数据是互相联系的。

1.1如何声明结构体呢?

struct 结构体名  //结构体名字用作结构体类型的标志

{成员列表};    

比如:

 

1 struct student
2 {
3   int num;  //2
4   char name[20];  //20
5   char sex;  //1
6   int age;  //2
7   float score;  //4
8   char addr[30];  //30
9 };

 

注意:声明只是指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际内存单元。为了能在程序中使用结构类型的数据,应当定义结构体类型的变量....

1.2如何定义结构体变量呢?

方法一:可以在声明的同时定义。在第9行分号前面添加 “student1,student2” 即可表明,student1和student2就是student结构体的两个变量。在定义了结构体变量后,系统会为之自动分配内存,上述就分配了59个字节。

一般形式为:

struct 结构体名

{

 成员表列

}变量名表列;

方法二:直接定义结构类型变量。此形式不出现结构体名!

一般形式为:

struct 

{

  成员表列

}变量名表列;

此处特别强调:类型和变量的区别,变量能进行赋值、存取、和运算,但是类型不行。在编译时,类型是不分配空间的,只能对变量分配空间。所以,对结构体里面的各个的成员可都以单元使用,因为它是有内存的。那么怎么去用结构体里面的成员呢?接下来就告诉你!

方法3:在已经声明/定义了结构体类型时,利用了类型名称定义结构体变量!

struct student student1;  //student1是变量名;struct student 是变量类型名称

 

1.3如何使用结构体成员变量

复制代码

 1 #include <stdio.h>
 2 struct student
 3 {
 4   long int num;
 5   char name[20];
 6   char sex;
 7   char addr[30];
 8 }a = {89031, "Li Lin", 'M', "123 Beijing Road"};    //定义了结构体变量,并给予赋值
 9 void main()
10 {
11   printf("NO. : %d\nname: %s\nsex: %c\naddress: %s\n", a.num, a.name, a.sex, a.addr) //输出结构体成员的值
12 }

复制代码

但是需要注意以下几点:

(1)不能将一个结构体变量作为一个整体进行输入和输出,只能对结构体变量在的各个成员分别进行输入输出!

  引用结构体变量中成员方式:  结构体变量.成员名称

若p是指向 结构体类型(student) 的指针,也可以这样表示成员      (*)p.age    也可以p->age

故,以上三种表达成员的方式均是等价的!

 

附:->是指向运算符

  p -> n 得到 p 指向的结构体变量中的成员 n 的值

  p -> n ++ 得到 p 指向的结构体变量中的成员 n 的值,用完值后使它加1

  ++p -> n 得到 p 指向的结构体变量中的成员 n 的值使之加 1 (先加)

 

(2)如果成员本身又属于一个结构体类型,则要用若干个成员运算符,一级一级地找到最低一级的成员,只能对最低级的成员进行运算、赋值!

  结构体变量.结构体中的结构体名称.成员名称

附:   .是优先级最高的运算符

 

1.4结构体数组

定义方法:(1)struct student stu[3];

(2)在结构体最后,分号之前加入数组,如stu[4]  

(3)

-----类似定义结构体变量,只不过是变量是一个数组形式存在而已

赋值方式:(举个例子)

复制代码

 1 struct student
 2   {
 3     int mum;
 4     char name[20];
 5     char sex;
 6     int ag;
 7     float score;
 8     char addr[30];
 9   }stu[3] = {{10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"},
10         {10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"},
11        {10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"}};

复制代码

  定义数组 stu 时,元素个数可以不指定,即写成以下形式:

   stu[] = {{...},{...},{...}};

 

综上,举一个例子:

复制代码

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stlib.h>
 4 
 5 struct person
 6 {
 7   char name[20];
 8   int count;
 9 }leader[3] = {{"Li", 0},
10        {"Zhang", 0},
11        {"Fun", 0}};
12 
13 void main()
14 {
15   int i, j;
16   char leader_name[20];
17   for(i = 1; i<= 10;i++)
18   {
19     scanf("%s", leader_name);
20     for(j=0;j<3;j++)
21       if(strcmp(leader_name, leader[j].name) == 0)
22         leader[j].count ++;
23   }
24   printf("\n");
25   for(i=0;i<3;i++)
26   printf("%5s: %d\n", leader[i].name, leader[i].count);
27   system("pause");
28 }

复制代码

 

二、typedef  struct的用法

 (此部分转载自http://www.cnblogs.com/st-moon/p/5588321.html)

 

typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。

在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。

 

第一种  上面第二种用法前面直接加typedef

typedef struct student{

  char name[20];

  int age;

  char class;

}student_1;

这语句实际上完成两个操作:
1) 定义一个新的结构类型

struct student{

  char name[20];

  int age;

  char class;

};
2) typedef为这个新的结构起了一个名字,叫student_1。
typedef struct student student_1; (对比typedef int student_1来进行理解)
  因此,student_1实际上相当于struct student,这样定义一个变量的时候,既可以用struct student aaa,也可以用student_1 aaa。student_1成了一个数据类型。

如果有逗号,比如

typedef struct student{

  char name[20];

  int age;

  char class;

}student_1,student_2;

可以先理解成

struct student{

  char name[20];

  int age;

  char class;

}student_1;

struct student{

  char name[20];

  int age;

  char class;

}student_2;

这样再加上typedef,同上分析,也就是说struct student有两个别名,分别是student_1和student_2,都可以代替struct student定义变量。也就是说有三种用法,struct student aaa;student_1 aaa;student_2 aaa都是等价的。

第二种  上面第三种用法前面直接加typedef

typedef struct {

  char name[20];

  int age;

  char class;

}student_1;

根据唯一性,即定义变量的时候只能是student_1 aaa;

 

三、链表

是一种动态的存储分配结构。

1   struct student
2   {
3     int num;
4     float score;
5     struct student *next;
6   };

链表含有一个头指针变量,它存放一个地址,该地址指向一个元素,链表中每一个元素称为结点。

结点包含两部分:用户需要用的实际数据、下个结点的地址!存放下一个地址的叫作 头指针 (head).....当然,最后表尾的地址是NULL(空地址)

 以下实现建立和输出一个简单的链表:

复制代码

#include <stdio.h>

#include <stdlib.h>
#define NULL 0
struct student
{
  long num;
  float score;
  struct student *next;
};
void main()
{
  struct student a, b, c, *head, *p;
  a.num = 99101; a.score = 89.5;
  b.num = 99103; b.score = 90;
  c.num = 99107; c.score = 85;//对结点的 num 和 score 成员赋值
  head = &a;//将结点 a 的起始地址赋给头指针 head
  a.next = &b;//将结点 b 的起始地址赋给 a 结点的 next 成员
  b.next = &c;
  c.next = NULL;// c 结点的 next 成员不存放其他结点地址
  p = head;//使 p 指针指向 a 结点
  do
  {
    printf("%ld %5.1f\n", p->num, p->score);// 输出 p 指向的结点的数据
    p = p->next;//使 p 指向下一结点
  }while(p != NULL);//输出完 c 结点后 p 的值为 NULL
  system("pause");
}

运行结果

99101  89.5
99103  90.0
99107  85.0

复制代码

 

3.1动态链表所需的函数

 (1)malloc 函数

  void *malloc(unsigned int size);

  作用是在内存的动态存储区中分配一个长度为 size 的连接空间。些函数的值(即返回值)是一个指向分配空间起始地址的指针(基类型为 void)。如果些函数未能成功地执行(例如内存空间不足)则返回空指针 NULL。

  (2)calloc 函数

  void *calloc(unsigned n, unsigned size);

  其作用是在内存的动态区存储中分配 n 个长度为 size 的连续空间。函数返回一个指向分配空间起始地址的指针,如果分配不成功,返回 NULL。

  用 calloc 函数可以为一维数组开辟动态存储空间, n 为数组元素个数,每个元素长度为 size。  

  (3)free 函数

  void free(void *p);

  其作用是释放由 p 指向的内存区,使这部分内存区能被其它变量使用, p 是最后一次调用 calloc 或 malloc 函数时返回的值。free 函数无返回值。

  请注意:以前的C版本提供的 malloc 和 calloc 函数得到的是指向字符型数据的指针。ANSI C 提供的 malloc 和 calloc 函数规定为 void * 类型。

 

例:动态表的建立

 

1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 #define NULL 0
  5 #define LEN sizeof(struct student)
  6

 
  7 struct student      //声明结构体
  8 {
  9   long num;
 10   float score;
 11   struct student *next;
 12 };
 13 
 14 struct student *create()  //创建结构体,create是指向这个结构体的指针
 15 {
 16   struct student *p1, *p2, *head;
 17   int num;
 18   float score;
 19   int n = 0;
 20 
 21   head = NULL;
 22 
 23   p1 = p2 = (struct student *)malloc(LEN);
 24 
 25   printf("please input num and score.\n");
 26   scanf("%d,%f", &p1->num, &p1->score);
 27 
 28   while(p1->num != 0)
 29   {
 31     n ++;
 32     if(n == 1)
 33       head = p1;
 34     else
 35       p2->next = p1;
 36     p2 = p1;
 37     p1 = (struct student *)malloc(sizeof(struct student));
 38     printf("please input num and score.\n");
 39     scanf("%d,%f", &p1->num, &p1->score);
 40   }
 41   p2->next = NULL;
 42   return head;
 43 }
 44 
 45 void printlist(struct student *head)
 46 {
 47   struct student *p;
 48   p = head;
 49 
 50   if(head != NULL)
 51   {
 52     do
 53     {
 54        printf("num=%d score=%f\n", p->num, p->score);
 55       p = p->next;
 56 
 57     }while(p != NULL);
 58   }
 59 }
 60 
 61 void main()
 62 {
 63   struct student *head;
 64   head = create();
 65   printlist(head);
 66   system("pause");
 67 }
 68 
 69 以下是对链表的各种操作
 70 
 71 //打印链表
 73 void printlist(struct student *head)
 74 {
 75  struct student *p;
 76  p = head;
 77 
 78  if(head != NULL)
 79  {
 80   do 
 81   {
 82    printf("num=%d score=%5.2f\n", p->num, p->score);
 83    p = p->next;
 84   } while (p != NULL);
 85  }
 86 /* while(p -> next != NULL)
 87  {
 88   printf("num=%d score=%f\n", p->num, p->score);
 89   p = p->next;
 90  }*/
 91 }
 92 
 93 //删除节点
 95 struct student *delNode(struct student *head, int num)
 96 {
 97  printf("delNode.\n");
 98  struct student *p1, *p2;
 99  if(head == NULL)
100  {
101   printf("The List is NULL.\n");
102  }
103  else
104  {
105   p1 = head;
106   while(p1->next != NULL && p1->num != num)
107   {
108    p2 = p1;
109    p1 = p1->next;
110   }
111   if(p1->num == num)
112   {
113    if(p1 == head)
114     head = p1->next;
115    else
116     p2->next = p1->next;
117   }
118   else
119    printf("Can not find list num.\n");
120  }
121  return head;
122 }
123 
124 //更新节点
126 struct student *update(struct student *head, int index, int num, float score)
127 {
128  printf("update.\n");
129  struct student *p;
130  if(head == NULL)
131  {
132   printf("The List is NULL.\n");
133  }
134  else
135  {
136   p = head;
137   while(p->next != NULL && p->num != index)
138   {
139    p = p->next;
140   }
141   if(p->num == index)
142   {
143    p->num = num;
144    p->score = score;
145   }
146   else
147    printf("Can not find list index.\n");
148  }
149  return head;
150 }
151 
152 //增加节点
153 
154 struct student *add(struct student *head, int index, int num, float score)
155 {
156  printf("add.\n");
157  struct student *p1, *p2, *p3;
158  if(head == NULL)
159  {
160   printf("The List is NULL.\n");
161  }
162  else
163  {
164   p1 = p2 = head;
165   while(p1->next != NULL && p1->num != index)
166   {
167    p1 = p1->next;
168    p2 = p1;
169   }
170   if(p1->num == index)
171   {
172    p3 = (struct student *)malloc(LEN);
173    p3->num = num;
174    p3->score = score;
175 
176    if(p2->next == NULL)
177    {
178     p2->next = p3;
179     p3->next = NULL;
180    }
181    else
182    {
183     p3->next = p2->next;
184     p2->next = p3;   
185    }
186   }
187   else
188    printf("Can not find list index.\n");
189  }
190  return head;
191 }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值