【Contact】结构体+动态内存管理+文件存储实现简易通讯录代码


静态版本

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

void menu()
{
    
    
	printf("************************************\n");
	printf("*****   1. add     2. del      *****\n");
	printf("*****   3. search  4. modify   *****\n");
	printf("*****   5. show    6. sort     *****\n");
	printf("*****   0. exit                *****\n");
	printf("************************************\n");
}

enum Option
{
    
    
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
};

int main()
{
    
    
	int input = 0;

	// 创建一个通讯录
	struct Contact con;

	// 初始化通讯录
	InitContact(&con);

	do
	{
    
    
		menu();
		printf("请选择:>\n");
		scanf("%d", &input);

		switch (input)
		{
    
    
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case EXIT:
			printf("退出程序\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);

	return 0;
}

contact.h

#pragma once


#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#define NAME_MAX 30
#define SEX_MAX 15
#define TELE_MAX 15
#define ADDR_MAX 30

#define MAX 1000


struct PeoInfo
{
    
    
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
};


// 通讯录
struct Contact
{
    
    
	struct PeoInfo data[MAX]; // 存放1000个人的数据在data数组中
	int sz; // 记录当前通讯录有效信息的个数
};


// 初始化通讯录
void InitContact(struct Contact* pc);

// 增加联系人
void AddContact(struct Contact* pc);

// 显示所有联系人
void ShowContact(struct Contact* pc);

// 删除指定联系人
void DelContact(struct Contact* pc);

// 查找指定联系人
void SearchContact(const struct Contact* pc);

// 修改指定联系人
void ModifyContact(struct Contact* pc);

contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"


// 初始化通讯录
void InitContact(struct Contact* pc)
{
    
    
	pc->sz = 0; // 默认没有信息

	memset(pc->data, 0, MAX * sizeof(struct PeoInfo));
	// memset(pc->date, 0, sizeof(pc->data)); 
	// 通过结构体指针找到数组data 数组名data单独放在sizeof内部,计算的是数组总大小
}


// 增加联系人
void AddContact(struct Contact* pc)
{
    
    
	if (pc->sz == MAX)
	{
    
    
		printf("通讯录满了\n");
	}
	else
	{
    
    
		printf("请输入名字:>");
		scanf("%s", pc->data[pc->sz].name);
		printf("请输入年龄:>");
		scanf("%d", &(pc->data[pc->sz].age));
		printf("请输入性别:>");
		scanf("%s", pc->data[pc->sz].sex);
		printf("请输入电话:>");
		scanf("%s", pc->data[pc->sz].tele);
		printf("请输入地址:>");
		scanf("%s", pc->data[pc->sz].addr);

		pc->sz++;
		printf("添加成功\n");
	}
}


// 显示所有联系人
void ShowContact(struct Contact* pc)
{
    
    
	int i = 0;
	printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
		"name", "age", "sex", "tele", "addr");
	for (i = 0; i < pc->sz; i++)
	{
    
    
		//打印每一个数据
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}


// 删除指定联系人
FindContactByName(const struct Contact* pc, const char* name)
{
    
    
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
    
    
		if (strcmp(pc->data[i].name, name) == 0)
		{
    
    
			return i;
		}
	}
	// 找不到
	return -1;
}

void DelContact(struct Contact* pc)
{
    
    
	if (pc->sz == 0)
	{
    
    
		printf("通讯录为空,无法删除\n");
		return;
	}

	char name[NAME_MAX] = {
    
     0 };

	printf("请输入要删除人的名字:>");
	scanf("%s", name);

	// 查找
	int pos = FindContactByName(pc, name);
	if (pos == -1)
	{
    
    
		printf("指定的联系人不存在\n");
	}
	else
	{
    
    
		// 删除
		int j = 0;
		for (j = pos; j < pc->sz - 1; j++)
		{
    
    
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		printf("删除成功!\n");
	}
}


// 查找指定联系人
void SearchContact(const struct Contact* pc)
{
    
    
	char name[NAME_MAX] = {
    
     0 };

	printf("输入要查找人的名字:>");
	scanf("%s", name);

	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
    
    
		printf("查无此人\n");
	}
	else
	{
    
    
		printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n",
			"name", "age", "sex", "tele", "addr");
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
	}
}


// 修改指定联系人
void ModifyContact(struct Contact* pc)
{
    
    
	char name[NAME_MAX] = {
    
     0 };

	printf("输入要修改人的名字:>");
	scanf("%s", name);

	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
    
    
		printf("要修改的人的信息不存在\n");
	}
	else
	{
    
    
		printf("请输入新的名字:>");
		scanf("%s", pc->data[pos].name);
		printf("请输入新的年龄:>");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入新的性别:>");
		scanf("%s", pc->data[pos].sex);
		printf("请输入新的电话:>");
		scanf("%s", pc->data[pos].tele);
		printf("请输入新的地址:>");
		scanf("%s", pc->data[pos].addr);

		printf("修改成功\n");
	}
}


动态版本

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

void menu()
{
    
    
	printf("************************************\n");
	printf("*****   1. add     2. del      *****\n");
	printf("*****   3. search  4. modify   *****\n");
	printf("*****   5. show    6. sort     *****\n");
	printf("*****   0. exit                *****\n");
	printf("************************************\n");
}

enum Option
{
    
    
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
};

int main()
{
    
    
	int input = 0;

	// 创建一个通讯录
	struct Contact con;

	// 初始化通讯录
	InitContact(&con);

	do
	{
    
    
		menu();
		printf("请选择:>\n");
		scanf("%d", &input);

		switch (input)
		{
    
    
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case EXIT:
			// 销毁通讯录
			DestroyContact(&con);
			printf("退出程序\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);

	return 0;
}

contact.h

#pragma once


#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#define NAME_MAX 30
#define SEX_MAX 15
#define TELE_MAX 15
#define ADDR_MAX 30

#define MAX 1000

#define DEFAULT_SZ 3


struct PeoInfo
{
    
    
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
};


// 通讯录
// 动态增长版本
struct Contact
{
    
    
	struct PeoInfo* data;
	int sz; // 通讯录中当前有效信息的个数
	int capacity; // 通讯录当前的最大容量
};


// 初始化通讯录
void InitContact(struct Contact* pc);

// 增加联系人
void AddContact(struct Contact* pc);

// 显示所有联系人
void ShowContact(struct Contact* pc);

// 删除指定联系人
void DelContact(struct Contact* pc);

// 查找指定联系人
void SearchContact(const struct Contact* pc);

// 修改指定联系人
void ModifyContact(struct Contact* pc);

// 销毁通讯录
void DestroyContact(struct Contact* pc);

contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

// 初始化通讯录
// 动态版本
void InitContact(struct Contact* pc)
{
    
    
	pc->sz = 0;
	pc->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
	pc->capacity = DEFAULT_SZ;
}


// 增加联系人
// 动态版本
void AddContact(struct Contact* pc)
{
    
    
	if (pc->sz == pc->capacity)
	{
    
    
		// 增加容量
		struct PeoInfo* ptr = realloc(
			pc->data, (pc->capacity + 2) * (sizeof(struct PeoInfo)));
		if (ptr != NULL)
		{
    
    
			pc->data = ptr;
			pc->capacity += 2;

			printf("增容成功\n");
		}
		else
		{
    
    
			return;
		}
	}
	// 录入新增信息
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);

	printf("添加成功\n");

	pc->sz++;
}


// 显示所有联系人
void ShowContact(struct Contact* pc)
{
    
    
	int i = 0;
	printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
		"name", "age", "sex", "tele", "addr");
	for (i = 0; i < pc->sz; i++)
	{
    
    
		//打印每一个数据
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}


// 删除指定联系人
FindContactByName(const struct Contact* pc, const char* name)
{
    
    
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
    
    
		if (strcmp(pc->data[i].name, name) == 0)
		{
    
    
			return i;
		}
	}
	// 找不到
	return -1;
}

void DelContact(struct Contact* pc)
{
    
    
	if (pc->sz == 0)
	{
    
    
		printf("通讯录为空,无法删除\n");
		return;
	}

	char name[NAME_MAX] = {
    
     0 };

	printf("请输入要删除人的名字:>");
	scanf("%s", name);

	// 查找
	int pos = FindContactByName(pc, name);
	if (pos == -1)
	{
    
    
		printf("指定的联系人不存在\n");
	}
	else
	{
    
    
		// 删除
		int j = 0;
		for (j = pos; j < pc->sz - 1; j++)
		{
    
    
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		printf("删除成功!\n");
	}
}


// 查找指定联系人
void SearchContact(const struct Contact* pc)
{
    
    
	char name[NAME_MAX] = {
    
     0 };

	printf("输入要查找人的名字:>");
	scanf("%s", name);

	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
    
    
		printf("查无此人\n");
	}
	else
	{
    
    
		printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n",
			"name", "age", "sex", "tele", "addr");
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
	}
}


// 修改指定联系人
void ModifyContact(struct Contact* pc)
{
    
    
	char name[NAME_MAX] = {
    
     0 };

	printf("输入要修改人的名字:>");
	scanf("%s", name);

	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
    
    
		printf("要修改的人的信息不存在\n");
	}
	else
	{
    
    
		printf("请输入新的名字:>");
		scanf("%s", pc->data[pos].name);
		printf("请输入新的年龄:>");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入新的性别:>");
		scanf("%s", pc->data[pos].sex);
		printf("请输入新的电话:>");
		scanf("%s", pc->data[pos].tele);
		printf("请输入新的地址:>");
		scanf("%s", pc->data[pos].addr);

		printf("修改成功\n");
	}
}


// 销毁通讯录
void DestroyContact(struct Contact* pc)
{
    
    
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}


文件的版本

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

void menu()
{
    
    
	printf("************************************\n");
	printf("*****   1. add     2. del      *****\n");
	printf("*****   3. search  4. modify   *****\n");
	printf("*****   5. show    6. sort     *****\n");
	printf("*****   0. exit                *****\n");
	printf("************************************\n");
}

enum Option
{
    
    
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
};

int main()
{
    
    
	int input = 0;

	// 创建一个通讯录
	struct Contact con;

	// 初始化通讯录
	InitContact(&con);

	do
	{
    
    
		menu();
		printf("请选择:>\n");
		scanf("%d", &input);

		switch (input)
		{
    
    
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case EXIT:
			// 保存信息
			SaveContact(&con);
			// 销毁通讯录
			DestroyContact(&con);
			printf("退出程序\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);

	return 0;
}

// 文件的版本:
// 1. 退出通讯录的时候,保存信息到文件中
// 2. 运行通讯录的时候,加载文件中的信息到通讯录中


contact.h

#pragma once


#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#define NAME_MAX 30
#define SEX_MAX 15
#define TELE_MAX 15
#define ADDR_MAX 30

#define MAX 1000

#define DEFAULT_SZ 3


struct PeoInfo
{
    
    
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
};


// 通讯录
// 1. 静态版本
//struct Contact
//{
    
    
//	struct PeoInfo data[MAX]; // 存放1000个人的数据在data数组中
//	int sz; // 记录当前通讯录有效信息的个数
//};

// 动态增长版本
struct Contact
{
    
    
	struct PeoInfo* data;
	int sz; // 通讯录中当前有效信息的个数
	int capacity; // 通讯录当前的最大容量
};


// 初始化通讯录
void InitContact(struct Contact* pc);

// 增加联系人
void AddContact(struct Contact* pc);

// 显示所有联系人
void ShowContact(struct Contact* pc);

// 删除指定联系人
void DelContact(struct Contact* pc);

// 查找指定联系人
void SearchContact(const struct Contact* pc);

// 修改指定联系人
void ModifyContact(struct Contact* pc);

// 销毁通讯录
void DestroyContact(struct Contact* pc);


// 保存信息到通讯录中
void SaveContact(struct Contact* pc);

// 加载文件中的信息到通讯录中
void LoadContact(struct Contact* pc);


contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"


// 初始化通讯录
// 1. 静态版本
//void InitContact(struct Contact* pc)
//{
    
    
//	pc->sz = 0; // 默认没有信息
//
//	memset(pc->data, 0, MAX * sizeof(struct PeoInfo));
//	// memset(pc->date, 0, sizeof(pc->data)); 
//	// 通过结构体指针找到数组data 数组名data单独放在sizeof内部,计算的是数组总大小
//}


void CheckCapacity(struct Contact* pc)
{
    
    
	if (pc->sz == pc->capacity)
	{
    
    
		// 增加容量
		struct PeoInfo* ptr = realloc(
			pc->data, (pc->capacity + 2) * (sizeof(struct PeoInfo)));
		if (ptr != NULL)
		{
    
    
			pc->data = ptr;
			pc->capacity += 2;

			printf("增容成功\n");
		}
		else
		{
    
    
			perror("通讯录增容失败");
			exit(1); // 0-程序正常结束  1-异常结束
		}
	}
}

void LoadContact(struct Contact* pc)
{
    
    
	// 打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (NULL == pf)
	{
    
    
		perror("LoadContact:fopen");
		return;
	}

	// 读文件
	struct PeoInfo tmp = {
    
     0 };
	while (fread(&tmp, sizeof(struct PeoInfo), 1, pf))
	{
    
    
		// 空间如果不够,增容
		CheckCapacity(pc);

		pc->data[pc->sz] = tmp;
		pc->sz++;
	}

	// 关闭文件
	fclose(pf);
	pf = NULL;
}

//2. 动态版本
void InitContact(struct Contact* pc)
{
    
    
	pc->sz = 0;
	pc->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
	pc->capacity = DEFAULT_SZ;

	// 加载文件信息到通讯录中
	LoadContact(pc);
}


// 增加联系人
// 1. 静态版本
//void AddContact(struct Contact* pc)
//{
    
    
//	if (pc->sz == MAX)
//	{
    
    
//		printf("通讯录满了\n");
//	}
//	else
//	{
    
    
//		printf("请输入名字:>");
//		scanf("%s", pc->data[pc->sz].name);
//		printf("请输入年龄:>");
//		scanf("%d", &(pc->data[pc->sz].age));
//		printf("请输入性别:>");
//		scanf("%s", pc->data[pc->sz].sex);
//		printf("请输入电话:>");
//		scanf("%s", pc->data[pc->sz].tele);
//		printf("请输入地址:>");
//		scanf("%s", pc->data[pc->sz].addr);
//
//		pc->sz++;
//		printf("添加成功\n");
//	}
//}

// 2. 动态版本
void AddContact(struct Contact* pc)
{
    
    
	CheckCapacity(pc);

	// 录入新增信息
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);

	printf("添加成功\n");

	pc->sz++;
}


// 显示所有联系人
void ShowContact(struct Contact* pc)
{
    
    
	int i = 0;
	printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
		"name", "age", "sex", "tele", "addr");
	for (i = 0; i < pc->sz; i++)
	{
    
    
		//打印每一个数据
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}


// 删除指定联系人
FindContactByName(const struct Contact* pc, const char* name)
{
    
    
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
    
    
		if (strcmp(pc->data[i].name, name) == 0)
		{
    
    
			return i;
		}
	}
	// 找不到
	return -1;
}

void DelContact(struct Contact* pc)
{
    
    
	if (pc->sz == 0)
	{
    
    
		printf("通讯录为空,无法删除\n");
		return;
	}

	char name[NAME_MAX] = {
    
     0 };

	printf("请输入要删除人的名字:>");
	scanf("%s", name);

	// 查找
	int pos = FindContactByName(pc, name);
	if (pos == -1)
	{
    
    
		printf("指定的联系人不存在\n");
	}
	else
	{
    
    
		// 删除
		int j = 0;
		for (j = pos; j < pc->sz - 1; j++)
		{
    
    
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		printf("删除成功!\n");
	}
}


// 查找指定联系人
void SearchContact(const struct Contact* pc)
{
    
    
	char name[NAME_MAX] = {
    
     0 };

	printf("输入要查找人的名字:>");
	scanf("%s", name);

	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
    
    
		printf("查无此人\n");
	}
	else
	{
    
    
		printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n",
			"name", "age", "sex", "tele", "addr");
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
	}
}


// 修改指定联系人
void ModifyContact(struct Contact* pc)
{
    
    
	char name[NAME_MAX] = {
    
     0 };

	printf("输入要修改人的名字:>");
	scanf("%s", name);

	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
    
    
		printf("要修改的人的信息不存在\n");
	}
	else
	{
    
    
		printf("请输入新的名字:>");
		scanf("%s", pc->data[pos].name);
		printf("请输入新的年龄:>");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入新的性别:>");
		scanf("%s", pc->data[pos].sex);
		printf("请输入新的电话:>");
		scanf("%s", pc->data[pos].tele);
		printf("请输入新的地址:>");
		scanf("%s", pc->data[pos].addr);

		printf("修改成功\n");
	}
}


// 销毁通讯录
void DestroyContact(struct Contact* pc)
{
    
    
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}


// 保存信息到通讯录中
void SaveContact(struct Contact* pc)
{
    
    
	// 打开文件
	FILE* pf = fopen("contact.txt", "wb");
	if (NULL == pf)
	{
    
    
		perror("SaveContact:fopen");
		return;
	}

	// 写数据
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
    
    
		fwrite(&(pc->data[i]), sizeof(struct PeoInfo), 1, pf);
		// fwrite(pc->data+i, sizeof(struct PeoInfo), 1, pf);
	}

	// 关闭文件
	fclose(pf);
	pf = NULL;
}



练习

计算位段大小

有如下宏定义和结构定义,当A = 2, B = 3时,pointer分配( )个字节的空间。

#include <stdio.h>
#include <stdlib.h>

#define A 2
#define B 3
#define MAX_SIZE A+B

struct _Record_Struct
{
    
    
	// 1byte - 8bit
	unsigned char Env_Alarm_ID : 4;
	unsigned char Para1 : 2;
	// 1byte
	unsigned char state;
	// 2byte
	unsigned char avail : 1;
}*Env_Alarm_Record;

int main()
{
    
    

	struct _Record_Struct* pointer = (struct _Record_Struct*)malloc(sizeof(struct _Record_Struct) * MAX_SIZE);
	
	int sz = sizeof(struct _Record_Struct) * MAX_SIZE;
	                                  // 3 * 2 + 3 = 9
	return 0;
}

下面代码的结果是( )

#include <stdio.h>
#include <string.h>

int main()
{
    
    
    unsigned char puc[4];

    struct tagPIM
    {
    
    
        unsigned char ucPim1;
        unsigned char ucData0 : 1;
        unsigned char ucData1 : 2;
        unsigned char ucData2 : 3;
    }*pstPimData;

    pstPimData = (struct tagPIM*)puc;
    memset(puc, 0, 4);

    pstPimData->ucPim1 = 2;
    pstPimData->ucData0 = 3;
    pstPimData->ucData1 = 4;
    pstPimData->ucData2 = 5;

    printf("%02x %02x %02x %02x\n", puc[0], puc[1], puc[2], puc[3]);
    // 02 29 00 00
    return 0;
}

在这里插入图片描述


计算以下联合体大小

#include <stdio.h>

union Un
{
    
    
	short s[7]; // 7*2=14
	// 2 8 2
	int n;
	// 4 4 4
	// 14不是4的倍数 -> 16
};

int main()
{
    
    
	printf("%d\n", sizeof(union Un));

	return 0;
}

在X86下,有下列程序

#include<stdio.h>

int main()
{
    
    
    union
    {
    
    
        short k;
        char i[2];
    }*s, a;

    s = &a;
    s->i[0] = 0x39;
    s->i[1] = 0x38;

    printf("%x\n", a.k);

    return 0;
}

在这里插入图片描述


模拟实现atoi

#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <limits.h>

enum State
{
    
    
	VALID, // 正常
	INVALID, // 非法
};
enum State state = INVALID;

int my_atoi(const char* str)
{
    
    
	// str是NULL
	assert(str);

	// str指向的是空字符串
	if (*str == '\0') 
		return 0; // 返回的是0还是空字符串返回0

	// 跳过空白字符
	while (isspace(*str)) // 如果参数时空白字符,为真,返回非0数字,不是,返回0
	{
    
    
		str++;
	}

	// 识别正负数
	int flag = 1;
	if (*str == '+')
	{
    
    
		str++;
	}
	else if (*str == '-')
	{
    
    
		flag = -1;
		str++;
	}

	// 识别数字字符并转换
	long long ret = 0;
	while (*str)
	{
    
    
		if (isdigit(*str)) // 判断数字字符
		{
    
    
			ret = ret * 10 + flag * (*str - '0');
			if (ret > INT_MAX || ret < INT_MIN)
			{
    
    
				return 0; // 非法返回
			}
			str++;
		}
		else
		{
    
    
			state = VALID;
			return (int)ret; // 合法
		}
	}

	state = VALID;
	return (int)ret;
}

int main()
{
    
    
	int ret = my_atoi("    -1234abc");
	// my_atoi("    1234"); // 前面有空白字符
	// my_atoi("    +1234"); // 前面+-
	// my_atoi("    +1234abc"); // 非数字字符
	// my_atoi("    123123123123123"); // 给的数字太大了,溢出了

	if (state == VALID)
	{
    
    
		printf("合法返回,值为:%d\n", ret);
	}
	else
	{
    
    
		printf("非法返回,值为:%d\n", ret);
	}

	return 0;
}

找单身狗

一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字

#include <stdio.h>

void FindNum(int* arr, int sz)
{
    
    
	int i = 0;
	for (i = 0; i < sz; i++)
	{
    
    
		int flag = 1;
		int j = 0;
		for (j = 0; j < sz; j++)
		{
    
    
			if (i == j)
			{
    
    
				continue;
			}
			if (arr[i] == arr[j])
			{
    
    
				flag = 0;
				break;
			}
		}
		if (flag == 1)
		{
    
    
			printf("%d ", arr[i]);
		}
	}
}

int main()
{
    
    
	int arr[] = {
    
     1,1,2,2,3,4,4,5,6,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);

	FindNum(arr, sz);

	return 0;
}
#include <stdio.h>

int main()
{
    
    
	int arr[] = {
    
     1,2,3,4,5,1,2,3,4,6 };

	// 1. 把所有数字异或在一起,就是5^6
	int sz = sizeof(arr) / sizeof(arr[0]);
	int ret = 0;
	int i = 0;
	for (i = 0; i < sz; i++)
	{
    
    
		ret = ret ^ arr[i];
	}
	
	// 2. 计算ret的二进制的第几位为1
	int pos = 0;
	for (i = 0; i < 32; i++)
	{
    
    
		if (((ret >> i) & 1) == 1)
		{
    
    
			pos = i;
			break;
		}
	}

	// 3. 按照不相同的位分组
	int m = 0;
	int n = 0;
	for (i = 0; i < sz; i++)
	{
    
    
		if (((arr[i] >> pos) & 1) == 1) // arr[i]的第pos位&1如果是1
		{
    
    
			m ^= arr[i]; // 1 1 3 3 5
		}
		else
		{
    
    
			n ^= arr[i]; // 2 2 4 4 6
		}
	}
	// 分组:
	// 101   5 1 1 3 3
	// 110   6 2 2 4 4

	printf("%d %d\n", m, n);

	return 0;
}

交换奇偶位

写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换

#include <stdio.h>

#define SWAP_BIT(n) (n=((n&0xaaaaaaaa)>>1)+((n&0x55555555)<<1))
// a - 1010

int main()
{
    
    
	int a = 10;
	// 00000000000000000000000000001010 - 10
	
	SWAP_BIT(a);
	printf("a = %d\n", a);
	
	return 0;
}

offsetof宏

写一个宏,计算结构体中某变量相对于首地址的偏移,并给出说明
考察:offsetof宏的实现

#include <stdio.h>
#include <stddef.h>

struct Stu
{
    
    
	int a; // 0-3
	char c; // 4
	double d; // 8-15 
};

#define OFFSETOF(struct_type, mem_name)  (int)&(((struct_type*)0)->mem_name) 
// 假设地址是0,把0强制类型转换成结构体指针,偏移量就相当于地址    取出成员的地址,偏移量是整数,强制类性转换

int main()
{
    
    
	// printf("%d\n", sizeof(struct Stu));
	//printf("%d\n", offsetof(struct Stu, a)); // 0
	//printf("%d\n", offsetof(struct Stu, c)); // 4
	//printf("%d\n", offsetof(struct Stu, d)); // 8

	printf("%d\n", OFFSETOF(struct Stu, a)); // 0
	printf("%d\n", OFFSETOF(struct Stu, c)); // 4
	printf("%d\n", OFFSETOF(struct Stu, d)); // 8

	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_56884023/article/details/120460332