c学习笔记 结构和其他数据形式 20210325

结构, 指针和malloc()

使用malloc()分配内存, 在结构中使用指针处理字符串就比较合理

struct namect{
	char * fname;
	char * lname;
	int letters;
};
void getinfo (struct namect * pst)
{
	char temp[SLEN];
	printf("Please enter your first name.\n");
	s_gets(temp, SLEN);
	pst -> fname = (char * ) malloc (strlen(temp) + 1);
	strcpy(pst-> fname, temp);
	printf("Please enter your last name.\n");
	s_gets(temp, SLEN);
	pst -> lname = (char *)malloc (strlen(temp) + 1);
	strcpy(pst -> lname, temp);
}

还需创建cleanup()函数, 释放动态分配的内存

void cleanup(struct namect * pst)
{
	free(pst -> fname);
	free(pst -> lname);
}

复合字面量和结构(c99)

复合字面量声明语法:
把类型名放在圆括号内, 后面紧跟一个花括号括起来的初始化列表

(struct book){"The Idiot", "Fyodor Dostoyevsky", 6.99}
#include <stdio.h>

#define MAXTITL 41
#define MAXAUTL 31

struct book {
	char title[MAXTITL];
	char author[MAXAUTL];
	float value;
};

int main(void)
{
	struct book readfirst;
	int score;

	printf("Enter test score: ");
	scanf("%d", &score);

	if (score >= 84)
		readfirst = (struct book){ "Crime and Punishment", "Fyodor Dostoyevsky", 11.25 };
	else
		readfirst = (struct book){"Mr. Bouncy's Nice Hat", "Fred Winsome", 5.99};
	printf("Your assigned reading:\n");
	printf("%s by %s: $%.2f\n", readfirst.title, readfirst.author, readfirst.value);
	return 0;
}

匿名结构(c11)

c11中可以用嵌套的成员结构定义结构:

struct person
{
	int id;
	struct {char first[20]; char last[20];};
};
struct person ted = {8483, {"Ted", "Grass"}};

访问时只需要把first看成是person的成员即可

puts(ted.first);

使用结构数组的函数

#include <stdio.h>
#define FUNDLEN 50
#define N 2

struct funds {
	char bank[FUNDLEN];
	double bankfund;
	char save[FUNDLEN];
	double savefund;
};
double sum(const struct funds money[], int n);
int main(void)
{
	struct funds jones[N] = {
		{
			"Garlic-Melon Bank",
			4032.27,
			"Lucky's Savings and loan",
			8543.94
		},
		{
			"Honest Jack's Bank",
			3620.88,
			"Party Time Savings",
			3802.91
		}
	};
	printf("The Joneses have a total of $%.2f.\n", sum(jones, N));
	return 0;
}

double sum(const struct funds money[], int n)
{
	double total;
	int i;

	for (i = 0, total = 0; i < n; i++)
		total += money[i].bankfund + money[i].savefund;
	return (total);
}

money指向jones数组的首地址
可以把数组名作为数组第一个结构的地址传递给函数。

把结构内容保存到文件中

结构是构建数据库的重要工具
数据库文件可以包含任意数量的此类数据对象。储存在一个结构中的整套信息称为记录(record), 单独的项称之为字段

fwrite(&primer, sizeof(struct book), 1,  pbooks);

定位到primer结构的位置, 并把其中所有字节都拷贝到与pbooks相关的文件中。

其相同参数的fread()函数, 这两个参数都一次读写整个记录, 而不是一个字段。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10

struct book {
	char title[MAXTITL];
	char author[MAXAUTL];
	float value;
};

int main(void)
{
	struct book library[MAXBKS];
	int count = 0, index, filecount;
	FILE* pbooks;
	int size = sizeof(struct book);

	if ((pbooks = fopen("book.dat", "a+b")) == NULL)
	{
		fputs("Can't open book.dat file\n", stderr);
		exit(1);
	}

	rewind(pbooks);
	while (count < MAXBKS && fread(&library[count], size, 1, pbooks) == 1)
	{
		if (count == 0)
			puts("Current contents of book.dat:");
		printf("%s by %s: $%.2f\n", library[count].title, library[count].author, library[count].value);
		count++;
	}
	filecount = count;
	if (count == MAXBKS)
	{
		fputs("The book.dat file is full.", stderr);
		exit(2);
	}

	puts("Please add new book titles.");
	puts("Press [enter] at the start of a line to stop.");
	while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL && library[count].title[0] != '\0')
	{
		puts("Now enter the author.");
		s_gets(library[count].author, MAXAUTL);
		puts("Now enter the value.");
		scanf("%f", &library[count++].value);
		while (getchar() != '\n')
			continue;
		if (count < MAXBKS)
			puts("Enter the next title.");
	}

	if (count > 0)
	{
		puts("Here is the list of your books:");
		for (index = 0; index < count; index++)
			printf("%s by %s: $%.2f\n", library[index].title, library[index].author, library[index].value);
		fwrite(&library[filecount], size, count - filecount, pbooks);
	}
	else
		puts("No books? Too bad.\n");
	puts("Bye.\n");
	fclose(pbooks);
	return 0;
}

程序以”a + b”模式打开文件, 即二进制更新模式, 在现有文件后面追加, rewind()确保文件指针位于文件开始处, 第一个while()每次把一个结构读入结构数组中直到数组满或文件结尾, filecount统计已读结构的数量。
第二个while()提示用户输入, 添加到数组的末尾。
for循环打印文件及用户输入的数据,新写入的内容添加到文件现有内容的末尾。

这种方法相对简单, 不过这种方法浪费内存。

链式结构(linked structure)

联合(union)

联合可以在同一个内存空间储存不同的数据类型, 其典型用法为设计一种表储存既无顺序也无规律的混合类型
带标记的联合模板:

union hold{
	int digit;
	double bigfl;
	char letter;
};

以上形式声明的联合能且仅能储存一个int型或double型或char类型的值。
声明方法:

union hold fit;    // hold类型的联合变量
union hold save[10];     // 含10个联合变量的数组
union hold *pu;    // 指向hold类型联合变量的指针

联合初始化方法;

union hold valA;
valA.letter = 'R';
union hold valB = valA;    // 使用另一个联合进行初始化
union hold valC = {88};   // 初始化联合的digit成员
union hold valD = {.bigfl = 118.2};   //制定初始化器

使用联合

fit.digit = 23;        //储存23, 占2字节
fit.bigfl = 2.0;      //清除20, 储存2.0, 占8字节
fit.letter = 'h';      //清除2.0, 储存h, 占1字节

联合中一次只储存一个值
指针访问联合应使用->运算符:

pu = &fit;
x = pu -> digit;       //相当于x = fit.digit;
struct owner{
	char socsecurity[12];
	...
};
struct leasecompany{
	char name[40];
	char headquarters[40];
	...
};
union data{
		struct owner owncar;
		struct leasecompany leasecar;
};	
struct car_data{
	char make[15];
	int status;   
	union data ownerinfo;
	...
};

匿名联合(c11)

匿名联合与匿名结构工作原理相同

struct owner{
	char socsecurity[12];
	...
};
struct leasecompany{
	char name[40];
	char headquarters[40];
	...
};
struct car_data{
	char make[15];
	int status;
	union{
		struct owner owncar;
		struct leasecompany leasecar;
	};
	...
};

如果flits是car_data型结构变量, 可以用flits.owncar.socsecurity代替flits.ownerinfo.owncar.socsecurity。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值