赞
踩
建议学完指针再学
为什么要有自定义数据类型?
基本数据类型不能满足我们在编程中的要求时,需要自己定义一些数据类型使用。
如果我们想存储单个数据,可以直接用数组存储;那么如果我们想存储多个数据呢?
比如我们要存储学生的学号、姓名、性别、年龄,又该如何操作呢?这就要用到结构体了
struct 结构体名
{
成员列表
};
在定义结构体时,常常会用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; }
结构体类型指针访问成员的获取和赋值形式:
实例:
#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呢?
原来是内存对齐惹的祸
成员共享同一块存储空间
共用体的定义
union 共用体名
{
成员列表
};
定义和用法类比于结构体
共用体内存分配符合两项原则:
例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
};
使用枚举类型对变量进行声明
方法一:枚举类型的定义和变量的声明分开
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。