アドレス帳実装【C言語】

目次

序文

1. 全体的な論理分析

2. 導入手順

1. メニュー作成や複数の操作に関する問題

2.アドレス帳を作成する

3.アドレス帳の初期化

4.連絡先を追加する

5.連絡先の表示

6. 指定した連絡先を削除する

7. 指定された連絡担当者を見つける

8.連絡先情報の変更

9. 連絡先情報の並べ替え

3. すべてのソースコード


序文

前回はカスタムタイプについて詳しく紹介しましたが、今回は学んだ知識を使って小さなプロジェクトを作って実践してみます。今回はC言語を使って静的バージョンのアドレス帳を実装してみます!動的メモリ管理やファイル操作については後ほど紹介しますが、このバージョンをベースに最適化・改善していきます!

1. 全体的な論理分析

以前にスリーピースチェスや掃海艇の小規模プロジェクトを実装したときと同様に、まずプロジェクト全体のロジックをできるだけ詳細に整理します。最後にそれがすべてバグだったことがわかったのは残念でした。後から問題が発生してもすぐに特定できるよう、最初にできるだけ明確に分析します。この号でも、以前の号と同様にマルチファイル プログラミングが使用されています。さて、この小さなプロジェクトの基本的な実装ロジックを整理しましょう。

1. メニュー作成や複数の操作に関する問題

2.アドレス帳を作成する

3. アドレス帳の初期化、追加、削除、確認、変更等の操作

2. 導入手順

1. メニュー作成や複数の操作に関する問題

アドレス帳を操作する際に、操作前にメニュー機能を持たせてほしいと思います!今後、アドレス帳を何度も操作(追加、削除、確認、修正など)することを考えて、すぐに do..while ループを使って処理することを思いつき、これを 2 つまたは 3 つ書きました。何度も前に書いたので、直接コーディングします。

#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");
}

void test()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择操作数:> ");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//add
			break;
		case 2:
			//del
			break;
		case 3:
			//search
			break;
		case 4:
			//modify
			break;
		case 5:
			//show
			break;
		case 6:
			//sort
			break;
		case 0:
			printf("退出成功!\n");
			break;
		default:
			printf("选择数非法!\n");
			break;
		}

	} while (input);
}

int main()
{
	test();
	return 0;
}

効果を確認してください:

2.アドレス帳を作成する

アドレス帳に対してさまざまな操作を実行する前に、まずアドレス帳を用意する必要があります。アドレス帳の本質は、名前、年齢、性別、電話番号、住所などの個人の属性を記述することです。これらはすべて異なるタイプであり、構造を使用して解決することを簡単に考えることができます。ただし、これは 1 人の人物を説明しているだけであり、アドレス帳には 1 人だけが存在することはできません。多くの人物が存在するはずです。これらの連絡先は同じタイプであるため、アドレス帳の作成には構造体配列が使用されます。

typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char tele[15];
	char addr[20];
}PeoInfo;

これは人の基本的な属性を表す構造です。この構造体を作成した後、ファイル test.c の do..while ループでアドレス帳として構造体配列を作成できます。

しかし、この書き方には問題があります。連絡先を保存または削除したときに、その時点でアドレス帳に登録されている連絡先であるかどうかを確認するために印刷したい場合、どのくらい印刷すればよいでしょうか。私たちはまだ疑問に思っています。したがって、ここではアドレス帳のサイズを記録するために別の変数 sz を定義する必要があります。

実際、sz はアドレス帳のサイズを記録できるだけでなく、連絡先を追加するときにも、それを sz の位置まで増やし、sz++ を追加し、sz-- を削除するだけで済むことがわかりました。 sz とアドレス帳は実際にバインドされています。同時に、アドレス帳を構造体にカプセル化することもできます。1 つのメンバーは PeoInfo 構造体配列で、もう 1 つはアドレス帳のサイズを記録する sz です。

typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char tele[15];
	char addr[20];
}PeoInfo;


typedef struct Contact
{
	PeoInfo data[100];
	int sz;
}Contact;

次に、test.c ファイル内に作成します。

わかりました!このアドレス帳が作成され、記録されます。実際、ここではまだ少し最適化を行うことができます: 両方の構造体に多くの定数があることがわかりました。後でニーズが変わった場合は、これらを変更する必要があります。したがって、後の修正の便宜を図るために、これらを #define 定数に変更し、後で修正しやすくしました。前回の号で列挙型が導入されたと言うかもしれませんが、ここでは複数の定数列挙型を使用した方がよいのではないでしょうか? ここでの列挙は確かに目的を達成できますが、列挙は開始する前にすべての可能性を列挙することであり、私たちの場合はそうではありません。したがって、ここで列挙する必要はありません。

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 15
#define ADDR_MAX 20
#define MAX 100

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


typedef struct Contact
{
	PeoInfo data[MAX];
	int sz;
}Contact;

これが現在のロジックで最適なコードです。

3.アドレス帳の初期化

アドレス帳を作成したら、まず初期化します。構造体配列の各要素を 0 に初期化し、アドレス帳のサイズを 0 に設定します。構造体の内容を変更したいので、アドレスを渡す必要があります。ここで使用しているのは、memset 関数を直接 0 に初期化することも、ループを使用して初期化することもできるということです。memset がわからない場合は、 memsetをクリックしてください

void InitContact(Contact* pc)
{
	assert(pc);

	memset(pc->data, 0, sizeof(pc->data));
	pc->sz = 0;
}

4.連絡先を追加する

前にも言ったように、必要なのは sz の位置を増やすだけです。ただし、アドレス帳がいっぱいになった場合の状況を考えてください。

void AddContact(Contact* pc) 
{
	assert(pc);
	//通讯录已满
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法添加!\n");
		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);
	pc->sz++;

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

OK、まず表示連絡先を書き込んで、正常に追加されたかどうかを確認しましょう。

5.連絡先の表示

連絡先を表示するとは、アドレス帳の連絡先をコンソールに印刷することを意味します。

void ShowContact(Contact* pc)
{
	assert(pc);

	printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr
		);
	}
}

OK、追加が成功し、連絡先が表示されるかどうかを確認してみましょう。

OK、連絡先の追加と連絡先の表示は成功しました。上記のロジックに問題がないことがわかります。

6. 指定した連絡先を削除する

削除したい人の名前を入力し、検索して削除します。そうでない場合、出力にはそのような連絡先はありません。アドレス帳が空の場合も考慮してください。ここで検索について説明しますが、この検索はアドレス帳の検索とは少し異なり、検索後に下付き文字を返すだけの検索と、連絡先情報を出力する機能が異なります。したがって、関数だけをカプセル化しています。

//查找要删除的人并返回下标
int FindContact(const Contact* pc, const char* name)
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;//找到了
		}
	}

	return -1;//没找到
}

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

	char name[NAME_MAX] = { 0 };
	printf("请输入要删除人的姓名:> ");
	scanf("%s", name);

	int pos = FindContact(pc, name);

	if (pos != -1)
	{
		//删除
		for (int i = pos; i < pc->sz - 1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}

		pc->sz--;
		printf("成功删除联系人!\n");
	}
	else
	{
		printf("没有此联系人!\n");
	}
}

ここで注意したいのは、文字列の比較にはstrcmpを使う必要があり、==は使えないということですが、これについては文字列関数とメモリ関数の回で詳しく紹介しました!削除するときは添え字の範囲外の問題にも注意してください。

効果を確認してください:

 7. 指定された連絡担当者を見つける

指定された連絡先を見つけるには、まず指定されたメソッドで検索する必要があります。見つかった場合は印刷します。そうでない場合は、出力にこの連絡先は含まれません。ここに連絡先を表示するこのページは、後で連絡先を変更するためにも使用される可能性があるため、便宜上、連絡先を関数にカプセル化し、直接呼び出します。


//显示单个联系人信息
void Print(const Contact* pc, int pos)
{
	assert(pc);

	printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");

	printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",
		pc->data[pos].name,
		pc->data[pos].age,
		pc->data[pos].sex,
		pc->data[pos].tele,
		pc->data[pos].addr);

}

//查找指定联系人
void Search(const Contact* pc)
{
	assert(pc);

	char name[NAME_MAX] = { 0 };
	printf("请输入要查找联系人姓名:> ");
	scanf("%s", name);

	int pos = -1;//初始化为-1表示没有此联系人
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			pos = i;//找到了
			break;
		}
	}

	if (pos != -1)
	{
		Print(pc, pos);
	}
	else
	{
		printf("没有此联系人!\n");
	}
}

FindContact は上記で実装されているので、それを使用できます。

void Search(const Contact* pc)
{
	assert(pc);

	char name[NAME_MAX] = { 0 };
	printf("请输入要查找联系人姓名:> ");
	scanf("%s", name);

	int pos = FindContact(pc, name);

	if (pos != -1)
	{
		Print(pc, pos);
	}
	else
	{
		printf("没有此联系人!\n");
	}
}

効果を確認してください:

8.連絡先情報の変更

連絡先情報の変更にはさまざまな可能性があり、たとえば、名前や性別などの 1 つの項目のみを変更する場合もあれば、名前や年齢などの複数の項目を変更する場合もあり、これらすべてを変更する必要がある場合もあります。何かを変更したい場合でも、選択できるメニューがあることが期待できます。また、項目を変更した後も、さらに変更を続けたい場合があります。これを踏まえて、test.c ファイルに do...while ループ + メニューを採用します。

//修改联系人信息菜单
void menu1()
{
    system("cls");
	printf("*****************************************\n");
	printf("********* 1. name     2. age   **********\n");
	printf("********* 3. sex      4. tele  **********\n");
	printf("********* 5. addr     6. all   **********\n");
	printf("********* 0. exit              **********\n");
	printf("*****************************************\n");
}

//修改名字
void ModName(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人姓名:> ");
	scanf("%s", pc->data[ret].name);
	printf("修改成功!\n");
}

//修改年龄
void ModAge(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人年龄:> ");
	scanf("%d", &pc->data[ret].age);
	printf("修改成功!\n");
}

//修改性别
void ModSex(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人性别:> ");
	scanf("%s", &pc->data[ret].sex);
	printf("修改成功!\n");
}

//修改电话
void ModTele(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人电话:> ");
	scanf("%s", &pc->data[ret].tele);
	printf("修改成功!\n");
}

//修改住址
void ModAddr(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人住址:> ");
	scanf("%s", &pc->data[ret].addr);
	printf("修改成功!\n");
}


void ModAll(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入联系人姓名:> ");
	scanf("%s", pc->data[ret].name);
	printf("请输入联系人年龄:> ");
	scanf("%d", &pc->data[ret].age);
	printf("请输入联系人性别:> ");
	scanf("%s", pc->data[ret].sex);
	printf("请输入联系人电话:> ");
	scanf("%s", pc->data[ret].tele);
	printf("请输入联系人住址:> ");
	scanf("%s", pc->data[ret].addr);
	
	printf("修改成功!\n");
}


//修改联系人
void ModContact(Contact* pc)
{
	assert(pc);
	//判断是否为空
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法修改!\n");
		return;
	}

	char name[NAME_MAX] = { 0 };
	printf("请输入要修改系人姓名:> ");
	scanf("%s", name);
	//判断是否有该联系人
	int ret = FindContact(pc, name);
	
	//有该联系人
	if (ret != -1)
	{
		int n = 0;
		do
		{
			menu1();
			printf("请选择修改内容:> ");
			scanf("%d", &n);
			//修改
			switch (n)
			{
			case 1:
				ModName(pc,ret);
				break;
			case 2:
				ModAge(pc, ret);
				break;
			case 3:
				ModSex(pc, ret);
				break;
			case 4:
				ModTele(pc, ret);
				break;
			case 5:
				ModAddr(pc, ret);
				break;
			case 6:
				ModAll(pc, ret);
				break;
			case 0:
				printf("修改结束!\n");
				break;
			default:
				printf("选择数非法!\n");
				break;
			}

		} while (n);
	}
	else
	{
		printf("没有此联系人!\n");
	}
}

効果を見てください: (エディターは画面をクリアしました)

修正する前に:

 変更後:

よし、大成功だ!もう一度整理してみましょう!

9. 連絡先情報の並べ替え

上記のアドレス帳の追加、削除、確認、変更という基本的な機能はすでに実装されています。名前順や年齢順など、別のソート機能もつけてほしいです!ポインタの前進セクションでコールバック関数を紹介しましたが、ここでは qsort を使用してアドレス帳を並べ替えます。上記のように最初にメニュー選択がまだあると予想します。


//排序菜单
void menu2()
{
	system("cls");
	printf("**********************************\n");
	printf("***** 1. name    2. age **********\n");
	printf("**********************************\n");
}

//名字比较函数
int cmp_name(const void* str1, const void* str2)
{
	//return strcmp(((PeoInfo*)str1)->name, ((PeoInfo*)str2)->name);
	return strcmp((((Contact*)str1)->data)->name, (((Contact*)str2)->data)->name);
}

//名字排序
void SortName(Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
}

//年龄比较函数
int cmp_age(const void* str1, const void* str2)
{

	//return ((PeoInfo*)str1)->age - ((PeoInfo*)str2)->age;
	return (((Contact*)str1)->data)->age - (((Contact*)str2)->data)->age;
}
//年龄排序
void SortAge(Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_age);
}

//排序联系人信息
void SortContact(Contact* pc)
{
	assert(pc);
	//判断为空
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法排序!\n");
		Sleep(3000);
		system("cls");
		return;
	}


	menu2();
	int n = 0;
	printf("请选择排序方式:> ");
	scanf("%d", &n);
	//排序
	switch (n)
	{
	case 1:
		SortName(pc);
		system("cls");
		printf("排序成功!\n");
		break;
	case 2:
		SortAge(pc);
		system("cls");
		printf("排序成功!\n");
		break;
	default:
		printf("选择数非法!\n");
		Sleep(3000);
		system("cls");
		break;
	}
}

効果を確認してください:

並べ替え前 (年齢):

 並べ替え後 (年齢):

並べ替え前 (名前):

 並べ替え後 (名前):

OK、ソートが実装されました!

3. すべてのソースコード

 contact.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<windows.h>

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 15
#define ADDR_MAX 20
#define MAX 100

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


typedef struct Contact
{
	PeoInfo data[MAX];
	int sz;
}Contact;


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

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

//显示联系人
void ShowContact(const Contact* pc);

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

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

//修改联系人
void ModContact(Contact* pc);

//排序联系人信息
void SortContact(Contact* pc);


contact.c

#include"contact.h"

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

	memset(pc->data, 0, sizeof(pc->data));
	pc->sz = 0;
}

//增加联系人
void AddContact(Contact* pc) 
{
	assert(pc);
	//通讯录已满
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法添加!\n");
		Sleep(2000);
		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);
	pc->sz++;

	printf("添加成功!\n");
	Sleep(1000);
}

//显示联系人
void ShowContact(const Contact* pc)
{
	assert(pc);

	printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr
		);
	}
}


//查找要删除的人并返回下标
int FindContact(const Contact* pc, const char* name)
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;//找到了
		}
	}

	return -1;//没找到
}

//删除联系人
void DelContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除!\n");
		Sleep(2000);
		return;
	}

	char name[NAME_MAX] = { 0 };
	printf("请输入要删除人的姓名:> ");
	scanf("%s", name);

	int pos = FindContact(pc, name);

	if (pos != -1)
	{
		//删除
		for (int i = pos; i < pc->sz - 1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}

		pc->sz--;
		printf("成功删除联系人!\n");
		Sleep(1000);
	}
	else
	{
		printf("没有此联系人!\n");
		Sleep(2000);
	}
}



//显示单个联系人信息
void Print(const Contact* pc, int pos)
{
	assert(pc);

	printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");

	printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",
		pc->data[pos].name,
		pc->data[pos].age,
		pc->data[pos].sex,
		pc->data[pos].tele,
		pc->data[pos].addr);

}

//查找指定联系人
void Search(const Contact* pc)
{
	assert(pc);

	char name[NAME_MAX] = { 0 };
	printf("请输入要查找联系人姓名:> ");
	scanf("%s", name);

	int pos = FindContact(pc, name);
	if (pos != -1)
	{
		Print(pc, pos);
	}
	else
	{
		printf("没有此联系人!\n");
		Sleep(2000);
		system("cls");
	}
}


//修改联系人信息菜单
void menu1()
{
	system("cls");
	printf("*****************************************\n");
	printf("********* 1. name     2. age   **********\n");
	printf("********* 3. sex      4. tele  **********\n");
	printf("********* 5. addr     6. all   **********\n");
	printf("********* 0. exit              **********\n");
	printf("*****************************************\n");
}

//修改名字
void ModName(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人姓名:> ");
	scanf("%s", pc->data[ret].name);
}

//修改年龄
void ModAge(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人年龄:> ");
	scanf("%d", &pc->data[ret].age);
}

//修改性别
void ModSex(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人性别:> ");
	scanf("%s", &pc->data[ret].sex);
}

//修改电话
void ModTele(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人电话:> ");
	scanf("%s", &pc->data[ret].tele);
}

//修改住址
void ModAddr(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入修改后联系人住址:> ");
	scanf("%s", &pc->data[ret].addr);
}


void ModAll(Contact* pc, int ret)
{
	assert(pc);

	printf("请输入联系人姓名:> ");
	scanf("%s", pc->data[ret].name);
	printf("请输入联系人年龄:> ");
	scanf("%d", &pc->data[ret].age);
	printf("请输入联系人性别:> ");
	scanf("%s", pc->data[ret].sex);
	printf("请输入联系人电话:> ");
	scanf("%s", pc->data[ret].tele);
	printf("请输入联系人住址:> ");
	scanf("%s", pc->data[ret].addr);
}


//修改联系人
void ModContact(Contact* pc)
{
	assert(pc);
	//判断是否为空
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法修改!\n");
		Sleep(2000);
		system("cls");
		return;
	}

	char name[NAME_MAX] = { 0 };
	printf("请输入要修改系人姓名:> ");
	scanf("%s", name);
	//判断是否有该联系人
	int ret = FindContact(pc, name);
	
	//有该联系人
	if (ret != -1)
	{
		int n = 0;
		do
		{
			menu1();
			Print(pc, ret);
			printf("请选择修改内容:> ");
			scanf("%d", &n);
			//修改
			switch (n)
			{
			case 1:
				ModName(pc,ret);
				break;
			case 2:
				ModAge(pc, ret);
				break;
			case 3:
				ModSex(pc, ret);
				break;
			case 4:
				ModTele(pc, ret);
				break;
			case 5:
				ModAddr(pc, ret);
				break;
			case 6:
				ModAll(pc, ret);
				break;
			case 0:
				printf("修改结束!\n");
				Sleep(2000);
				system("cls");
				break;
			default:
				printf("选择数非法!\n");
				Sleep(2000);
				system("cls");
				break;
			}

		} while (n);
	}
	else
	{
		printf("没有此联系人!\n");
		Sleep(2000);
		system("cls");
	}
}

//排序菜单
void menu2()
{
	system("cls");
	printf("**********************************\n");
	printf("***** 1. name    2. age **********\n");
	printf("**********************************\n");
}

//名字比较函数
int cmp_name(const void* str1, const void* str2)
{
	return strcmp(((PeoInfo*)str1)->name, ((PeoInfo*)str2)->name);
}

//名字排序
void SortName(Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
}

//年龄比较函数
int cmp_age(const void* str1, const void* str2)
{

	return ((PeoInfo*)str1)->age - ((PeoInfo*)str2)->age;
}
//年龄排序
void SortAge(Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_age);
}

//排序联系人信息
void SortContact(Contact* pc)
{
	assert(pc);
	//判断为空
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法排序!\n");
		Sleep(3000);
		system("cls");
		return;
	}


	menu2();
	int n = 0;
	printf("请选择排序方式:> ");
	scanf("%d", &n);
	//排序
	switch (n)
	{
	case 1:
		SortName(pc);
		system("cls");
		printf("排序成功!\n");
		break;
	case 2:
		SortAge(pc);
		system("cls");
		printf("排序成功!\n");
		break;
	default:
		printf("选择数非法!\n");
		Sleep(3000);
		system("cls");
		break;
	}
}

test.c

#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");
}

void test()
{
	int input = 0;
	Contact con;
	InitContact(&con);
	do
	{
		menu();
		printf("请选择操作数:> ");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			system("cls");
			break;
		case 2:
			DelContact(&con);
			system("cls"); 
			break;
		case 3:
			system("cls");
			Search(&con);
			break;
		case 4:
			ModContact(&con);
			break;
		case 5:
			system("cls");
			ShowContact(&con);
			break;
		case 6:
			SortContact(&con);
			break;
		case 0:
			printf("退出成功!\n");
			break;
		default:
			printf("选择数非法!\n");
			break;
		}

	} while (input);
}

int main()
{
	test();
	return 0;
}

OK、今回の共有はこれで終わりです。良い兄弟たち、また会いましょう!

おすすめ

転載: blog.csdn.net/m0_75256358/article/details/132369058