C语言_结构体

结构体与共用体

定义一个结构

  1. C语言给出了另一种构造数据类型-“结构(structure)”或叫“结构体”
  2. 相当于高级语言中的记录
  3. “结构”是一种构造类型,它是由若干“成员”组成的
  4. 每一个成员可以是一个基本数据类型或者又是一个构造类型
  5. “结构”既是一种构造而成的数据类型,那么在说明和使用之前必须先定义它,也就是构造它
struct 结构名{
	// 成员表列
	类型说明符 成员名1;
	类型说明符 成员名2;
	...
	类型说明符 成员名n;
};

例:

struct stu{
	int num;
	char name[20];
	char sex;
	float score;
};

结构类型变量的说明

三种方法:

  1. 先定义结构,再说明结构变量
struct stu{
	int num;
	char name[20];
	char sex;
	float score;
}
struct stu boy1,boy2;
  1. 在定义结构类型的同时说明结构变量
struct stu{
	int num;
	char name[20];
	char sex;
	float score;
}boy1,boy2;

用宏定义使一个符号常量表示一个结构类型

#define STU struct stu
STU
{
	int num;
	char name[20];
	char sex;
	float score;
};
STU boy1,boy2;
  1. 直接说明结构变量(省去结构名)
struct 
{
	int num;
	char name[20];
	char sex;
	float score;
}boy1,boy2;

结构嵌套结构
在这里插入图片描述

struct date{
	int month;
	int day;
	int year;
};
struct{
	int num;
	char name[20];
	char sex;
	struct date birthday;
	float score;
}boy1,boy2;

结构变量成员的表示方法

  1. 一般形式
    结构变量名.成员名
  2. 成员变量本身又是一个结构,必须逐级找到最低的成员才能使用
    boy1.birthday.moth

结构变量的赋值

#include<stdio.h>


void main(){
    struct date{
        int month;
        int day;
        int year;
    };
    struct{
        int num;
        char *name;
        char sex;
        struct date birthday;
        float score;
    }boy1,boy2;

    boy1.num = 102;
    boy1.name = "张 三";
    printf("input sex and score:\n");
    scanf("%c,%f",&boy1.sex, &boy1.score);
    printf("input birthday:year-month-day\n");
    scanf("%d-%d-%d",&boy1.birthday.year, &boy1.birthday.month, &boy1.birthday.day);
    boy2=boy1;
    printf("\nInformation:\n");
    printf("Number=%d \nName=%s\n",boy2.num,boy2.name);
    printf("Sex=%c \nScore=%f\n",boy2.sex,boy2.score);
    printf("Birthday:%d-%d-%d\n",boy2.birthday.year,boy2.birthday.month,boy2.birthday.day);
}

在这里插入图片描述

结构变量的初始化

#include<stdio.h>

void main(){
    struct stu{
        int num;
        char *name;
        char sex;
        float score;
    }boy2,boy1={102,"Zhang San",'M',78.5};
    boy2=boy1;
    printf("Number=%d \nName=%s\n",boy2.num,boy2.name);
    printf("Sex=%c \nScore=%f\n",boy2.sex,boy2.score);
}

在这里插入图片描述

结构数组的定义

数组元素也可以是结构类型

案例1

计算学生的平均成绩和不及格的人数

#include<stdio.h>

struct stu{
    int num;
    char *name;
    char sex;
    float score;
}boy[5]={
        {101,"Li ping",'M',45},
        {102,"Zhang ping",'M',62.5},
        {103,"He fang",'F',92.5},
        {104,"Cheng ling",'F',87},
        {105,"Wang ming",'M',58},
    };

void main(){
    int i,c=0;
    float ave,s=0;
    for(i=0;i<5;i++){
        s+=boy[i].score;
        if(boy[i].score<60){
            c+=1;
        }
    }
    printf("s=%f\n",s);
    ave=s/5;
    printf("average=%f\ncount=%d\n",ave,c);
}

在这里插入图片描述

案例2

建立同学通讯录

#include<stdio.h>

#define NUM 3
struct mem{
    char name[20];
    char phone[11];
};
void main(){
    struct mem man[NUM];
    int i;
    for(i=0;i<NUM;i++){
        printf("N0.=%d\n",i+1);
        printf("input name:\n");
        gets(man[i].name);
        printf("input phone:\n");
        gets(man[i].phone);
    }
    printf("\nname\t\tphone\n\n");
    for(i=0;i<NUM;i++){
        printf("%s\t\t\t%s\n",man[i].name,man[i].phone);
    }
}

在这里插入图片描述

结构指针变量的说明和使用

指向结构变量的指针

结构指针变量:一个指针变量当用来指向一个结构变量时,称为结构指针变量
结构指针变量中的值:所指向的结构变量的首地址

  1. 结构指针变量说明
    struct 结构名 *结构指针变量名
  2. 赋值:把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量
    pstu=&boy
  3. 访问
    (*结构指针变量).成员名
    结构指针变量->成员名
#include<stdio.h>

struct stu{
    int num;
    char *name;
    char sex;
    float score;
} boy1={102,"Zhang ping",'M',78.5}, *pstu;

void main(){
    pstu=&boy1;
    printf("Number=%d \nName=%s\n",boy1.num,boy1.name);
    printf("Sex=%c \nScore=%f\n",boy1.sex,boy1.score);
    printf("\n");
    printf("Number=%d \nName=%s\n",(*pstu).num,(*pstu).name);
    printf("Sex=%c \nScore=%f\n",(*pstu).sex,(*pstu).score);
    printf("\n");
    printf("Number=%d \nName=%s\n",pstu->num,pstu->name);
    printf("Sex=%c \nScore=%f\n",pstu->sex,pstu->score);
}

在这里插入图片描述

指向结构数组的指针

#include<stdio.h>

struct stu{
    int num;
    char *name;
    char sex;
    float score;
}boy[5]={
        {101,"Li ping",'M',45},
        {102,"Zhang ping",'M',62.5},
        {103,"He fang",'F',92.5},
        {104,"Cheng ling",'F',87},
        {105,"Wang ming",'M',58},
};

void main(){
    struct stu *ps;
    printf("No.\tName\t\t\tSex\tScore\t\n");
    for(ps=boy;ps<boy+5;ps++){
        printf("%d\t%s\t\t%c\t\t%f\t\n",ps->num,ps->name,ps->sex,ps->score);
    }
}

在这里插入图片描述

结构指针变量作函数参数

#include<stdio.h>

struct stu{
    int num;
    char *name;
    char sex;
    float score;
}boy[5]={
        {101,"Li ping",'M',45},
        {102,"Zhang ping",'M',62.5},
        {103,"He fang",'F',92.5},
        {104,"Cheng ling",'F',87},
        {105,"Wang ming",'M',58},
};

void ave(struct stu *ps){
    int c=0,i;
    float ave,s=0;
    for(i=0;i<5;i++){
        s+=ps->score;
        if(ps->score<60){
            c+=1;
        }
    }
    printf("s=%f\n",s);
    ave=s/5;
    printf("average=%f\ncount=%d\n",ave,c);
}
void main(){
    struct stu *ps;
    void ave(struct stu *ps);
    ps=boy;  //定义说明结构指针变量ps,并把boy的首地址赋予它,使ps指向boy数组
    ave(ps); // 以ps作为实参调用函数ave()
}

在这里插入图片描述

动态存储分配

  1. 在实际的编程中,往往会发生这种情况,即所需的内存空间取绝于实际输入的数据,而无法预先确定
  2. C语言提供了一些内存管理函数,这些内存管理函数可以按需要动态地分配内存空间,也可以把不再使用的空间回收待用

分配内存空间函数malloc

  1. 在内存的动态存储区中分配一块长度为 size字节的连续区域
  2. 函数的返回值为该区域的首地址

(类型说明符 *)malloc(size)
类型说明符: 表示把该区域用于何种数据类型
(类型说明符*):表示把返回值强制转换为该类型指针
size:是一个无符号数

pc=(char *)malloc(100);

表示分配100个字节的内存空间,并强制转换为字符数组类型,函数的返回值指向该字符数组的指针,把该真值赋予指针变量pc.

分配内存空间函数 calloc

  1. 在内存动态存储区中分配 n 块长度为 size 字节的连续区域
  2. 函数的返回值为该区域的首地址
  3. calloc() 与 malloc() 函数的区别:仅在于一次可以分配n块区域.

(类型说明符 *)calloc(n,size)

ps=(struct stu*)calloc(2, sizeof(struct stu));

按 stu的长度分配2块连续区域,强制转换为stu类型,并把其首地址赋予指针变量ps

sizeof(struct stu) 是求 stu 的结构长度

释放内存空间函数 free

free(void *ptr)

  1. 释放ptr所指向的一块内存空间,ptr 是一个任意类型的指针变量,它指向被释放区域的首地址
  2. 被释放区应是 malloc 或 calloc 函数所分配的区域

案例

分配一块区域,输入一个学生数据

#include<stdio.h>

void main(){
    struct stu{
        int num;
        char *name;
        char sex;
        float score;
    }*ps;
    ps=(struct stu*)malloc(sizeof(struct stu));
    ps->num=102;
    ps->name="Zhang ping";
    ps->sex='M';
    ps->score=62.5;
    printf("Number=%d \nName=%s\n",ps->num,ps->name);
    printf("Sex=%c \nScore=%f\n",ps->sex,ps->score);
    free(ps);
}

在这里插入图片描述

链表

每一次分配一块空间可用来存放一个学生的数据,可称之为一个节点. 有多少个学生就应该申请分配多少块内存空间,也就是建立多少个节点

结构数组与链表的区别

  1. 结构数组的弊端:
    a. 预先不能准确把握学生人数,也就是无法确定数组大小
    b. 而且当学生留级、退学也不能把该元素占用的空间从数组中释放出来
  2. 链表的优点(动态存储的方法):
    a. 有一个学生就分配一个节点,无须预先确定学生的准确人数,某学生退学,可删去该节点,并释放节点占用的存储空间,从而节约了宝贵的内存资源
    b. 用数组的方法必须占用一块连续的内存区域。而使用动态分配时,每个节点之间可以是不连续的(节点内是连续的).节点之间的联系可以用指针实现.

指针域:即在节点结构中定义一个成员项用来存放下一节点的首地址,这个用于存放地址的成员,常把它称为指针域

链表: 可在第一个节点的指针域内存入第二个节点的首地址,在第二个节点的指针域内又存放第三个节点的首地址,如此串连下去直到最后一个节点。最后一个节点因无后续节点连接,其指针域可赋值为0.这种连接方式,在数据结构中称为链表.

示例:
在这里插入图片描述
第0个节点称为 头节点head),它存放第一个节点的首地址,它没有数据,只是一个指针变量. 以下每个节点都分为两个域,一个是数据域,存放各种实际数据,如学号、姓名、性别、成绩等;另一个域为指针域,存放下一节点的首地址.

struct stu{
	int num;
	int score;
	struct stu *next;
};

枚举类型

  1. 在枚举类型的定义中列举出所有可能的取值,被说明为该“枚举”类型的变量取值不能超过定义的范围
  2. 枚举类型是一种基本数据类型,而不是一种构造类型

枚举类型的定义和枚举变量的说明

enum 枚举名{枚举值表}枚举变量1,枚举变量2

枚举类型变量的赋值和使用

  1. 枚举值是常量,不是变量。不能再程序中赋值语句再对它赋值
  2. 枚举元素本身由系统定义了一个表示序号的数据,从0开始顺序定义为0,1,2,… 如在weekday中,sun值为0,mon值为1, …, sat值为6
  3. 只能把枚举值赋予枚举变量,不能把元素的数据直接赋予枚举变量
案例1
#include<stdio.h>

void main(){
    enum weekday {sun,mon,tue,wed,thu,fri,sat} a,b,c;
    a=sun;
    b=mon;
    c=(enum weekday)2;  // 一定要把数值赋予枚举变量,则必须用强制类型转换;
                        // 其意义是将顺序号为2的枚举元素赋予枚举变量c
    printf("%d,%d,%d \n",a,b,c);
}

在这里插入图片描述

案例2
#include<stdio.h>

void main(){
    enum body{a,b,c,d} month[31],j;
    int i;
    j=a;
    for(i=1;i<=30;i++){
        month[i]=j;
        j++;
        if(j>d) j=a;
    }
    for(i=1;i<=30;i++){
        switch(month[i]){
            case a:printf("  %2d  %c\t\n",i,'a');break;
            case b:printf("  %2d  %c\t\n",i,'b');break;
            case c:printf("  %2d  %c\t\n",i,'c');break;
            case d:printf("  %2d  %c\t\n",i,'d');break;
            default:break;
        }
    }
}

在这里插入图片描述

类型定义符 typedef

允许用户为数据类型取“别名”,使用 typedef
typedef 原类型名 新类型名

宏定义是在预处理完成的,而 typedef 则是在编译时完成的

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值