C语言——结构体(超详解)

时间:2024-12-15 12:53:39

目录

一.介绍

二.结构体在C语言中的定义

struct Date birth = {12, 28, 1987};

定义结构体数组:

例子:

指向结构体变量的指针:

例子:

指向结构体数组的指针:

例子:

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

将一个结构体变量的值传递给另一个函数,有3个方法。

往期回顾:


一.介绍

        列出的每个数据项本身就是一个实体,称为数据字段
        所有数据字段合在一起形成一个称为记录的单元
        在C语言中,记录被称为结构。

结构的形式由符号名称、数据类型和记录中各个数据字段的排列组成。
该结构的内容由存储在符号名中的实际数据组成。

二.结构体在C语言中的定义

   struct

{

 int month;

  int day;

  int year;

} birth;

为结构中列出的各个数据项保留存储空间。结尾后面分号前面是变量。
这三个数据项是结构的成员。结构体的成员可以通过:•birth.month, birth.day, birth.year;这种形式进行访问。

代码如下:

#include <stdio.h>
int main()
{
    struct
    {
        int month;
        int day;
        int year;
    } birth;

    birth.month = 12;
    birth.day = 28;
    birth.year = 1987;
    printf("My birth date is %d/%d/%d\n", birth.month, birth.day, birth.year % 100);
    return 0;
}

        通常列出结构的形式,没有后面的变量名结构成员列表的前面必须有用户选择的结构类型名称。

        比如:

struct Date
{
  int month;
  int day;
  int year;
};

定义语句如下:struct Date birth 。struct Date的作用相当于int等

#include <stdio.h>
struct Date
{
    int month;
    int day;
    int year;
};

int main()
{
    struct Date birth;
    birth.month = 12;
    birth.day = 28;
    birth.year = 1987;
    printf("My birth date is %d/%d/%d\n", birth.month, birth.day, birth.year % 100);
    return 0;
}

结构体的初始化遵循与数组初始化相同的规则:

struct Date birth = {12, 28, 1987};

结构成员可以是任何数据类型

比如:

struct PayRecord
{
  char name[20];
  int idNum;
  double regRate;
  double otRate;
};
struct PayRecord employee = {"H. Price", 12387, 15.89, 25.50};
结构的优点是同一结构类型在列表中多次使用,单个成员可以是数组和结构体。

 

struct
{
  char name[20];
  struct Date birth;
} person;
Example: person.name[4]
                       person.birth.month
综上我们可以用如下代码加深一下理解:
#include <stdio.h>
#define NUMRECS 5
struct PayRecord {  // construct a global structure type
    int id;
    char name[20];
    double rate;
};

int main() {
    int i;
    struct PayRecord employee[NUMRECS] = {
        {32479, "Abrams, B.", 6.72},
        {33623, "Bohm, P.", 7.54},
        {34145, "Donaldson, S.", 5.56},
        {35987, "Ernst, T.", 5.43},
        {36203, "Gwodz, K.", 8.72}
    };

    for (i = 0; i < NUMRECS; i++) {
        printf("%d %-20s $%.2f\n",
               employee[i].id, employee[i].name, employee[i].rate);
    }

    return 0;
}
如果没有显式初始化,静态数组和外部数组或结构的数值元素都初始化为0(或null)。

定义结构体数组:

说明:

(1)定义结构体数组一般形式是

struct 结构体名

    {成员表列} 数组名[数组长度];

② 先声明一个结构体类型,然后再用此类型定义结构体数组:

     结构体类型  数组名[数组长度];

   如:

     struct Person  leader[3];

(2)对结构体数组初始化的形式是在定义数组的后面加上:

={初值表列};

 如:

struct Person  leader[3]= {"Li",0,"Zhang",0,"Fun",0};

例子:

        有3个候选人,每个选民只能投票选一人,要求编一个统计选票的程序,先后输入被选人的名字,最后输出各人得票结果。

解题思路:
设一个结构体数组,数组中包含 3 个元素
每个元素中的信息应包括候选人的姓名 ( 字符型 ) 和得票数 ( 整型 )
输入被选人的姓名,然后与数组元素中的“姓名”成员比较,如果相同,就给这个元素中的“得票数”成员的值加 1

输出所有元素的信息。

代码如下:

#include <string.h>
#include <stdio.h>
struct Person
{
	char name[20];
	int count;
}leader[3] = { “Li”,0,“Zhang”,0,“Sun”,0 };
int main()
{
	int i, j;   char leader_name[20];
	for (i = 1; i <= 10; i++)
	{
		scanf(“ % s”, leader_name);
		for (j = 0; j < 3; j++)
			if (strcmp(leader_name,
				leader[j].name) == 0)
				leader[j].count++;
	}
	for (i = 0; i < 3; i++)
	{
		printf("%5s:%d\n",leader[i].name,leader[i].count);
	}
	return 0;
}

指向结构体变量的指针:

指向结构体对象的指针变量既可以指向结构体变量,也可以用来指向结构体数组中的元素。
指针变量的基类型必须与结构体变量的类型相同。例如:

           struct Student *pt;

例子:

通过指向结构体变量的指针变量输出结构体变量中成员的信息。

解题思路:在已有的基础上,本题要解决两个问题:
怎样对结构体变量成员赋值;
怎样通过指向结构体变量的指针访问结构体变量中成员。
代码如下:
#include <stdio.h>
#include <string.h>

int main()
{
    struct Student
    {
        long num;
        char name[20];
        char sex;
        float score;
    };

    struct Student stu_1;
    struct Student *p;
    p = &stu_1;

    stu_1.num = 10101;
    strcpy(stu_1.name, "Li Lin");
    stu_1.sex = 'M';
    stu_1.score = 81.5;

    printf("No.:%ld\n", stu_1.num);
    printf("name:%s\n", stu_1.name);
    printf("sex:%c\n", stu_1.sex);
    printf("score:%5.1f\n", stu_1.score);

    return 0;
}
说明:
为了使用方便和直观, C 语言允许把 (*p).num p->num 来代替
(*p).name 等价于 p->name
如果 p 指向一个结构体变量 stu ,以下等价:

  stu.成员名(stu.num)

  (*p).成员名((*p).num)

     p->成员名(p->num)

指向结构体数组的指针:

例子:

3个学生的信息,放在结构体数组中,要求输出全部学生的信息。

解题思路:用指向结构体变量的指针处理

(1)声明struct Student,并定义结构体数组初始化

(2)定义指向struct Student类型指针p

(3)使p指向数组首元素,输出元素中信息

(4)使p指向下一个元素,输出元素中信息

(5)再使p指向结构体数组的下一个元素,输出它指向的元素中的有关信息

代码如下:

#include <stdio.h>
struct Student                  
{ int num;    char name[20];
   char sex;   int age;
};
struct Student stu[3]={
              {10101,"Li Lin",'M',18},
              {10102,"Zhang Fun",'M',19},
              {10104,"Wang Min",'F',20} };
int main()
{ struct Student *p;  
   printf(" No.  Name         sex  age\n");
   for(p=stu;p<stu+3;p++)
      printf(“%5d %-20s %2c %4d\n”,
                           p->num, p->name, 
                                p->sex, p->age); 
   return 0;
}

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

将一个结构体变量的值传递给另一个函数,有3个方法

(1) 用结构体变量的成员作参数。

  例如,用stu[1].numstu[2].name作函数实参,将实参值传给形参。

用法和用普通变量作实参是一样的,属于“值传递”方式。
应当注意实参与形参的类型保持一致。

(2) 用结构体变量作实参。

用结构体变量作实参时,将结构体变量所占的内存单元的内容全部按顺序传递给形参,形参也必须是同类型的结构体变量

在函数调用期间形参也要占用内存单元。这种传递方式在空间和时间上开销较大

在被调用函数期间改变形参(也是结构体变量)的值,不能返回主调函数

一般较少用这种方法

(3)用指向结构体变量(或数组元素)的指针作实参,将结构体变量(或数组元素)的地址传给形参。

例子:

n个结构体变量,内含学生学号、姓名和3门课程的成绩。要求输出平均成绩最高的学生的信息(包括学号、姓名、3门课程成绩和平均成绩)

解题思路:将n个学生的数据表示为结构体数组。按照功能函数化的思想,分别用3个函数来实现不同的功能:

input 函数输入数据和求各学生平均成绩
max 函数找平均成绩最高的学生
print 函数输出成绩最高学生的信息
在主函数中先后调用这 3 个函数,用指向结构体变量的指针作实参。最后得到结果。
本程序 假设 n=3

代码如下:

#include <stdio.h>
#define N 3
struct Student
{  int num;   
    char name[20];    
    float score[3];   
    float aver;   
};
int main()
{ void input(struct Student stu[]);   
   struct Student max(struct Student stu[]);     
   void print(struct Student stu);   
   struct Student stu[N],*p=stu;   
   input(p);   
   print(max(p));   
   return 0;
}
void input(struct Student stu[])   
{ int i;
   printf("请输入各学生的信息:
                 学号、姓名、三门课成绩:\n");
   for(i=0;i<N;i++)
   {scanf("%d %s %f %f %f",
                   &stu[i].num,stu[i].name,
              &stu[i].score[0],&stu[i].score[1],
                 &stu[i].score[2]);   
     stu[i].aver=(stu[i].score[0]+
          stu[i].score[1]+stu[i].score[2])/3.0;   
   }
}
struct Student max(struct Student stu[])   
{int i,m=0;   
  for(i=0;i<N;i++)
     if (stu[i].aver>stu[m].aver) m=i;     
  return stu[m];   
} 
void print(struct Student stud)   
{ printf("\n成绩最高的学生是:\n");
	printf("学号:%d\n姓名:%s\n 三门课成绩:%5.1f,%5.1f,%5.1f\n 平均成绩:%6.2f\n", 
stud.num,stud.name,stud.score[0],stud.score[1],stud.score[2],stud.aver);
 }
以上 3 个函数的调用,情况各不相同:
调用 input 函数时,实参是指针变量,形参是结构体数组,传递的是结构体元素的地址,函数无返回值。
调用 max 函数时,实参是指针变量,形参是结构体数组,传递的是结构体元素的地址,函数的返回值是结构体类型数据。
调用 print 函数时,实参是结构体变量,形参是结构体变量,传递的是结构体变量中各成员的值,函数无返回值。

往期回顾:

C语言函数递归经典题型——汉诺塔问题-****博客

C语言——判断输入字符串是否合法代码分享-****博客

C语言——字符串指针变量与字符数组(易错分析)-****博客

C语言——习题练习(一)-****博客

C语言——指针初阶(三)-****博客

C语言——海龟作图(对之前所有内容复习)_海龟图c语言-****博客

C语言——指针初阶(二)-****博客

C语言——指针初阶(一)_c语言指针p和*p区别-****博客