结构体(篇八)

  1. 字符串输入的代替方案
    代替方法:
    一:自定实现 gets
    二:fgets();
    char *fgets(char *s, int size, FILE *stream);
    s:目的地址,用于存储输入的字符串
    size:需输入的字符串的长度
    stream:文件指针
    用做输入字符串时,使用 stdin 即可

     	int fputs(const char *s, FILE *stream);
     		s:要输出的字符串的首地址
     		stream: 用于输出字符串时,使用 stdout
     		
     			stdin:标准输入
     			stdout:标准输出
     			stderr:标准错误输出
     	
     	使用形式:
     		char arr[64] = "";
     		//fgets(arr, 64, stdin); 	//会存储最后输入的换行符
     		fgets(arr, sizeof(arr), stdin);
     		fputs(arr, stdout);
    
  2. strcat() / strcmp()
    字符串拼接:strcat()/strncat()
    字符串比较:strcmp()/strncmp()

    man 手册查看函数原型及详细用法

  3. 结构体
    (1)复合数据类型
    联合体
    枚举类型
    结构体

    结构体是一种构造类型,它是由若干成员组成,每一个成员可以是一个基本类型
    或者是一个构造类型(复合数据类型)

(2)定义
结构体的一般定义形式
struct 结构名称
{
成员列表;
};

成员列表由若干成员组成,每个成员都是该结构的一个组成部分。
每个成员也要做类型说明,形式为:类型说明符 成员名;

注意:
	右 } 右侧的 ; 不可省略
	结构定义相当于结构设计,不分配内存空间
	结构定义放置在程序的开始部分,位于头文件声明之后
	结构体类型名与其成员名,变量名可重复

例如:
	struct student   --- 建议采用
	{ 
		char name[32];
		int age;
		float grade;
	};
	
	student:结构体名称
	struct student:结构数据类型,相当于 int ,double 等数据类型
	//定义一个结构变量:
	struct student stu; //stu 结构体变量
	
	//定义结构体的同时,定义结构体变量  ---- 不建议
	struct student1
	{
		char name[32];
		int age;
	}stu1, stu2;

	//无名结构  --- 不建议使用
	struct
	{
		int a;
		int b;
	}boy, girl;
	
	无名结构只能在声明时,定义变量

	结构体的嵌套定义
	struct date
	{
		int year;
		int month;
		int day;
	};
	
	struct person
	{
		char name[32];
		int age;
		struct date birthday;	//OK
	};

	//结构嵌套定义自身变量
	struct person1
	{
		char name[32];
		int age;
		struct person1 stu;	//Error
	};

	struct person
	{
		char name[32];
		int age;
		struct person *ps;	//OK,指针大小是固定的,4 Byte(32 Bit OS)/8 Byte(64 Bit OS)
	};

(3)结构成员的访问
访问结构成员: .
结构变量名.成员名;

	注意:
		结构体变量不能整体访问,只能访问变量成员	

	例如:
	struct date
	{
		int year;
		int month;
		int day;
	};
	
	struct person
	{
		char name[32];
		int age;
		struct date birthday;	//OK
	};
	
		struct person stu;
		stu.name = "Jack";
		stu.age  = 20;
		stu.birthday.year = 1999;
		stu.birthday.month = 1;

	如果成员本身又是一个结构,则必须找到最低级的成员才能使用

(4)结构体变量的初始化
struct person boy;

	boy = {"Jack", 20, {1999, 1, 3}};
	注意:
		采用此方法进行初始化,数值必须要与结构成员一一对应

	struct person boy1 = boy; //结构体变量之间相互赋值

(5)指向结构变量的指针
a. 结构指针的一般声明形式:
struct 结构名 *结构指针变量名;
b. 引用
同其他类型指针变量相同,结构指针必须先赋值,才能使用
赋值是把结构变量的首地址赋予该指针,不能呢个把结构名赋予该指针变量

	struct person stu;	 //结构体变量
	struct person *pStu; //结构体指针
	
	pStu = &stu;   //OK
	pStu = person; //Error

c. 指针访问成员变量
	结构体指针变量名->成员名;
	(*结构体指针变量名).成员名;
	
	pStu->name = "Jack";
	//pStu = &stu;
	//*pStu = *(&stu);
	//*pStu = stu;
	(*pStu).age = 20;

在 C 语言中,"()", "[]", "->", ".", 四个运算符优先级相同
其次是:*, &, ++, --

(6)typeof
作用:
重命名已有数据类型的名称,主要用于结构体类型的重命名。

	typeof DataType otherName;
	
	typeof float F;
	F grage = 3.14; //等价于 float grage = 3.14;	

结构体取别名:
	struct student
	{
		char name[32];
		int age;
	};

a. 使用宏定义
	#define struct student STU;
	
b. 使用typeof
	typedef struct student tStu;
		
或者使用:
	typedef struct student
	{
		char name[32];
		int age;
	}Stu;

	思考以下变量分别是何种类型:
	#define struct student* STU;
	typedef struct student* tStu;
	
		STU  ps1, ps2, ps3;
		tStu pt1, pt2, pt3;

(7)动态内存分配和释放 — #include <stdlib.h>
a. malloc
void *malloc(int size);
size:要分配的内存大小
void 类型指针可以赋值给任意类型的指针
int *pc = (int *)malloc(5 * sizeof(int));//借助malloc获取二十个字节存储空间
最好强制转换(前面是什么类型 那后面括号就是什么类型)
b. free
void free(void *ptr);

malloc 和 free 总是成对出现:
free 之后的内存地址,将不可访问,否则会造成未知的错误!
避免重复释放内存地址!!否则会出现内存错误

结构指针变量的动态申请
	Stu *pstu = (Stu *)malloc(sizeof(struct struct));
千里之行,始于足下!
原文地址:https://www.cnblogs.com/MINAIot/p/13041013.html