【C语言】自定义数据类型

建议学完指针再学

为什么要有自定义数据类型?

基本数据类型不能满足我们在编程中的要求时,需要自己定义一些数据类型使用。

结构体

如果我们想存储单个数据,可以直接用数组存储;那么如果我们想存储多个数据呢?

比如我们要存储学生的学号、姓名、性别、年龄,又该如何操作呢?这就要用到结构体了

结构体的定义

struct 结构体名
{
   成员列表
};

在定义结构体时,常常会用typedef起一个别名

【C语言】typedef

实例:

#include <stdio.h>
//定义结构体Student
struct Student{
	char s_id[10];
	char s_name[20];
	char s_sex[8];
	int s_age;
}; 
/*typedef起别名
typedef struct Student{
	char s_id[10];
	char s_name[20];
	char s_sex[8];
	int s_age;
}ST; 
定义变量时直接使用ST即可
ST stu;
*/
int main ()
{
   //结构体变量的初始化
   struct Student stu={"2408210","liuwen","male",18};
   //结构体成员访问:使用'.'访问
   printf("%s\t%s\t%s\t%d",stu.s_id,stu.s_name,stu.s_sex,stu.s_age);
   return 0;
}

在C语言中不存在结构体类型的强制转换

结构体指针变量

struct Student{
    char* s_id;
    char* s_name;
    char* s_sex;
    int* s_age;
};

结构体嵌套

#include <stdio.h>
struct Date{
	int year;
	int month;
	int day;
};
struct Student{
	char s_name[20];
	struct Date birthday;
	float score;
}; 
/*也可以直接这样写
struct Student{
	char s_name[20];
	struct Date{
	int year;
	int month;
	int day;
    }birthday;
	float score;
};
*/
int main ()
{
   struct Student stu={"liuwen",2000,10,1,99.5};
   printf("%s\t%d.%d.%d\t%.1f",stu.s_name,
   stu.birthday.year,stu.birthday.month,stu.birthday.day,stu.score);
   return 0;
}

结构体变量和指针

结构体类型指针访问成员的获取和赋值形式:

  1. (*p).成员名
  2. p->成员名

实例:

#include <stdio.h>
struct Inventory{//商品 
	char description[20];//货物名
	int quantity;//库存数据 
};
int main ()
{
   struct Inventory sta={"iphone",20};
   struct Inventory* stp=&sta;
   printf("%s %d\n",stp->description,stp->quantity);
   printf("%s %d\n",(*stp).description,(*stp).quantity);
   return 0;
}

结构体和函数

#include <stdio.h>
struct School{
	char s_name[20];
	int s_age;
};
void Print_a(struct School sx){
	printf("%s %d\n",sx.s_name,sx.s_age);
}
void Print_b(struct School* sp){
	printf("%s %d\n",sp->s_name,sp->s_age);
}
int main(){
	struct School sc={"xi'an",100};
	Print_a(sc);
	Print_b(&sc);
	return 0;
}

结构体和数组

结构体数组,是指数组中的每一个元素都是一个结构体类型。在实际应用中,C语言结构体数组常被用来表示有相同的数据结构的群体,比如一个班的学生,一个公司的员工等

#include <stdio.h>
struct Student{
	char s_name[20];
	int age;
	float score;
};
int main(){
	struct Student cla[]={
		{"李华",18,149.5},
		{"李雷",16,130},
		{"韩梅梅",16,141.5},
	};
	for(int i=0;i<3;i++){
		printf("%s\t%d\t%f\n",cla[i].s_name,cla[i].age,cla[i].score);
	}
	return 0;
}

计算结构体大小

#include <stdio.h>
struct node{
	char cha;
	char chb;
	int ia;
};
int main(){
	struct node sd={'a','b',2};
	printf("%d",sizeof(struct node));
	return 0;
}

输出结果为:8

让我们调整一下结构体成员的顺序:

struct node{
	char cha;
	int ia;
	char chb;
};

输出结果为:12

这是怎么一回事呢?为什么大小不是1+1+4=6呢?

原来是内存对齐惹的祸

【C语言】变量占用内存的大小&&内存对齐

共用体

成员共享同一块存储空间

共用体的定义

union 共用体名
{
   成员列表
};

定义和用法类比于结构体

共用体内存分配符合两项原则:

  1. 共用体的内存必须大于或等于其他成员变量中最大数据类型(包括基本数据类型和数组)的大小
  2. 共用体的内存必须是最宽基本数据类型的整数倍,如果不是,则填充字节

例1.成员变量都是基本数据类型的共用体

union data{
    int m;
    float x;
    char c;
}a;

共用体a的内存大小是最大数据类型所占的字节数,即int和float的大小,所以a的内存大小为4字节

例2.成员变量包含数组类型的共用体

union{
    int m;
    float x;
    char c;
    char str[5];
}b;

共用体b的最大数据类型为字符数组,但它的大小是5字节,不满足原则2.必须是最大基本数据类型的整数倍,所以填充3字节,共8字节

共用体变量的初始化和引用

在共用体变量的定义的同时,只能对其中一个成员的类型值进行初始化,这与它的内存分配也是响应的。

共用体变量初始化的格式如下:

union 共用体类型  共用体变量={其中一个成员的类型值};//必须用大括号括起来

完成共用体变量的初始化后,就可以引用共用体中的成员,共用体变量的引用与结构体类似,有直接引用和间接引用两种。

实例演示:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
struct Person
{
	char name[20];
	char role[20];
	union
	{
		char classroom[20];
		char office[20];
	}dept;
}person[3];
 
int main() {
	for (int i = 0; i < 3; i++) {
		printf("please input your information:NO.%d\n", i + 1);
		printf("Name:");
		scanf("%s", &person[i].name);
		getchar();
		printf("Role:");
		scanf("%s", &person[i].role);
		getchar();
		if (strcmp(person[i].role, "student")==0) {
			printf("Classroom:");
			getchar();
			scanf("%s", &person[i].dept.classroom);
		}
		else if (strcmp(person[i].role, "teacher") == 0) {
			printf("Office:");	
			getchar();
			scanf("%s", &person[i].dept.office);
			
		}
		getchar();
	}
 
	for (int i = 0; i < 3; i++) {
		printf("please input your information:NO.%3d\n", i + 1);
		printf("\tName:%6s",person[i].name);
		printf("\tRole:%10s",person[i].role);
		if (strcmp(person[i].role, "student") == 0) {
			printf("\tClassroom:%s",person[i].dept.classroom);
		}
		else if (strcmp(person[i].role, "teacher") == 0) {
			printf("\tOffice:%6s",person[i].dept.office);
		}
		printf("\n");
	}
}

枚举类型

在程序中,可能需要为某些整数定义一个别名,我们可以利用预处理指令#define来完成这项工作,您的代码可能是:

#define MON 1
#define TUE  2
#define WED 3
#define THU  4
#define FRI  5
#define SAT  6
#define SUN  7

在此,我们定义一种新的数据类型,希望它能完成同样的工作。这种新的数据类型叫枚举型。

枚举类型的定义

格式:

enum 枚举类型名
{
   成员列表
};

示例:

enum  DAY
{
      MON = 1 , TUE, WED, THU, FRI, SAT, SUN
};
  1. 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。
  2. DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。
  3. 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。
  4. 可以人为设定枚举成员的值,从而自定义某个范围内的整数。
  5. 枚举型是预处理指令#define的替代。
  6. 类型定义以分号**;**结束。

使用枚举类型对变量进行声明

方法一:枚举类型的定义和变量的声明分开

enum DAY
{
   MON = 1 , TUE, WED, THU, FRI, SAT, SUN
};
enum DAY yesterday;
enum DAY today;
enum DAY tomorrow; // 变量tomorrow的类型为枚举型enum DAY
enum DAY good_day, bad_day; // 变量good_day和bad_day的类型均为枚举型enum DAY

方法二:类型定义与变量声明同时进行:

enum  //跟第一个定义不同的是,此处的 标号DAY省略,这是允许的。
{
  saturday,
  sunday = 0 ,
  monday,
  tuesday,
  wednesday,
  thursday,
  friday
} workday; // 变量workday的类型为枚举型enum DAY
enum week { Mon = 1 , Tue, Wed, Thu, Fri Sat, Sun} days; // 变量days的类型为枚举型enum week
enum BOOLEAN { false , true } end_flag, match_flag; // 定义枚举类型并声明了两个枚举型变量

方法三:用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明:

typedef enum workday
    //enum workday中的workday可以省略
{
  saturday,
  sunday =  0 ,
  monday,
  tuesday,
  wednesday,
  thursday,
  friday
} workday; // 此处的workday为枚举型enum workday的别名
workday today, tomorrow; // 变量today和tomorrow的类型为枚举型workday,也即enum workday

注意:同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常量。错误示例如下所示:

错误声明一:存在同名的枚举类型

typedef enum
{
  wednesday,
  thursday,
  friday
} workday;

typedef enum WEEK
{
  saturday,
  sunday =  0 ,
  monday,
} workday;

错误声明二:存在同名的枚举成员

typedef enum
{
  wednesday,
  thursday,
  friday
} workday_1;

typedef enum WEEK
{
  wednesday,
  sunday =  0 ,
  monday,
} workday_2;

对枚举型的变量赋整数值时,需要进行类型转换

#include<stdio.h>
enum  DAY { MON = 1 , TUE, WED, THU, FRI, SAT, SUN };
int main()
{
     enum  DAY yesterday, today, tomorrow;
    yesterday  =  TUE;
    today  =  ( enum  DAY) (yesterday  +   1 );  // 类型转换
    tomorrow  =  ( enum  DAY)  30 ;  // 类型转换
     // tomorrow = 30;  // 错误
    printf( " %d %d %d \n " , yesterday, today, tomorrow);  // 输出:2 3 30
}

使用枚举型变量

#include<stdio.h>
enum
{ 
    BELL       =   '\a' ,
    BACKSPACE  =   '\b' ,
    HTAB       =   '\t' ,
    RETURN     =   '\r' ,
    NEWLINE    =   '\n' , 
    VTAB       =   '\v' ,
    SPACE      =   ' '
};
enum  BOOLEAN { FALSE = 0 , TRUE } match_flag;
int main()
{
     int  index = 0 ;
     int  count_of_letter= 0 ;
     int  count_of_space = 0 ;

     char str[] = "I'm Ely efod" ;

    match_flag  =  FALSE;

     for (; str[index]  != '\0' ; index ++ )
         if ( SPACE  !=  str[index] )
            count_of_letter ++ ;
         else
        {
            match_flag  =  ( enum  BOOLEAN)  1 ;
            count_of_space ++ ;
        }
    
    printf( "%s %d times %c" , match_flag  ?   "match"  :  "not match" , count_of_space, NEWLINE);
    printf( "count of letters: %d %c%c " , count_of_letter, NEWLINE, RETURN);
}

运行结果:

match 2 times
count of letters: 10

枚举类型与sizeof运算符

#include<stdio.h>
enum escapes
{ 
    BELL       =   '\a' ,
    BACKSPACE  =   '\b' ,
    HTAB       =   '\t' ,
    RETURN     =   '\r' ,
    NEWLINE    =   '\n' , 
    VTAB       =   '\v' ,
    SPACE      =   ' '
};
enum  BOOLEAN { FALSE = 0 , TRUE } match_flag;
int main()
{
    printf( "%d bytes \n" ,  sizeof (enum escapes));  // 4 bytes
    printf( "%d bytes \n" ,  sizeof (escapes));  // 4 bytes
    printf( "%d bytes \n" ,  sizeof (enum  BOOLEAN));  // 4 bytes
    printf( "%d bytes \n" ,  sizeof (BOOLEAN));  // 4 bytes
    printf( "%d bytes \n" ,  sizeof (match_flag));  // 4 bytes
    printf( "%d bytes \n" ,  sizeof (SPACE));  // 4 bytes
    printf( "%d bytes \n" ,  sizeof (NEWLINE));  // 4 bytes
    printf( "%d bytes \n" ,  sizeof (FALSE));  // 4 bytes
    printf( "%d bytes \n" ,  sizeof ( 0 ));  // 4 bytes
}

参考博文:

https://blog.csdn.net/weixin_48560325/article/details/124280883

https://blog.csdn.net/Jacky_Feng/article/details/109219560

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/586491.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

『FPGA通信接口』DDR(3)DDR3颗粒读写测试

文章目录 前言1.配套工程简介2.测试内容与策略3. 测试程序分析4.程序结果分析5.一个IP控制两颗DDR36.传送门 前言 以四颗MT41K512M16HA-125AIT颗粒为例&#xff0c;介绍如何在一块新制板卡上做关于DDR3的器件测试。前面两篇介绍了什么是DDR&#xff0c;并介绍了xilinx给出的FPG…

基于Springboot的音乐翻唱与分享平台

基于SpringbootVue的音乐翻唱与分享平台设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 音乐资讯 音乐翻唱 在线听歌 后台登录 后台首页 用户管理 音乐资讯管理…

Elasticsearch:探索 11 种流行的机器学习算法

作者&#xff1a;来自 Elastic Elastic Platform Team 过去几年中&#xff0c;机器学习&#xff08;ML&#xff09;已经悄然成为我们日常生活中不可或缺的一部分。它影响着从购物网站和流媒体网站上的个性化推荐&#xff0c;到保护我们的收件箱免受我们每天收到的大量垃圾邮件的…

3.9设计模式——Strategy 策略模式(行为型)

意图 定义一系列的算法&#xff0c;把它们一个个封装起来&#xff0c;并且使他们可以相互替换此模式使得算法可以独立于使用它们的客户而变化 结构 Strategy&#xff08;策略&#xff09;定义所有支持的算法的公共入口。Context使用这个接口来调用某ConcreteStrategy定义的方…

手撕spring框架(2)

相关系列 java中spring底层核心原理解析&#xff08;1&#xff09;-CSDN博客 java中spring底层核心原理解析(2)-CSDN博客 手撕spring框架&#xff08;1&#xff09;-CSDN博客 依赖注入原理 依赖注入(Dependency Injection&#xff0c;简称DI)是一种设计模式&#xff0c;它允许我…

DS高阶:图论基础知识

一、图的基本概念及相关名词解释 1.1 图的基本概念 图是比线性表和树更为复杂且抽象的结&#xff0c;和以往所学结构不同的是图是一种表示型的结构&#xff0c;也就是说他更关注的是元素与元素之间的关系。下面进入正题。 图是由顶点集合及顶点间的关系组成的一种数据结构&…

深入浅出DBus-C++:Linux下的高效IPC通信

目录标题 1. DBus简介2. DBus-C的优势3. 安装DBus-C4. 使用DBus-C初始化和连接到DBus定义接口和方法发送和接收信号 5. dbus-cpp 0.9.0 的安装6. 创建一个 DBus 服务7. 客户端的实现8. 编译和运行你的应用9. 瑞芯微&#xff08;Rockchip&#xff09;的 Linux 系统通常会自带 db…

上位机开发PyQt(五)【Qt Designer】

PyQt5提供了一个可视化图形工具Qt Designer&#xff0c;文件名为designer.exe。如果在电脑上找不到&#xff0c;可以用如下命令进行安装&#xff1a; pip install PyQt5-tools 安装完毕后&#xff0c;可在如下目录找到此工具软件&#xff1a; %LOCALAPPDATA%\Programs\Python\…

智能体可靠性的革命性提升,揭秘知识工程领域的参考架构新篇章

引言&#xff1a;知识工程的演变与重要性 知识工程&#xff08;Knowledge Engineering&#xff0c;KE&#xff09;是一个涉及激发、捕获、概念化和形式化知识以用于信息系统的过程。自计算机科学和人工智能&#xff08;AI&#xff09;历史以来&#xff0c;知识工程的工作流程因…

【Web】2024XYCTF题解(全)

目录 ezhttp ezmd5 warm up ezMake ez?Make εZ?мKε? 我是一个复读机 牢牢记住&#xff0c;逝者为大 ezRCE ezPOP ezSerialize ezClass pharme 连连看到底是连连什么看 ezLFI login give me flag baby_unserialize ezhttp 访问./robots.txt 继…

ChatGPT向付费用户推“记忆”功能,可记住用户喜好 | 最新快讯

4月30日消息&#xff0c;人工智能巨头OpenAI宣布&#xff0c;其开发的聊天机器人ChatGPT将在除欧洲和韩国以外的市场全面上线“记忆”功能。这使得聊天机器人能够“记住”ChatGPT Plus付费订阅用户的详细信息&#xff0c;从而提供更个性化的服务。 OpenAI早在今年2月就已经宣布…

无缝对接配电自动化:IEC104转OPC UA网关解决方案

随着水电厂自动化发展的要求&#xff0c;具有一定规模的梯级水电站越来越多&#xff0c;为了实现水电站的无人值班(少人值守)&#xff0c;并考虑到节能控制&#xff0c;电厂采用了集中监控。集中监控关注的是整个电网的安全稳定运行及电压、频率和整个电网的电力需求&#xff0…

C++必修:类与对象(二)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 贝蒂的主页&#xff1a;Betty’s blog 1. 构造函数 1.1. 定义 构造函数是一个特殊的成员函数&#xff0c;名字与类名相…

软件工程物联网方向嵌入式系统复习笔记--如何控制硬件

5-如何控制硬件 #mermaid-svg-of9KvkxJqwLjSYzH {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-of9KvkxJqwLjSYzH .error-icon{fill:#552222;}#mermaid-svg-of9KvkxJqwLjSYzH .error-text{fill:#552222;stroke:#552…

vue3步骤条带边框点击切换高亮

如果是div使用clip-path: polygon(0% 0%, 92% 0%, 100% 50%, 92% 100%, 0% 100%, 8% 50%);进行裁剪加边框没实现成功。目前这个使用svg完成带边框的。 形状可自行更改path 标签里的 :d“[num ! 1 ? ‘M 0 0 L 160 0 L 176 18 L 160 38 L 0 38 L 15.5 18 Z’ : ‘M 0,0 L 160,0…

Docker: 如何不新建容器 修改运行容器的端口

目录 一、修改容器的映射端口 二、解决方案 三、方案 一、修改容器的映射端口 项目需求修改容器的映射端口 二、解决方案 停止需要修改的容器 修改hostconfig.json文件 重启docker 服务 启动修改容器 三、方案 目前正在运行的容器 宿主机的3000 端口 映射 容器…

2024最新版JavaScript逆向爬虫教程-------基础篇之常用的编码与加密介绍(python和js实现)

目录 一、编码与加密原理1.1 ASCII 编码1.2 详解 Base641.2.1 Base64 的编码过程和计算方法1.2.2 基于编码的反爬虫设计1.2.3 Python自带base64模块实现base64编码解码类封装 1.3 MD5消息摘要算法1.3.1 MD5 介绍1.3.2 Python实现md5以及其他常用消息摘要算法封装 1.4 对称加密与…

【GitHub】github学生认证,在vscode中使用copilot的教程

github学生认证并使用copilot教程 写在最前面一.注册github账号1.1、注册1.2、完善你的profile 二、Github 学生认证注意事项&#xff1a;不完善的说明 三、Copilot四、在 Visual Studio Code 中安装 GitHub Copilot 扩展4.1 安装 Copilot 插件4.2 配置 Copilot 插件&#xff0…

Java设计模式 _结构型模式_组合模式

一、组合模式 1、组合模式 组合模式&#xff08;Composite Pattern&#xff09;是这一种结构型设计模式。又叫部分整体模式。组合模式依据树形结构来组合对象&#xff0c;用来表示部分以及整体层次关系。即&#xff1a;创建了一个包含自己对象组的类&#xff0c;该类提供了修改…

Educational Codeforces Round 165 (Rated for Div. 2)[A~D]

这场签到很快那会rank1400吧&#xff0c;但到c就写不动了&#xff0c;最后排名也是3000 左右&#xff0c;可见很多人其实都不会写dp。快速签到也很重要啊&#xff01;&#xff01; A. Two Friends Problem - A - Codeforces 题目大意&#xff1a; M有n个朋友&#xff0c;编号…
最新文章