用户自定义数据类型
约 1973 字大约 7 分钟
2024-07-07
71.结构体的定义和初始化
#include <stdio.h>
//结构体定义总结:结构体标记和变量名至少有一种,如果有变量。可以进行初始化
struct Student //1.定义时为结构体起一个结构体标记名
{
char name[30];
int age;
double score;
};
struct Student2 //2.定义时为结构体起一个结构体标记名并定义这种数据类型的变量
{
char name[30];
int age;
double score;
}A,*p;
struct Student3 //3.定义时为结构体起一个结构体标记名并为变量初始化
{
char name[30];
int age;
double score;
}A1={"张三",23},*p1;
struct //4.只定义结构体类型的变量
{
char name[30];
int age;
double score;
}A2,*p2;
void f(void);
int main(void)
{
f();
struct Student a ={"张三",28,34}; //①完全初始化
struct Student b ={"张三",28}; //②部分初始化
struct Student c = a; //③定义结构体变量时,使用其他的结构体变量完成初始化
struct Student d ={.score = 23}; //④c99支持这种形式在定义一个定义一个结构体变量时,对其某一个成员初始化
printf("学生的姓名:%s,年龄:%d,成绩:%lf",c.name,c.age,c.score);
return 0;
}
void f(void)
{
struct Student a;
printf("请输入学生的姓名、年龄和成绩\n");
scanf("%s%d%lf",&a.name,&a.age,&a.score);
printf("学生的姓名:%s,年龄:%d,成绩:%lf",a.name,a.age,a.score); //①可以通过 变量名.成员名的方式访问一个结构体变量的成员
struct Student *p =&a;
printf("学生的姓名:%s,年龄:%d,成绩:%lf",p->name,p->age,p->score); //②可以通过 指针->成员名 的方式访问一个结构体变量的成员
}
72.1结构体变量所占字节长度
#include <stdio.h>
#define N 4
struct Stu
{
char name[30];
double score;
};
void input(struct Stu *p,int len)
{
for(int i = 0;i<len;++i)
{
printf("请输入第%d个学生的姓名和成绩:\n",i+1);
// scanf("%s%lf",&p[i].name,&p[i].score); 与下面一句等价
scanf("%s%lf",&(p+i)->name,&(p+i)->score);
}
}
void sort(struct Stu *p,int len)
{
for(int i =0;i<len-1;++i)
for(int j =0;j<len-1-i;++j)
{
if(p[j].score>p[j+1].score)
{
struct Stu b =p[j];
p[j]=p[j+1];
p[j+1]=b;
}
}
}
void show(struct Stu *p,int len)
{
for(int i =0;i<len;++i)
printf("第%d个学生的姓名:%s,成绩:%lf\n",i+1,p[i].name,p[i].score);
}
int main(void)
{
struct Stu a[N];
input(a,N);
sort(a,N);
show(a,N);
return 0;
}
72.2结构体数组和指针
#include <stdio.h>
int main(void)
{
//字节对齐,各种数据类型是按照一定的规则在内存中排列的
short a;
int b;
double c;
printf("%d,%d,%d\n",(int)&a%2,(int)&b&4,(int)&c%8);
struct Stu1
{
char a;
short b;
};
struct Stu2
{
char a;
int b;
};
struct Stu1 A;
struct Stu2 B;
printf("%d,%d\n",(int)&A%2,(int)&B%4);//1.结构体变量的首地址能够被其最宽基本类型成员的大小所整除
printf("%d,%d\n",sizeof(A),sizeof(B));//2.结构体成员对于结构体变量的首地址的偏移量都是对其成员大小的整数倍
printf("%d,%d\n",(int)&A.b-(int)&A%2,(int)&B.b-(int)&B%4);
struct Stu3
{
char a;
double f;
int b;
}C;
printf("%d\n",sizeof(C)); //结构体总大小为结构体最宽基本类型成员的整数倍
struct Stu4
{
char a;
struct Stu2 b;
}D;
printf("&d\n",sizeof(D)); //如果结构体成员是复合数据类型的,那么它对于结构体首地址的偏移量,应该是其最宽基本类型成员的整数倍
return 0;
}
72.3复杂的数据类型
看变量所属圆括号的最外层,把最外层的数据类型设为一个新数据类型,然后去掉最外层的圆括号,通过这种方法,直到原式转化为“整型数据变量”的形式
73.typedef
#include <stdio.h>
typedef int Count; //1.Count代表int类型
typedef int Num[3]; //2.NUm代表一个含有3个int型元素的数组类型
typedef struct
{
int a;
double b;
}Stu; //3.Stu代表一个结构体类型
#define INI int
int main(void)
{
Count a = 3; //①定义一个int类型变量a
printf("%d\n",a);
Num b ={1,3,4}; //②定义一个含有3个int类型元素的数组b
printf("%d%d%d",b[0],b[1],b[2]);
Stu m={12,34}; //③定义了1个结构体类型变量m
printf("%d,%lf",m.a,m.b);
INI c =10;
printf("%d\n",c); //④在预编译阶段,该句被替换为 int c =10;
return 0;
}
74.单向动态链表
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Node
{
int data;
struct Node *pnext;
}N,*P;
P create(void)
{
P pheard = (P)malloc(sizeof(N));
if(pheard == NULL)
{
printf("分配内存失败,程序退出\n");
exit(-1);
}
pheard->pnext = NULL;
return pheard;
}
void input(P pheard,int value)
{
P last = (P)malloc(sizeof(N));
if(last == NULL)
{
printf("分配内存失败,程序退出\n");
exit(-1);
}
last->data = value;
last->pnext = NULL;
while (pheard->pnext !=NULL)
pheard = pheard =last;
pheard->pnext = last;
}
void show(P pheard)
{
while(pheard->pnext != NULL)
{
pheard = pheard->pnext;
printf("%d\n",pheard->data);
}
}
int len(P pheard)
{
for(int i =0;(pheard = pheard->pnext) != NULL;++i)
{
;
return i;
}
}
bool del(P pheard,int index)
{
if(index <=0 || index > len(pheard))
return false;
for(int i =1;i<index;++i)
pheard = pheard->pnext;
P ptail=pheard->pnext->pnext;
free(pheard->pnext);
pheard->pnext=ptail;
return true;
}
bool insert(P pheard,int index,int value)
{
if(index <=0 || index >len(pheard)+1)
return false;
P pw = (P)malloc(sizeof(N));
if(pw == NULL)
{
printf("分配内存失败,程序退出\n");
exit(-1);
}
pw->data = value;
for(int i =1;i<index;++i)
pheard =pheard->pnext;
pw->pnext = pheard->pnext;
pheard->pnext= pw;
}
int main(void)
{
P pheard = create();
input(pheard,1);
input(pheard,2);
input(pheard,3);
input(pheard,4);
// del(pheard,2);
insert(pheard,2,10);
show(pheard);
printf("%d\n",len(pheard));
return 0;
}
75.共用体的定义和变量初始化
#include <stdio.h>
union Data
{
int i;
char ch;
double f;
};
int main(void)
{
union Data a;
// a =3; error 不可以直接用一个基本类型的数据对共用体变量赋值
a.i=3;
printf("%d\n",a.i);
a.ch = 'A';
printf("%lf\n",a.ch);
a.f = 3.14;
printf("%lf\n",a.f);
printf("%d,%c\n",a.i,a.ch); //输出垃圾值,因为共用体所有成员所使用d内存的开头地址的值都是一样的。所以当我们对其中一个成员赋值,其他成员也会改变
//定义共用体变量时的初始化
union Data b={123}; //此种方式只能对共用体第一个元素进行赋值
// void Data c = {.f = 4.5}; //这种方法可以指定某一个成员进行赋值,这属于C99的功能
union Data d =b; //c.99允许共用体变量互相赋值
//1.共用体变量的地址和长度必须被其最宽基本类型成员的大小整除
//2.其总长度必须大于等于最宽成员的宽度
union Data2
{
char a[10];
int b;
}g;
printf("%d\n",sizeof(g));
return 0;
}
76.枚举类型
#include <stdio.h>
//枚举类型定义总结:枚举名和枚举变量至少有一个即可,如果有变量,可以对变量进行初始化。定义枚举元素时也可以显示的指定数值
enum A{a1,a2,a3,a4}; //1.只定义枚举名
enum B{b1=3,b2,b3,b4=4,b5,b6,b7}; //2.给部分枚举元素指定一个值
enum C{c1,c2,c3}n; //3.定义枚举名和枚举变量
enum {d1,d2,d3}m; //4.只定义枚举变量而不定义枚举名
enum E{e1,e2,e3}k =e2; //5.定义了枚举变量并为其初始化
int main(void)
{
enum A w =a2;
// w =1; error 因为两者数据类型不同
w= (enum A)1; //强制数据类型转换
printf("%d\n",w);
// a2 = (enum A)10; error 因为a2是一个常量
printf("%d,%d,%d,%d\n",a1,a2,a3,a4); //因为c语言在编译的时候会根据枚举元素定义的顺序分别给他们一个默认值0
printf("%d,%d,%d,%d,%d,%d,%d",b1,b2,b3,b4,b5,b6,b7); //定义枚举类型的时候可以为枚举元素指定一个值,未指定值的元素的值将是前一个元素加1的值
return 0;
}