当前位置:网站首页>复合类型(自定义类型)
复合类型(自定义类型)
2022-07-03 14:43:00 【敏儿好xun】
结构体
概述
- 数组:描述一组具有相同类型数据的有序集合,用于处理大量相同类型的数据运算。
- 有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性。显然单独定义以上变量比较繁琐,数据不便于管理。
- C语言中给出了另一种构造数据类型——结构体。
结构体变量的定义和初始化
定义结构体变量的方式:
- 先声明结构体类型再定义变量名
- 在声明类型的同时定义变量
- 直接定义结构体类型变量(无类型名)
示例:
方法一:
#include<stdio.h>
//struct 结构体名
//{
// //结构体成员列表
// 姓名
// 年龄
//};
struct student
{
char name[21];
int age;
int score;
char addr[51];
};
int main()
{
//创建及结构体变量
//方法1:比较慢
//struct student stu;//结构体类型 结构体变量
//strcpy(stu.name,"张三");//结构体对字符串数组进行赋值时,采用拷贝赋值。//数组名为常量,所以对其赋值的时候不能使用=,得使用strcpy
//stu.age = 18;
//stu.score = 100;
//strcpy(stu.addr, "山西省太原市");
//方法2
struct student stu = {
"张三",18,100,"山西省太原市" };
printf("姓名:%s\n", stu.name);
printf("年龄:%d\n", stu.age);
printf("成绩:%d\n", stu.score);
printf("地址:%s\n", stu.addr);
return 0;
}
方法二:
#include<stdio.h>
struct student
{
char name[21];
int age;
int score;
char addr[51];
}stu= {
"张三",18,100,"山西省太原市" };
int main0202()
{
printf("姓名:%s\n", stu.name);
printf("年龄:%d\n", stu.age);
printf("成绩:%d\n", stu.score);
printf("地址:%s\n", stu.addr);
return 0;
}
int main(void)
{
struct student stu;
//键盘获取值
scanf("%s%d%d%s", stu.name, &stu.age, &stu.score, stu.addr);//数组名为首地址,所以不用加&
printf("姓名:%s\n", stu.name);
printf("年龄:%d\n", stu.age);
printf("成绩:%d\n", stu.score);
printf("地址:%s\n", stu.addr);
return 0;
}
结果:
姓名:张三
年龄:18
成绩:100
地址:山西省太原市
结构体数组
示例:
头文件.h——struct.h
#pragma once
struct student
{
char name[21];
int age;
char sex;
int score[3];
char addr[51];
};
主函数调用头文件
#include<stdio.h>
#include "struct.h"//头文件调用
int main(void)
{
struct student stu[3]=
{
{
"马笑笑",19,'M',90,100,98,"河南郑州"},
{
"丁心",18,'F',97,96,99,"重庆"},
{
"刘光头",15,'M',97,96,98,"重庆"}
};
printf("结构体大小:%d\n", sizeof(stu));
printf("结构体元素大小:%d\n", sizeof(stu[0]));结构体成员需要偏移对齐
printf("结构体元素个数:%d\n", sizeof(stu) / sizeof(stu[0]));
for (int i = 0; i < 3; i++)
{
printf("姓名:%s\n", stu[i].name);
printf("年龄:%d\n", stu[i].age);
printf("性别:%s\n", stu[i].sex == 'M' ? "男" : "女");
printf("成绩1:%d\n", stu[i].score[0]);
printf("成绩2:%d\n", stu[i].score[1]);
printf("成绩3:%d\n", stu[i].score[2]);
printf("地址:%s\n", stu[i].addr);
printf("\n");
}
return 0;
}
结果:
结构体大小:288
结构体元素大小:96
结构体元素个数:3
姓名:马笑笑
年龄:19
性别:男
成绩1:90
成绩2:100
成绩3:98
地址:河南郑州
姓名:丁心
年龄:18
性别:女
成绩1:97
成绩2:96
成绩3:99
地址:重庆
姓名:刘光头
年龄:15
性别:男
成绩1:97
成绩2:96
成绩3:98
地址:重庆
结构体排序
#include<stdio.h>
#include "struct.h"//头文件调用
//结构体排序
int main(void)
{
struct student stu[3] =
{
{
"马笑笑",19,'M',90,100,98,"河南郑州"},
{
"丁心",18,'F',97,96,99,"重庆"},
{
"刘光头",15,'M',97,96,98,"重庆"}
};
for (int i = 0; i < 3 - 1; i++)
{
for (int j = 0; j < 3 - i - 1; j++)
{
if (stu[j].age > stu[j + 1].age)
{
struct student temp=stu[j];
stu[j] = stu[j + 1];
stu[j + 1] = temp;
}
}
}
for (int i = 0; i < 3; i++)
{
printf("姓名:%s\n", stu[i].name);
printf("年龄:%d\n", stu[i].age);
printf("性别:%s\n", stu[i].sex == 'M' ? "男" : "女");
printf("成绩1:%d\n", stu[i].score[0]);
printf("成绩2:%d\n", stu[i].score[1]);
printf("成绩3:%d\n", stu[i].score[2]);
printf("地址:%s\n", stu[i].addr);
printf("\n");
}
return 0;
}
结果:
姓名:刘光头
年龄:15
性别:男
成绩1:97
成绩2:96
成绩3:98
地址:重庆
姓名:丁心
年龄:18
性别:女
成绩1:97
成绩2:96
成绩3:99
地址:重庆
姓名:马笑笑
年龄:19
性别:男
成绩1:90
成绩2:100
成绩3:98
地址:河南郑州
开辟堆空间存储结构体
示例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include "struct.h"
typedef struct student ss;//起个别名
int main(void)
{
//printf("%d", sizeof(struct student));//结构体元素大小
ss* p = (ss*)malloc(sizeof(ss) * 3);//开辟堆空间
for (int i = 0; i < 3; i++)
{
scanf("%s%d,%c%d%d%d%s",p[i].name,&p[i].age,&p[i].sex,
&p[i].score[0],&p[i].score[1],&p[i].score[2],p[i].addr);//因为有字符"%d%c",所以加逗号区分前面的int类型和字符类型
}
for (int i = 0; i < 3; i++)
{
printf("姓名:%s\n", p[i].name);
printf("年龄:%d\n", p[i].age);
printf("性别:%s\n", p[i].sex == 'M' ? "男" : "女");
printf("成绩1:%d\n", p[i].score[0]);
printf("成绩2:%d\n", p[i].score[1]);
printf("成绩3:%d\n", p[i].score[2]);
printf("地址:%s\n", p[i].addr);
printf("\n");
}
free(p);
return 0;
}
结果:
哈哈 18,M 89 98 99 山西
嘻嘻 19,M 99 80 98 陕西
嘿嘿 17,M 78 85 86 山东
姓名:哈哈
年龄:18
性别:男
成绩1:89
成绩2:98
成绩3:99
地址:山西
姓名:嘻嘻
年龄:19
性别:男
成绩1:99
成绩2:80
成绩3:98
地址:陕西
姓名:嘿嘿
年龄:17
性别:男
成绩1:78
成绩2:85
成绩3:86
地址:山东
结构体嵌套结构体
示例:
建立头文件.h文件
struct1.h
#pragma once
struct scores
{
int cl;//c语言
int cpp;//c++
int cs;//c#
};
struct student
{
char name[21];
int age;
struct scores ss;
char addr[51];
};
主程序调用
#include <stdio.h>
#include "struct1.h"
int main(void)
{
struct student stu = {
"哈喽",20,98,99,100,"陕西宝鸡" };
printf("%s\n%d\n%d\n%d\n%d\n%s", stu.name, stu.age, stu.ss.cl, stu.ss.cpp, stu.ss.cs, stu.addr);
return 0;
}
结果:
哈喽
20
98
99
100
陕西宝鸡
结构体赋值
示例:
#include<stdio.h>
#include"struct.h"
int main()
{
struct student stu = {
"呼呼",19,89,98,100,"太原" };
struct student s1 = stu;
//数组名为常量,所以对其赋值的时候不能使用=,得使用strcpy
strcpy(s1.name, "呵呵");//对s1的修改不影响stu 虽然复制 但两者为独立的空间
printf("%s", stu.name);
return 0;
}
结果:
呼呼
结构体和指针
结构体成员为指针类型
示例:
#include<stdio.h>
struct student//结构体成员为指针类型
{
char* name;
int age;
int* scores;
char* addr;
};
int main()
{
struct student stu;
//开辟堆空间
stu.name = (char*)malloc(sizeof(char) * 21);//为指针时,需要开辟堆空间再进行赋值,否则值为常量将不能被改变
stu.scores = (int*)malloc(sizeof(int) * 3);
stu.addr = (char*)malloc(sizeof(char) * 51);
//结构体赋值
strcpy(stu.name, "李四");
stu.age = 18;
stu.scores[0] = 89;
stu.scores[1] = 89;
stu.scores[2] = 89;
strcpy(stu.addr, "重庆");
//打印
printf("%s\n", stu.name);
printf("%d\n", stu.age);
printf("%d\n", stu.scores[0]);
printf("%d\n", stu.scores[1]);
printf("%d\n", stu.scores[2]);
printf("%s\n", stu.addr);
//释放堆空间
free(stu.name);
free(stu.scores);
free(stu.addr);
return 0;
}
结果:
李四
18
89
89
89
重庆
结构体指针
#include<stdio.h>
int main()
{
struct student1 ss = {
"王五",17,84,85,86,"四川" };
struct student1* p = &ss;
/*printf("%s\n", (*p).name); printf("%d\n", (*p).age); printf("%d\n", (*p).scores[0]);*/ //==
//结构体指针->成员
//结构体变量.成员
printf("%s\n", p->name);
printf("%D\n", p->scores[0]);
return 0;
}
结果:
王五
84
结构体整合(类似于开辟二级指针开辟的堆空间)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
typedef struct student ss;
struct student
{
char* name;
int age;
int* scores;
char* addr;
};
int main()
{
ss* p = (ss*)malloc(sizeof(ss) * 3);
for (int i = 0; i < 3; i++)
{
p[i].name= (char*)malloc(sizeof(char) * 21);
p[i].scores = (int*)malloc(sizeof(int) * 3);
p[i].addr = (char*)malloc(sizeof(char) * 51);
}
for (int i = 0; i < 3; i++)
{
scanf("%s%d%d%d%d%s", p[i].name, &p[i].age, &p[i].scores[0],
&p[i].scores[1], &p[i].scores[2], p[i].addr);
}
for (int i = 0; i < 3; i++)
{
printf("%s %d %d %d %d %s\n", p[i].name, p[i].age, (p+i)->scores[0],
(p+i)->scores[1], p[i].scores[2], p[i].addr);
}
//释放
for (int i = 0; i < 3; i++)
{
free(p[i].name);
free(p[i].scores);
free(p[i].addr);
}
free(p);
return 0;
}
结果:
哈哈 18 98 99 96 北京
呵呵 17 95 96 97 上海
嘻嘻 16 89 86 87 广州
哈哈 18 98 99 96 北京
呵呵 17 95 96 97 上海
嘻嘻 16 89 86 87 广州
结构体和函数
示例:
# include<stdio.h>
#include "struct.h"
typedef struct studennt ss;
void fun01(struct student stu1)
{
strcpy(stu1.name, "嘿嘿");//改变形参
printf("%s\n", stu1.name);
}
//若结构体成员为指针,则需要再主函数中开辟堆空间,若其他函数中的形参没开辟堆空间
//则,对形参的改变将影响实参。
int main0901()
{
struct student stu = {
"哈哈",18,89,79,99,"天津" };
fun01(stu);
printf("%s", stu.name);//形参不会改变实参
return 0;
}
void fun02(struct student* p)
{
strcpy(p->name, "你好");//地址传递,可以改变实参
printf("%s\n", p->name);
}
int main0902()
//结构体指针作为函数参数
{
struct student stu = {
"嘻嘻",19,98,79,97,"南京" };
fun02(&stu);
printf("%s", stu.name);
return 0;
}
//数组作为函数参数退化为指针 丢失元素精度,需要传递个数
void BUbbleSort(struct student* stu, int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
if (stu[j].age > stu[j + 1].age)
{
struct student temp = stu[j];
stu[j] = stu[j + 1];
stu[j + 1] = temp;
}
}
printf("\n");
}
}
int main()
{
//结构体数组作为函数参数
struct student stu[3] =
{
{
"张三",20,89,89,89,"宝鸡"},
{
"李四",18,87,87,87,"汉中"},
{
"王五",21,85,85,85,"渭南"}
};
BUbbleSort(stu, 3);
for (int i = 0; i < 3; i++)
{
printf("姓名:%s\n", stu[i].name);
printf("年龄:%d\n", stu[i].age);
printf("成绩1:%d\n", stu[i].score[0]);
printf("成绩2:%d\n", stu[i].score[1]);
printf("成绩3:%d\n", stu[i].score[2]);
printf("地址:%s\n", stu[i].addr);
printf("\n");
}
return 0;
}
结果0901:
嘿嘿
哈哈
结果0902:
你好
你好
结果0903:
姓名:李四
年龄:18
成绩1:87
成绩2:87
成绩3:8949408
地址:
姓名:张三
年龄:20
成绩1:89
成绩2:89
成绩3:8949400
地址:
姓名:王五
年龄:21
成绩1:85
成绩2:85
成绩3:8949416
地址:
const修饰结构体指针
示例:
#include<stdio.h>
typedef struct student ss;
struct student
{
char name[21];
int age;
char sex;
int score[3];
char addr[51];
};
int main1001()
{
ss stu1 = {
"陈一",22,99,99,99,"陈仓" };
ss stu2 = {
"郭二",24,98,98,98,"天水" };
//const修饰结构体指针类型,可修改变量 不能修改指针指向内存空间的值
const ss* p = &stu1;
//p = &stu2;//ok
//(*p).age = 28;//err
//p->age = 30;//err
return 0;
}
int main1002()
{
ss stu1 = {
"陈一",22,99,99,99,"陈仓" };
ss stu2 = {
"郭二",24,98,98,98,"天水" };
//const 修饰结构体指针变量
ss* const p = &stu1;
//strcpy(p->name, "孙叁");//ok
//p = &stu2;//err
//(*p).age = 28;//ok
//p->age = 30;//ok
return 0;
}
//const修饰结构体指针类型,const 修饰结构体指针变量
int main1001()
{
ss stu1 = {
"陈一",22,99,99,99,"陈仓" };
ss stu2 = {
"郭二",24,98,98,98,"天水" };
//const 修饰结构体指针变量
const ss* const p = &stu1;
//p = &stu2;//err
//(*p).age = 28;//err
ss** pp = &p;
//(*pp)->age = 45;//ok 指针指向内容用->
//*pp = &stu2;//ok
//(**pp).age = 50;//ok 变量.向内容用.
return 0
}
联合体
- 联合union是一个能在同一个存储空间存储不同类型数据的类型;
- 联合体所占的内存长度等于其最长成员的长度倍数,也有叫做共用体;
- 同一内存段可以用来存放几种不同类型的成员,但每一瞬时只有一种起作用;
- 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖;
- 共用体变量的地址和它的各成员的地址都是同一地址。
示例:
#include<stdio.h>
union Var //联合体里面类型的地址都是一样的
{
int a;
float b;
double c;
char d;
short f;
};
int main()
{
union Var var;
var.a = 10;
var.b = 3.14;
printf("%d\n",var.a);
printf("%f\n", var.b);//每一瞬时只有一种起作用,起作用的成员是最后一次存放的成员
printf("%d\n", sizeof(var));//大小是按内存最大的类型来计算的
return 0;
}
结果:
1078523331
3.140000
8
枚举
- 枚举:将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。
- 枚举用于流程控制比较多
- 枚举类型定义:
示例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//枚举用于流程控制比较多
enum TYPE
{
run,attack,skill,dance=10,showUI,frozen=20,dizz,dath,moti
}type;
//enum 交易
//{
// 插卡,读卡,锁卡,输入密码,查询,取款,退卡,取卡
//};
int main()
{
int value;
while (1)//死循环
{
scanf("%d", &value);
switch (value)//switch括号中写type是展现出case类型,写value是对各个类型进行输出
{
case run:
printf("英雄正在移动中.....\n");
break;
case attack:
printf("英雄正在攻击中.....\n");
break;
case skill:
printf("英雄正在释放技能中.....\n");
break;
case dance:
printf("英雄正在跳舞中.....\n");
break;
case showUI:
printf("英雄正在显示徽章.....\n");
break;
case frozen:
printf("英雄被冰冻中.....\n");
break;
case dizz:
printf("英雄被眩晕中.....\n");
break;
case dath:
printf("英雄死亡.....\n");
return 0;//外层为死循环,break跳不出来,可以加goto
break;
case moti:
printf("英雄等待释放命令.....\n");
break;
default:
break;
}
}
return 0;
}
结果:
0
英雄正在移动中.....
1
英雄正在攻击中.....
10
英雄正在跳舞中.....
typedef关键字
- 作用:起别名 定义函数指针
- typedef为C语言的关键字,作用是为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型。
- 与#define不同,typedef仅限于数据类型,而不是能是表达式或具体的值。
- #define发生在预处理,typedef发生在编译阶段。
边栏推荐
- How Facebook moves instagram from AWS to its own server
- Tonybot humanoid robot starts for the first time 0630
- Zzuli:1057 prime number determination
- Zzuli:1046 product of odd numbers
- Zzuli:1048 factorial table
- Zzuli:1041 sum of sequence 2
- How to color ordinary landscape photos, PS tutorial
- My QT learning path -- how qdatetimeedit is empty
- Niuke bm83 string deformation (case conversion, string inversion, string replacement)
- Zzuli:1043 max
猜你喜欢
Code writing and playing method of tonybot humanoid robot at fixed distance
tonybot 人形机器人 查看端口并对应端口 0701
Niuke: crossing the river
Pyqt interface production (login + jump page)
tonybot 人形机器人 定距移动 代码编写玩法
论文分享:Generating Playful Palettes from Images
retrofit
The latest M1 dedicated Au update Adobe audit CC 2021 Chinese direct installation version has solved the problems of M1 installation without flash back!
Puzzle (016.3) is inextricably linked
【北大青鸟昌平校区】互联网行业中,哪些岗位越老越吃香?
随机推荐
Amazon, express, lazada, shopee, eBay, wish, Wal Mart, Alibaba international, meikeduo and other cross-border e-commerce platforms evaluate how Ziyang account can seize traffic by using products in th
Happy capital new dual currency fund nearly 4billion yuan completed its first account closing
Sub GHz wireless solution Z-Wave 800 Series zg23 SOC and zgm230s modules
7-3 rental (20 points)
[qingniaochangping campus of Peking University] in the Internet industry, which positions are more popular as they get older?
表单文本框的使用(一) 选择文本
Zzuli:1045 numerical statistics
Adobe Premiere Pro 15.4 has been released. It natively supports Apple M1 and adds the function of speech to text
Tonybot humanoid robot infrared remote control play 0630
My QT learning path -- how qdatetimeedit is empty
Zzuli:1055 rabbit reproduction
Use of form text box (I) select text
Zzuli: cumulative sum of 1050 factorials
Time conversion ()
How to color ordinary landscape photos, PS tutorial
Use of constraintlayout
C language memory function
Zzuli:1052 sum of sequence 4
[combinatorics] permutation and combination (set combination, one-to-one correspondence model analysis example)
FPGA blocking assignment and non blocking assignment