C语言-结构体

Posted 霏ིྀ宇ིྀ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言-结构体相关的知识,希望对你有一定的参考价值。

结构体

结构体类型数据的定义和引用方法

一.结构体类型的概念

“结构体”是一种构造类型,它是由若干“成员”组成的。其中的每一个成员可以是一个基本数据类型或者又是一个构造类型。既然结构体是一种新的类型,那么就需要先进行对其构造,这里称这种操作为声明一个结构体。
在一个组合项中包含若干个类型不同(当然也可以相同)的数据项。C和C++允许用户自己指定这样一种数据类型,它称为结构体。它相当于其他高级语言中的记录(record)。例如,可以通过下面的声明来建立数据类型。

struct Student//声明一个结构体类型Student

int num;//包括一个整型变量num
char name[20];//包括一个字符数组name,可以容纳20个字符
char sex;//包括一个字符变量sex
int age;//包括一个整型变量age
float score;//包括一个单精度型变量
char addr[30];//包括一个字符数组addr,可以容纳30个字符
;

这样,程序设计者就声明了一个新的结构体类型Student(struct是声明结构体类型时所必须使用的关键字,不能省略),它向编译系统声明: 这是一种结构体类型,它包括num, name, sex, age, score, addr等不同类型的数据项。应当说明Student是一个类型名,它和系统提供的标准类型(如int、char、float、double 一样,都可以用来定义变量,只不过结构体类型需要事先由用户自己声明而已。

声明一个结构体类型的一般形式为

struct 结构体类型名
成员表列

结构体类型名用来作结构体类型的标志。上面的声明中Student就是结构体类型名。大括号内是该结构体中的全部成员(member),由它们组成一个特定的结构体。上例中的num,name,sex,score等都是结构体中的成员。在声明一个结构体类型时必须对各成员都进行类型声明即类型名成员名;每一个成员也称为结构体中的一个域(field)。成员表列又称为域表。
成员名的定名规则与变量名的定名规则相同
声明结构体类型的位置一般在文件的开头,在所有函数(包括main函数)之前,以便本文件中所有的函数都能利用它来定义变量。当然也可以在函数中声明结构体类型。
在C语言中,结构体的成员只能是数据(如上面例子中所表示的那样)。
其中,关键字struct表示声明结构,其后的结构体名标志着结构体的类型。大括号内是该结构体中的各个成员,每个成员都需要进行类型说明,说明形式如下:
类型名 成员名;
注意
在声明结构时,要注意大括号最后面有一个分号“;”,在编写时千万不要忘记。另外,关键字struct不可以省略,结构体类型名可以省略

例如声明一个结构:

struct Product
	char cName[10];				/*产品名称*/
	char cShape[20];				/*形状*/
	char cColor[10];				/*颜色*/
	char cFunc[20];				/*功能*/
	int	 iPrice;							/*价格*/
	char cArea[20];				/*产地*/

上面的代码使用关键字struct声明一个名为Product的结构类型,在结构体中定义的变量是Product结构的成员,这些变量表示产品名称、形状、颜色、功能、价格和产地,可以看到根据结构成员中不同的作用选择与此相对应的类型。

注意
struct Product是一个类型名,它和系统中提供的标准的数据类型具有同样的地位和作用。都是可以用来定义变量类型的,只不过结构体类型需要由用户自己定义而已

百度百科

定义结构体变量

在上一节中介绍了一个结构体的类型,这个类型就相当于一个模型,在这个模型中并没有具体的数据,编译器也并不为其分配实际的内存单元。结构体类型定义以后就可以使用它,下面介绍三种定义结构体类型变量的方法。

声明结构体类型,再定义变量
像上一节中声明的Product结构体类型就是先进行声明结构体类型,然后struct Product进行定义结构体变量,例如:
struct Product product1;
struct Product product2;
struct Product是结构体类型名,而product1和product2是结构体变量名。既然使用Product类型定义变量,那么这两个变量就具有相同的结构。
注意:
结构体变量的定义必须放在结构体类型定义之后,而且关键字struct必须与结构体名一起使用才能定义该结构体类型的变量。
变量定义为基本的数据类型不同于定义为结构体类型。如,定义为基本的数据类型,只需要指定int类型即可。而如果要定义为结构体类型,就可以定义出许多种基本数据类型。
说明:
在定义结构体变量后,系统就会为其分配内存单元。内存大小是这样计算的,例如product1和product2在内存中各占个84字节(10+20+10+20+4+20)

声明一个时间的结构体类型,其中包括年、月、日。声明一个学生信息的结构类型,并且定义两个结构体变量student1和student2。在struct student结构体类型中,可以看到有一个成员是表示学生的出生日期,使用的是struct date结构体类型,结构如图12.2所示。

定义结构体类型变量的方法

前面定义的结构体类型只是一种“模型”,还必须定义结构体变量后才能存放数据。
定义结构体变量有三种方法:

  1. 先定义结构体类型再定义结构体变量

定义了结构体类型后:
struct student st, stmax, stmin;

   类型符                  变量名
定义了三个结构体变量,每个变量包含三个成员,每个变量可存放一个学生的数据。

这种方式是声明类型和定义变量分离,在声明类型后可以随时定义变量,比较灵活

2、在定义结构体类型的同时定义结构体变量(在声明类型的同时定义结构体变量)

struct student

int num;
char name[20];
int score;
st, stmax, stmin;

这种定义方法的一般形式为:

   struct  结构体名
     
          成员表列
     变量名表列

3、不指定类型名而直接定义结构体类型变量

  struct            不出现类型名
  
     int  num;
     char  name[20];
     int  score;
   st, stmax, stmin;

这种定义方法的一般形式为:

   struct  
     
          成员表列
     变量名表列

说明:
①类型与变量不同,只对变量分配空间与操作。
②对成员可以单独使用,相当于普通变量。
③成员也可以是一个结构体变量。

   struct  date               struct  student
    int  month;              int  num;
     int  day;                      char  name[20];
     int  year;                     struct date birthday;
   ;                               st1, st2;

④成员名可以与程序中的变量名相同,两者代表不同的对象。

引用结构体成员

定义结构体类型变量以后,当然可以引用这个变量。但是要注意的是不能直接将一个结构体变量作为一个整体进行输入和输出。

例如,不能将product1和product2进行这样的输出:
printf("%s%s%s%d%s",product1);
printf("%s%s%s%d%s",product2);

成员引用

要对结构体变量进行赋值、存取或运算实质上就是对结构体成员的操作,

结构变量成员的一般形式是:

结构变量名.成员名
在引用结构的成员时,可以在结构的变量名的后面加上成员运算符“.”和成员的名字。例如:

product1.cName="Icebox";
product2.iPrice=2000;
上面的赋值语句就是对product1结构体变量中的成员cName和iPrice两个变量进行赋值。
但是如果成员本身又属于一个结构体类型,那应该怎么办呢?这时就要使用若干个成员运算符,一级一级地找到最低一级的成员。只能对最低级的成员进行赋值或存取以及运算操作。

例如对上面定义的student1变量中的出生日期进行赋值:

student1.birthday.year=1986;
student1.birthday.month=12;
student1.birthday.day=6;

说明:
不能使用student1.birthday来访问student1变量中的成员birthday,需要逐级找到最低级的成员。因为birthday本身是一个结构体变量

引用结构体数据成员的方法

定义好结构体变量或指针变量以后, 就可以通过它们来引用结构体数据中的成员, 引用结构体数据成员主要有以下 3 种方法。

  1. 通过结构体变量来引用成员
    使用结构体变量来引用成员是通过“.” 来实现的, 且它引用的是自 己的成员, 如文中第二部分定义的 p 是一个结构体变量,引 用结构体变量 p 中的成员 可表示:p.num, p.name, p.sex, p.age, p.pro。

  2. 结构体指针变量名->成员名
    通过结构体指针变量和“->” 来引用成员结构体指针变量只能存储和它同类型的变量或存储单元的地址, 它没有自 己的成员, 在使用结构体指针变量之前, 必须把同类型的变量的地址或动态创建的同类型的存储单元(用malloc 函数创建) 的地址赋值给它, 让它有所指向, 否则使用结构体指针变量是无意义的。 当结构体指针变量有指向以后, 可以通过“->” 来引用指针变量所指向的变量或存储单元中的成员。 如文中第二部分定义的 q 是一个结构体指针变量, 而 p 是一个结构体变量, 如果把 p 的地址赋值给 q(即 q=& p) , 则可通过 q 来引用 p 中的成员, 使用 q 来引用结构体变量 p 中的成员可表示为:q->num, q->name, q->sex, q->age, q->pro。

  3. 结构体指针变量名).成员名
    通过结构体指针变量和“.” 来引用成员当把变量的地址赋值给同类型的指针变量以后(指针变量指向该变量) ,“
    指针变量” 和“变量” 的作用是一样的, 如第二部分定义的变量 p 和指针变量 q, 如果把 p 的地址赋值给 q(即 q=& p) , 则 *q 的作用相当于 p, 使用 q 来引 用
    结构体变量 p 中的成员可表示为: (*q).num, (*q).name, (*q).sex, (*q).age, (*q).pro。 (注: 在 C 语言程序中, 由 于“.” 的优先级比“*” 的优先级高, 故 *q 外面的括号不可以省略

整体引用

可以对结构体变量进行整体赋值:

  stmax=st;  将st中的所有内容赋值给stmax。
对结构体变量的整体操作只限于赋值操作和参数传递,而且要求类型一致。不能对结构体变量进行整体输入输出。

初始化结构体变量

结构体类型和其他的基本类型一样,也可以在定义结构体变量时指定初始值。例如:
struct Student

	char cName[20];
	char cSex;
	int iGrade;
 student1="HanXue","W",3;		
			/*定义变量并设置初始值*/

注意:
在初始化时,定义的变量后面使用等号,然后将其初始化的值放在大括号中,并且每一个数据要与结构体的成员列表的顺序一样

结构体嵌套和用指针引用结构体成员

指向结构体类型数据的指针

  struct  student  st, st1;
  struct  student  *p;   //定义指向结构体类型数据的指针变量
  p=&st;     

通过指针变量引用结构体变量:

 1. 成员引用
(*p).num=1001;              或    p->num=1001;
(*p).score=85;                 或    p->score=85;
strcpy((*p).name,”wang”);strcpy(p->name,”wang”);
2.整体引用
  st1=*p;                等效于 st1=st;

指向结构体数组的指针

struct  student  a[100]struct  student  *p; 
   p=a;  

通过指针变量引用结构体数组元素:

  1. 成员引用
 (*p).num=1001;      或 p->num=1001;
   (*p).score=85;         或 p->score=85;
   strcpy((*p).name,”wang”);strcpy(p->name,”wang”);

一般地:

(*(p+i)).num=1001;(p+i)->num=1001;
(*(p+i)).score=85;(p+i)->score=85;
strcpy((*(p+i)).name,”wang”);strcpy((p+i)->name,”wang”);
//也可以用下标法:
p[i].num=1001;
  1. 整体引用
*(p+1)=*(p+0);  或  p[1]=p[0];

用结构体变量和指向结构体的指针作函数参数

用结构体变量作函数参数时,对应的实参应该是同类型的结构体变量(或数组元素),参数传递是“值传递”。
用指向结构体的指针作函数参数时,对应的实参应该是同类型的结构体变量的地址(或数组的地址),参数传递是“地址传递”。

结构作为函数参数例子:

#include <stdio.h>
#include <string.h>
 
struct Books

   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
;
 
/* 函数声明 */
void printBook( struct Books book );
int main( )

   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;
 
   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 输出 Book1 信息 */
   printBook( Book1 );
 
   /* 输出 Book2 信息 */
   printBook( Book2 );
 
   return 0;

void printBook( struct Books book )

   printf( "Book title : %s\\n", book.title);
   printf( "Book author : %s\\n", book.author);
   printf( "Book subject : %s\\n", book.subject);
   printf( "Book book_id : %d\\n", book.book_id);

指向结构的指针例子

#include <stdio.h>
#include <string.h>
 
struct Books

   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
;
 
/* 函数声明 */
void printBook( struct Books *book );
int main( )

   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;
 
   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 通过传 Book1 的地址来输出 Book1 信息 */
   printBook( &Book1 );
 
   /* 通过传 Book2 的地址来输出 Book2 信息 */
   printBook( &Book2 );
 
   return 0;

void printBook( struct Books *book )

   printf( "Book title : %s\\n", book->title);
   printf( "Book author : %s\\n", book->author);
   printf( "Book subject : %s\\n", book->subject);
   printf( "Book book_id : %d\\n", book->book_id);

结构体数组的应用;

输入100个学生的学号、姓名和考试成绩,然后按从高分到低分的顺序排列后输出。

#include "stdio.h"
struct student

    int num;
    char name[20];
    int score;
;
int main()

    int i, j;
    struct student a[100], t;
    for (i = 0; i < 5; i++)
        scanf("%d%s%d", &a[i].num, a[i].name, &a[i].score);
    for (i = 0; i < 4; i++)
        for (j = i + 1; j < 5; j++)
            if (a[i].score < a[j].score)
            
                t = a[i];
                a[i] = a[j];
                a[j] = t;
            
    for (i = 0; i < 5; i++)
        printf("\\n %5d,%15s,%5d", a[i].num, a[i].name, a[i].score);

访问结构成员

为了访问结构的成员,我们使用成员访问运算符(.)。成员访问运算符是结构变量名称和我们要访问的结构成员之间的一个句号。您可以使用 struct关键字来定义结构类型的变量。

下面的实例演示了结构的用法:

#include <stdio.h>
#include <string.h>
 
struct Books

   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
;
 
int main( )

   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;
 
   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 输出 Book1 信息 */
   printf( "Book 1 title : %s\\n", Book1.title);
   printf( "Book 1 author : %s\\n", Book1.author);
   printf( "Book 1 subject : %s\\n", Book1.subject);
   printf( "Book 1 book_id : %d\\n", Book1.book_id);
 
   /* 输出 Book2 信息 */
   printf( "Book 2 title : %s\\n", Book2.title);
   printf( "Book 2 author : %s\\n", Book2.author);
   printf( "Book 2 subject : %s\\n", Book2.subject);
   printf( "Book 2 book_id : %d\\n", Book2.book_id);
 
   return 0;

引用:https://www.runoob.com/cprogramming/c-structures.html

链表的基本操作(创建,插入,删除,输出)

链表概述

链表是一种重要的数据结构─动态数据结构。

以具体例子来说明链表的概念及其应用:

例:选择合适的数据结构来存放一批学生的学号及考试成绩,以便进一步处理。
由于学生人数未知,用静态数据结构不合适。用链表处理较恰当。

将各学生的数据进行离散存放,来一个学生就分配一小块内存(结点)。并将各结点用指针依次连接起来─链表。


每结点应包含下一结点的开始地址。
最后一个结点中的指针为空。
链头指针指向第一个结点,是访问链表的重要依据。这样的链表称单向链表。

一个结点可用如下结构体描述:

typedef  struct  student 

    int  num;               学号
    int  score;               成绩
    struct  student  *next;    下一结点的首地址
 STU;

单向链表的建立

①输入一个学生的数据。
②分配结点空间,数据存入。
③将该结点的首地址赋给上一结点的next,若该结点是第一个结点,则赋给头指针。
④将该结点的next置为空,表示该结点为当前的最后结点。

STU  *creat()
    STU st,*p0=NULL,*p,*head=NULL;
      while(1)
         scanf("%d%d",&st.num,&st.score);
           if(st.num<0) break;
           p=malloc(sizeof(STU));   *p=st;
           (*p).next=NULL;
           if(p0==NULL) head=p;     p0为前一结点的指针   
           else (以上是关于C语言-结构体的主要内容,如果未能解决你的问题,请参考以下文章

C语言结构体排序

c语言 结构体和共用体 1. 有5个学生,每个学生的数据包括学号、姓名、3门课的成绩,从键盘输入5个学生数据

c语言:用结构体变量输出学生的信息,包括学号,姓名,性别。

ZZNUOJ_用C语言编写程序实现1190:查询记录(结构体专题)(附完整源码)

ZZNUOJ_用C语言编写程序实现1191:添加记录(结构体专题)(附完整源码)

ZZNUOJ_用C语言编写程序实现1192:删除记录(结构体专题)(附完整源码)