C Primer Plus 第14章总结

直达我的博客主页(gitee版)

C Primer Plus 第14章总结链接1

结构和其他数据形式

结构变量的建立、声明及初始化(链接
建立

定义结构体前的准备阶段,此时应明确结构体中应含有的变量种类及数量。

声明

申明结构体需要使用struct语句(与intfloat相似但不同),声明样例如下:

/* 声明样例1 */
struct tag { 
    member-list
    member-list 
    member-list  
    ...
} variable-list ;
/* 声明样例2 */
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;

样例1中结构体tag包含多个变量,定义tag后其中含有多个成员。

样例2中结构体Books中包含titleauthorsubjectbook_id四个变量,而最后一个分号前的book则定义了一个类型为Books的结构体变量book

初始化

初始化样例如下:

/* 初始化样例 */
struct book library{
    "The Pious Pirate and Devious Damsel",
    "Renee Vivotte",
    1.95
};

该样例将结构体library中的变量初始化赋值。

结构体的数据对齐原则(链接

1: 整体空间是占用空间最大的成员(的类型)所占字节数的整数倍,若最大成员类型所占字节数超过4,如double是8,则整体空间是4的倍数即可。
2: 数据对齐原则。内存按结构体成员的先后顺序排列,当排到该成员变量时,其前面已摆放的空间大小必须是该成员类型大小的整数倍,如果不够则补齐,依次向后类推。某成员类型所占字节数超过4,如double是8,则前面已摆放的空间大小是4的整数倍即可,不够则补齐。

结构成员的访问

结构成员的访问需要使用成员访问运算符.例:library.value便是结构体变量library中的value变量。

/* 样例 */
struct book gift = {
    .value= 25.99,
    .author = "James Broadfoot",
    .title = "Rue for the Toad"};
结构数组(链接

结构数组中的每一个元素都是struct book类型的结构体变量。

/* 结构体声明略 */
struct STUDENT stu[10];

stu[i]便是stu数组中的第i + 1个结构体变量。

嵌套结构(链接

在一个结构中包含另一个结构,以方便使用。

 /* 样例 */
struct Student_info{ 
    char *name;         //姓
    char *Branch_name;  //名

    struct Evaluation{
        char *division; 
        int hsc_score;
        int ssc_score;
        int roll_num; 		
    }eval;

}student;
指向结构的指针(链接

当一个指针变量指向结构体时,我们就称它为结构体指针。

//结构体
struct stu{
    char *name;     //姓名
    int num;        //学号
    int age;        //年龄
    char group;     //所在小组
    float score;    //成绩
} stu1 = { "Tom", 12, 18, 'A', 136.5 };
struct stu *pstu = &stu1;   //结构体指针

使用

#include <stdio.h>

int main(){
    struct{
        char *name;     //姓名
        int num;        //学号
        int age;        //年龄
        char group;     //所在小组
        float score;    //成绩
    } stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
    //读取结构体成员的值
    printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score);
    printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", pstu->name, pstu->num, pstu->age, pstu->group, pstu->score);
    return 0;
}

->是一个新的运算符,习惯称它为“箭头”,有了它,可以通过结构体指针直接取得结构体成员;这也是->在C语言中的唯一用途。

运行结果:

Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!
Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!
#include <stdio.h>

struct stu{
    char *name;     //姓名
    int num;        //学号
    int age;        //年龄
    char group;     //所在小组
    float score;    //成绩
}stus[] = {
    {"Zhou ping", 5, 18, 'C', 145.0},
    {"Zhang ping", 4, 19, 'A', 130.5},
    {"Liu fang", 1, 18, 'A', 148.5},
    {"Cheng ling", 2, 17, 'F', 139.0},
    {"Wang ming", 3, 17, 'B', 144.5}
}, *ps;

int main(){
    //求数组长度
    int len = sizeof(stus) / sizeof(struct stu);
    printf("Name\t\tNum\tAge\tGroup\tScore\t\n");
    for(ps=stus; ps<stus+len; ps++){
        printf("%s\t%d\t%d\t%c\t%.1f\n", ps->name, ps->num, ps->age, ps->group, ps->score);
    }

    return 0;
}

运行结果:

NameNumAgeGroupScore
Zhou ping518C145.0
Zhang ping419A130.5
Liu fang118A148.5
Cheng ling217F139.0
Wang ming317B144.5
向函数传递结构的信息(链接
传递结构成员

有时候我们并不需要对于结构体的全体成员进行访问,而只需要单个的或者个别几个的成员便足矣。这时候我们只需要将结构体的部分成员对函数及逆行传参即可。

#include<stdio.h>

struct	person
{
	char	name[10];		//成员姓名
	char	sex;			//成员性别
	double	salary;			//平日工资
	double	extra_gains;	//外快收入
};

double sum(double x,double y)
{
	return(x + y);
}

int main()
{
	struct person Zhangsan =
	{
		"张三",
		'm',
		10000,				//张三日常划水的工资收入
		10000000,			//法外狂徒的外快收入
	}

	printf("张三一个月的收入有%.2f元\n",sum(Zhangsan.salary,Zhangsan.extra_gains));

	return 0;
}

传递结构

希望能够更加方便地对整个结构体进行操作,在现行的C语言标准下,是可以的,通过该函数后变化的只是结构体的副本,而非结构体本身。

#include<stdio.h>

struct	person
{
	char name[10];		    //成员姓名
	char sex;			    //成员性别
	double salary;			//平日工资
	double extra_gains;	    //外快收入
};

double sum(struct person who)
{
	return(who.salary + who.extra_gains);
}

int main()
{
	struct person Zhangsan =
	{
		"张三",
		'm',
		10000,				//张三日常划水的工资收入
		10000000,			//法外狂徒的外快收入
	};

	printf("张三一个月的收入有%.2f元\n", sum(Zhangsan));

	return 0;
}
传递结构的地址

将指向结构体的指针作为参数传入到函数当中,由于指针本身只占有4个字节,内存较小,同时也能对结构体本身进行修改。

#include<stdio.h>

struct	person
{
	char	name[10];		//成员姓名
	char	sex;			//成员性别
	double	salary;			//平日工资
	double	extra_gains;	//外快收入
};

double sum(struct person who)
{
	who.extra_gains += who.salary;
	return( who.extra_gains);
}

int main()
{
	struct person Zhangsan =
	{
		"张三",
		'm',
		20000,				//张三日常划水的工资收入
		10000000,			//法外狂徒的外快收入
	};

	printf("张三一个月的收入有%.2f元\n", sum(Zhangsan));
	printf("此时Zhangsan的extra成员的值为%f\n", Zhangsan.extra_gains);

	return 0;
}
复合字面量和结构(链接

复合字面量:通过复合字面量,我们可以在一个语句中给结构变量的多个成员变量赋值。

struct time this_time={3,29,55};//相当于定义了时间结构变量,并将其设置为3:29:55
struct time={.hour=12,.minut=10};//通过给出成员的名字,可以以任意顺序初始化结构变量的成员,或者只初始化部分成员
struct date birthdays[10];  //定义了一个结构数组,该数组包含了10个元素,每个元素都是一个结构类型变量

birthdays[1].month=8;
birthdays[1].day=8;

birthdays[1].year=2004;     //将结构数组中的第二个元素赋值为2004年8月8日
checkdate(birthdays[1]);    //将数组中第二个元素传递给checkdate函数

//checkdate的函数定义可能如下:
void checkdate (struct date d0){}//因为该函数需要接收struct date类型参数
伸缩型数组成员(链接
struct flex{
    int count;
    double average;
    double scores[];    //伸缩型数组成员,利用molloc动态分配
} 
#include <stdio.h>
#include <stdlib.h>

struct arr
{
	int 	count;
	double 		average;
	double 		scores[]; 			//伸缩型数组成员
};

void show_arr(const struct arr *p);	//不改变结构体中的内容,故使用关键字const

int main (int argc, char *argv[])
{
    int 			total = 0;
    int				n = 5;
    int 			i;
    struct arr 	   *p1;

    //为结构体分配存储空间
    p1 = malloc(sizeof(struct arr) + n * sizeof(double));

	p1->count = n;
    for (i = 0; i < n; i++)
    {
    	p1->scores[i] = 20.0 - i;
    	total += p1->scores[i];
    }
    p1->average = total / n;
    show_arr(pl);
	
	//释放在堆中动态分配的存储空间
	free(p1);	

    return 0; 
}

void show_arr(const struct arr *p)
{
	int i;

    printf ("Scores : ");
    for (i = 0; i < p->count; i++)
    {
    	printf("%g ", p->scores[i]);
    }
    
    printf ("\n");
    printf ("Average: %g\n", p->average) ;
}
匿名结构(链接

C语言中,可以在结构体中声明某个联合体(或结构体)而不用指出它的名字,如此之后就可以像使用结构体成员一样直接使用其中联合体(或结构体)的成员。

把结构内容保存到文件中(链接

利用fprintffreadfwrite,对文件进行读写操作。

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

ptr – 这是指向带有最小尺寸 size*nmemb 字节的内存块的指针。
size – 这是要读取的每个元素的大小,以字节为单位。
nmemb – 这是元素的个数,每个元素的大小为 size 字节。
stream – 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

ptr – 这是指向要被写入的元素数组的指针。
size – 这是要被写入的每个元素的大小,以字节为单位。
nmemb – 这是元素的个数,每个元素的大小为 size 字节。
stream – 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。

int fprintf(FILE *stream, const char *format, …)

stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
format – 这是 C 字符串,包含了要被写入到流 stream 中的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。format 标签属性是 %[flags][width][.precision][length]specifier,具体讲解见链接

链式结构(链接

二叉树及相关知识

联合体(共用体)简介(链接

结构体(Struct)是一种构造类型或复杂类型,它可以包含多个类型不同的成员。在C语言中,还有另外一种和结构体非常类似的语法,叫做共用体(Union)。
结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。

枚举类型(链接

枚举enum是 C 语言中的一种基本数据类型,它可以让数据更简洁,更易读。
第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。
把第一个枚举成员的值定义为 1,第二个就为 2,以此类推。

#define MON  1
#define TUE  2
#define WED  3
#define THU  4
#define FRI  5
#define SAT  6
#define SUN  7
enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};
typedef简介(链接

typedef是C语言的一个重要的关键字,是为数据类型的定义一个新的名字。也就是类型的别名。

#include<stdio.h>
typedef int A;
int main(void)
{
	A a = 10;
	printf("a = %d", a);
	return 0;
}
其他复杂的声明
符号含义优先级
*表示一个指针
()表示一个函数
[]表示一个数组
函数和指针(链接

可以把适当类型的函数的地址赋给函数指针,然后通过函数指针访问函数。

void ToUpper (char *);
void ToLower (char *);
int round (double);
void (*Pf) (char *);
pf = ToUpper;       // 合法,ToUpper是函数ToUpper( )的地址
pf = ToLower;       // 合法,ToLower是函数ToLower( )的地址
// pf = round;      // 非法,round是错误类型的函数
// pf = ToLower();  // 非法,ToLower()不是地址

  1. 本人编程萌新,见解仅供参考。 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值