——————————结构体数组————————————————————
结构体数组是指数组元素是结构体的数组
它也有一位数组,二维数组,等之分
int nums[] = ...
char str[] = ...
struct 结构体名 数组名[] = ...
数组的初始化
1, 定义的同时进行初始化
struct CZPoint array[] = { {0, 0}, {11, 22}, {22, 33} };
struct CZPoint array[] = { 0, 0, 11, 22, 22, 33 };
struct CZPoint array[] = { 0, 0, 11, 22, 22 };
struct CZPoint array[5] = { 0, 0, 11, 22, 22 };
2, 先定义再初始化
数组的遍历
for (int i = 0; i < length; i++) {
array[i]...
}
数组作为函数参数
void func(int nums[], int length)
void func(struct CZPoint array[], int length)
#include <stdio.h>
#define getLength(array, type) (sizeof(array) / sizeof(type))
struct CZPoint {
int X;
int Y;
};
void foreachArray(structCZPoint array[],int length) {
printf("length = %d\n", length);
for (int i =0; i < length; i++) {
printf("%d, %d\n", array[i].X, array[i].Y);
}
}
int main(int argc,constchar *argv[]) {
structCZPoint array1[5];
structCZPoint array2[] = {{0,0}, {11,22}, {22, 33}};
structCZPoint array3[] = {0,0,11, 22, 22, 33,44,55, 66, 77};
structCZPoint array4[] = {0,0,11, 22, 22};
structCZPoint array5[5] = {0,0,11, 22, 22};
// int length = sizeof(array4) / sizeof(struct CZPoint);
//
// printf("%d\n", length);
//
// for (int i = 0; i < length; i++) {
// printf("%d, %d\n", array4[i].X, array4[i].Y);
// }
// foreachArray(array2, getLength(array2, struct CZPoint));
foreachArray(array3,getLength(array3, struct CZPoint));
return 0;
}
——————————————————————————————
#include <stdio.h>
struct Phone {
char name[31];
char phone[14];
};
// 学习使用 scanf
// scanf("%d", &num);
void czscanf(structPhone *p,int i) {
//(*p).name = ...
// (*p).phone = ...
printf("=============\n");
//提示用户的输入
printf("请输入第 %d个人的信息\n", i +1);
// 提供输入
scanf("%s", (*p).name);
//提示输入电话
printf("请输入电话号码\n");
scanf("%s", (*p).phone);
}
int main(int argc,constchar *argv[]) {
structPhone array[5];
for (int i =0; i <5; i++) {
// printf("=============\n");
// // 提示用户的输入
// printf("请输入第 %d个人的信息\n", i + 1);
// // 提供输入
// scanf("%s", array[i].name);
// // 提示输入电话
// printf("请输入电话号码\n");
// scanf("%s", array[i].phone);
czscanf(&array[i], i);
}
//打印出来输入的信息
int length =sizeof(array) /sizeof(structPhone);
for (int i =0; i < length; i++) {
printf("%s : %s\n", array[i].name, array[i].phone);
}
return 0;
}
————————结构体指针——————————————————————
指向结构体类型的指针
与指向 int类型的指针一样,从定义到使用都是一样的规则
int num;
int (*p); -> &(*p) -> p
int (*p)[] .. *p
int (*p)() ... p
struct Point point;
struct Point *p;
p 就是指向一个结构体变量的指针
#include <stdio.h>
struct CZPoint {
int X;
int Y;
}; // p1 = { 10, 20 };
int main(int argc,constchar * argv[]) {
//利用结构体的赋值
structCZPoint point1 = {11,22 };
structCZPoint point2;
structCZPoint *p1 =NULL;
structCZPoint *p2 =NULL;
// 1
point2 = point1; // 将结构体中所有的变量的值都复制一份, 赋值给 point2的所有的变量
// 2
p1 = &point1;
p2 = p1; // 将 p1 中存储的地址 复制 一份, 赋值给 p2, 此时 p1 和 p2 都是指向 point1
return0;
}
————————$——————————————————————
#include <stdio.h>
struct CZPoint {
int X;
int Y;
};
int main(int argc,constchar *argv[]) {
structCZPoint point = {11,22};
structCZPoint *p = &point;
// 使用 p 去访问 point 里面$的 X Y 成员需要使用 (*p).Y
//使用 ->符号,可以直接使用指针变量访问成员
printf("( %d, %d )\n", (*p).X, (*p).Y);
printf("( %d, %d )\n", p->X, p->Y);
// Student...Score
// (*(*stu).score).mathScore
// stu -> score -> mathScore
return 0;
}
—————单项链表$—————————————————————————
#include <stdio.h>
#include <stdlib.h>
struct Temp {
int num;
structTemp *next;
};
int main(int argc,constchar * argv[]) {
structTemp t1;
t1.num =10;
//
// struct Temp t2;
// t2.num = 20;
//
// t1.next = &t2;
// 添加一个新的项
t1.next = (structTemp *)malloc(sizeof(structTemp));
t1.next->num =20;
t1.next->next = (structTemp *)malloc(sizeof(structTemp));
t1.next->next->next = &t1;
// 单向链表
return0;
}
———————————枚举———————————————————
为了表征某一个特性的状态,状态会有很多种,常常使用的是数字
但是数字不太方便记忆与使用,因此可以考虑使用宏定义,但是
宏定义容易混淆,可以考虑使用枚举
语法: enumator
enum 枚举的类型名 {
枚举成员(和标识符)
};
定义枚举类型的变量
enum 枚举类型名 变量名;
赋值:
1, 先定义再赋值
2, 定义的同时赋值
赋值就是将枚举中的项赋值给变量即可
使用枚举有一个规范
所有的枚举项都一应该以枚举类型开头
——————————————————————————————
C 语言枚举的本质是数字
定义的枚举实际上就是数字的一个别名
枚举类型的项,从第 0项,往后默认就是从 0开始的编号
枚举类型允许为枚举项赋值,如果赋值了,从下一项开始又是新数字的递增
系统的枚举类型,常常会定义成标志枚举
// 为了表示某一个特征的状态
enum State {
state1 =0, // 0000 0000
state2 =1, // 0000 0001
state3 =1<<1, // 0000 0010
state4 =1<<2, // 0000 0100
state5 =1<<3 // 0000 1000
};
———————————typedef———————————————————
语法:
typedef 定义变量的写法;
这个变量的名字就是新类型的名字
// typedef 关键字用来定义新的类型,可以将复杂的声明规则进行简化
// void (*p)(int num1, int num2) => 类型名 p;
// struct Student stu; => Student stu;
// 语法
// typedef 变量的定义规则;
// 原来应该定义成变量的名字就是类型名
int func1(char *str,int length) {
printf("%s\n", str);
return length *2;
}
// 写一个函数, 返回一个无参无返回值的函数指针?
typedef int (*p)(char *,int);
typedefvoid (*CZFunc)();
CZFunc func2() {returnNULL; }
// 在 C 语言中 不允许在 函数体内声明函数, 所以也就没有这种用法
int main(int argc,constchar *argv[]) {
// int 2 4 8
// int16, int32, int64
// int int16; // 定义变量
// typedef short int16; // 此时就定义了一个 int16 的类型,
//可以使用这个了类型定义新的变量,新的变量类型是 short
// int16 num = 10;
// printf("%d\n", num);
// int (*p)(char *, int); // 定义了一个指向 int 返回值, 带有 char * 和 int
//类型参数的函数的指针
// typedef int (*p)(char *, int);
p p1;
p1 =func1;
int num = p1("abc",10);
printf("%d\n", num);
return 0;
}
——————————————————————————————
#include <stdio.h>
#include <stdlib.h>
//
struct Teacher {
int age;
};
int main1(int argc,constchar *argv[]) {
//定义一个数组指针
// int (*p)[10]; // 定义了一个变量
typedefint(*ptr_array)[3];
//定义了一个数据类型, ptr_array该类型声明的变量,是一个可以指向长度为 3的
// 一维数组的
ptr_array p;
int array[][3] = {1,2,3, 4, 5, 6,7,8, 9};
//
p = array; // p 指向 array[0]
for (int i =0; i <3; i++) {
for (int j =0; j <3; j++) {
// *( *( p + i ) + j )
printf("%d\t", *(*(p + i) + j));
}
printf("\n");
}
return 0;
}
int main(int argc,constchar *argv[]) {
//定义一个结构体类型
// typedef 定义变量; 变量就是类型名
/* struct Person {
int age;
} p1; */
typedefstruct Pers {int age; } Person;// 定义了一个 Person的结构体类型
// typedef 旧类型名 新类型名;
typedefstruct {int age; } Student;
typedefstructTeacher Teacher;
Teacher tch;
tch.age =30;
structPers p1;
p1.age =20;
printf("%d\n", p1.age);
Person p;
p.age =10;
printf("%d\n", p.age);
return 0;
———————预处理———————————————————————
#include <stdio.h>
#define NAME "你好");
int main(int argc,constchar *argv[]) {
// 源文件(.c) -> 编译器(预编译,编译) ->目标文件(.o) -> 链接器 ->
// 可执行(a.out)
// IDE, 集成开发环境
// 预编译
// 1, 宏替换(宏展开)
// 2, 检测语法
// 3, 去掉注释
// ...
// 宏替换
//就是使用宏名后面的内容,替换代码宏使用到宏名的地方(除了字符串以外)
char *str ="NAME";
// Mac 平台
// clang -c 源文件.c -o 目标文件.o 编译
// clang 目标文件.o -o 输出文件 链接
// clang 源文件.c -o 输出文件 编译链接一起完成
// clang -S 源文件.c -o 汇编文件
// clang -E 源文件.c -o 宏替换的文件
// Objective-C
// clang -framework 框架名 源文件名.c -o 输入文件 编译链接已完成
printf(NAME
return0;
}
——————————————————————————————
/*
什么时候用带参数的宏
1, 不需要使用函数的时候,但是又有很多重复代码的时候,可以使用带参数的宏
2, 函数代码及其短小的时候,可以使用宏
3, 对于重复的操作,但是无法使用函数的时候,使用带参数宏
语法:
#define 宏名(形式参数1,形似参数2, ...) 替换体
*/
#include <stdio.h>
// 完成加减法
#define Add(num1, num2) (num1 + num2)
#define Mult(n1, n2) ((n1) * (n2))
#define LEN(array, type) (sizeof(array) / sizeof(type))
// 类似于 if 的结构, 很轻松写成宏
#define Func(num) \
if ((num) >10) { \
printf("大于10\n"); \
}elseif ((num) <10) { \
printf("小于10\n"); \
}else { \
printf("等于10\n"); \
}
// int getLength(int array[], int length) {
//
//}
int main(int argc,constchar *argv[]) {
// int n1 = 10;
// int n2 = 20;
//
// int res = Add(n1, n2) * 3; // 30 * 3 // 10 + 20 * 3
// printf("%d + %d = %d\n", n1, n2, res);
//
// // => int res = n1 + n2;
//
// float fNum1 = 1.123;
// float fNum2 = 2.234;
//
// float res2 = Add(fNum1, fNum2) * 2; //
//
// printf("%f + %f = %f\n", fNum1, fNum2, res2);
// int num1 = 10;
// int num2 = 3;
// int res = Mult(num1 + 1, num2); // (10 + 1) * 3 => 10 + 1 * 3
//
// printf("%d\n", res);
Func(1);
return 0;
——————————————————————————————