c++大作业——通讯录管理系统1.0

本文介绍一款基于C++的联系人管理程序,适合新手练习。编码环境为Visual Studio 2022。先进行需求分析,接着探讨用文件存储信息、程序主体编写及功能构造函数等问题,给出最终代码,还对fstream和locale进行总结,介绍其使用方法和相关函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        一款基于c++的可以满足基础的查看、添加、删除、修改、清空联系人的程序,适合新手练习。

 编码环境,visual studio 2022,c++空项目


需求分析:

        拿到问题后,首先进行需求分析,一款c++程序,可以存储一些联系人信息,并在需要的时候输出信息。

第一个问题,用什么存储信息?

        经过我搜集各类资料后,选择了我认为最简单的文件(.txt),也就是可以通过c++标准库函数fstream进行文件流的写入、读取、更改等操作。

第二个问题,程序主体应该怎么写?

        首先,头文件添加最基础的iostream和需要输出string类型的string和using namespace std;

#include<iostream>
#include<string>

using namespace std;

        其次,我们根据需求输出一个菜单与用户进行交互,接收到用户所选择的功能然后执行。那么switch选择语句在这里就最为使用。

#include<iostream>
#include<string>

using namespace std;

int main()
{
	cout << "菜单" << endl;
	int i;
	cin >> i;
	switch (i)
	{
	case 1:
		//查看
		break;
	case 2:
		//添加
		break;
	case 3:
		//删除
		break;
	case 4:
		//修改
		break;
	case 5:
		//清空
		break;
	case 0:
		//退出
		break;
	default:
		//输入数字错误
		break;
	}
	return 0;
}

        然后,我们如何让这个行为(输出菜单,接收用户需求,执行)不停的重复直到用户想要退出程序呢?循环语句while!在此时就很适合。我们将整个行为的代码放入while循环中,再设置用户选择退出的条件为循环结束条件就完成了我们的设想。

        再加入一些文字提示用户操作。

#include<iostream>
#include<string>

using namespace std;

int main()
{
	bool flag = true;//标志位
	while (flag)
	{
		cout << "菜单" << endl;
		int i;
		cin >> i;
		switch (i)
		{
		case 1:
			//查看
			break;
		case 2:
			//添加
			break;
		case 3:
			//删除
			break;
		case 4:
			//修改
			break;
		case 5:
			//清空
			break;
		case 0:
			//退出
			flag = false;//当用户选择0.即想要退出程序时,将标志位置0,循环结束
			cout << "欢迎下次使用!!!" << endl;
			break;
		default:
			//输入数字错误
			cout << "您的输入有误,请重新选择功能对应数字输入:" << endl;
			break;
		}
	}
	return 0;
}

        此时经过运行,发现程序已经可以正常运作,我们的初步目的已经达到。

第三个问题,功能的实现应该怎么构造函数?

        首先还是先来看看我们的需求:

  1.  打印菜单并接收用户输入反馈给switch
  2. 查看通讯录
  3. 添加联系人
  4. 删除联系人
  5. 修改联系人信息
  6. 清空通讯录

        其中,我们多次用到联系人,他应该包含姓名、性别、住址、电话号码等多种信息,所以构造一个struct结构体是很有用的。

        考虑到后续需要写入txt文件中并且并无特殊需求,那么其中信息都可以用string类型进行存储。

struct people
{
	string name;
	string gender;
	string address;
	string phoneNumber;
};

        然后在主函数前声明函数:

int show_menu();//显示菜单
void read_line();//查看通讯录
void add_people();//添加
void delete_people();//删除
void modify_people();//修改
void clear_people();//清空

        之后逐一完善函数功能在主函数后方,此时根据需求在头部添加头文件:

#include<iostream>
#include<fstream>
#include<locale>
#include<string>

1.菜单:

        打印需求和对应的功能,接收用户输入数字并返回给switch,自然返回值类型为int,并添加一些文字提示:

int show_menu()
{
	cout << "~~~~~~~~~~~~~~~欢迎使用通讯录管理系统~~~~~~~~~~~~~~~" << endl;
	cout << "\t1----显示所有联系人" << endl;
	cout << "\t2----添加联系人" << endl;
	cout << "\t3----删除联系人" << endl;
	cout << "\t4----修改联系人" << endl;
	cout << "\t5----清空联系人列表" << endl;
	cout << "\t0----退出系统" << endl;
	cout << "请您输入选项所对应的数字:" << endl;
	int i = 0;
	cin >> i;
	return i;
}

        修改主函数switch语句条件为:

int main()
{
	bool flag = true;
	while (flag)
	{

		switch (show_menu())
		{
		case 1://省略

2.查看通讯录:

        查看通讯录是需要我们读取txt文件,并输出,这里我们按行读取:

void read_line()
{
    //txt文件路径含有中文字符,所以需要一个宽字符串变量wstring来记录,名为filePath,使用L表示引号内为宽字符串,双斜杠用以转义,否则会出错
	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";
	ifstream file(filePath);//定义一个ifstream(读取流)的对象file用于后续调用函数,打开文件,()内为路径
	if (file.is_open())//判断是否打开
	{
		string line;//定义一个字符串用于接收读取到的字符串
		while (getline(file, line))按行读取后暂时存入line中
		{
			cout << line << endl;//打印并换行
		}
		file.close();//关闭文件,释放资源
        cout <<"完成读取!!!"<< endl;//提示读取成功
	}
	else cout << "无法打开文件!!!" << endl;//文件打开失败时提示

}

3.添加联系人

        注意,我们是通过程序作为一个入口和路径最终达到修改txt文件的用法。

void add_people()
{
    //依旧是按行添加,首先接收用户输入的关于联系人的所有信息
	people x;
	cout << "请按照提示输入联系人的相关信息" << endl;
	cout << "姓名:";
	cin >> x.name;
	cout << endl;
	cout << "性别:";
	cin >> x.gender;
	cout << endl;
	cout << "住址:";
	cin >> x.address;
	cout << endl;
	cout << "电话号码:";
	cin >> x.phoneNumber;
	cout << endl;
	string line = "姓名:" + x.name + " 性别:" + x.gender + " 住址:" + x.address + " 电话号码:" + x.phoneNumber;//将联系人信息合并成一条string语句
	cout << line << endl;//打印给用户检查

	locale Oldlocale = locale::global(locale("zh_CN.UTF-8"));//改变编码方式为UTF-8,以防止乱码或输入后无法读取或输入进不去,并且记录原有环境为Oldlocale
	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";//记录路径
	ofstream file(filePath, ios::app);//以写入流ofstream定义对象file并打开文件,ios::app表示以追加的方式打开文件
	if (file.is_open())//判断文件是否打开
	{
		file << line << endl;//向其中添加联系人信息并且换行
		file.close();//关闭文件
		locale::global(Oldlocale);//将原有环境恢复防止菜单中的中文无法打印
		cout << "已成功添加联系人!" << endl;
	}
	else cout << "无法打开文件!!!" << endl;


}

4.删除联系人:

        对于文件的删除是将特定行以外的其余信息写入另一个文件最后进行替换:

void delete_people()
{
	string targetName;
	cout << "请输入您所要删除联系人的姓名:" << endl;
	cin >> targetName;//记录需要删除的联系人姓名
	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";
	fstream file(filePath, ios::in);//以只读的方式打开
	if (file.is_open())
	{
		wstring tempFilePath = L"D:\\study C++\\通讯录系统\\temp.txt";//临时文件的路径
		ofstream tempFile(tempFilePath);//创建一个临时文件
		string line;
		while (getline(file, line))
		{    //当该行不包含姓名时,直接写入临时文件
			size_t found = line.find(targetName);
			if (found == string::npos)
			{
				tempFile << line << endl;
			}
		}
		file.close();
		tempFile.close();//关闭两个文件
		cout << "已成功删除联系人" << targetName << endl;
		const char* fileName = "D:\\study C++\\通讯录系统\\联系人目录.txt";
		const char* tempFileName = "D:\\study C++\\通讯录系统\\temp.txt";
		if (remove(fileName) != 0)
		{
			cout << "无法删除原始文件!" << endl;
			return;
		}
		if (rename(tempFileName, fileName) != 0) // 将临时文件重命名为原始文件的名称
		{
			cout << "无法重命名临时文件!" << endl;
			return;
		}
	}
	else
	{
		cout << "无法打开文件!" << endl;
	}
}

5.修改联系人:

        修改与删除原理相似:

void modify_people()//修改联系人
{
	string targetName;
	cout << "请输入您所要修改联系人的姓名:" << endl;
	cin >> targetName;
	people x;
	cout << "请按照提示输入联系人的相关信息" << endl;
	cout << "姓名:";
	cin >> x.name;
	cout << endl;
	cout << "性别:";
	cin >> x.gender;
	cout << endl;
	cout << "住址:";
	cin >> x.address;
	cout << endl;
	cout << "电话号码:";
	cin >> x.phoneNumber;
	cout << endl;
	string xline = "姓名:" + x.name + " 性别:" + x.gender + " 住址:" + x.address + " 电话号码:" + x.phoneNumber;
	cout << "修改后的信息为:" << xline << endl;
	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";
	fstream file(filePath, ios::in);
	if (file.is_open())
	{
		wstring tempFilePath = L"D:\\study C++\\通讯录系统\\temp.txt";
		ofstream tempFile(tempFilePath);
		string line;
		while (getline(file, line))
		{
			size_t found = line.find(targetName);
			if (found != string::npos)
			{
				tempFile << xline << endl;
			}
			else
			{
				tempFile << line << endl;//对特定行,进行新信息的输入
			}

		}
		file.close();
		tempFile.close();
		const char* fileName = "D:\\study C++\\通讯录系统\\联系人目录.txt";
		const char* tempFileName = "D:\\study C++\\通讯录系统\\temp.txt";
		if (remove(fileName) != 0)
		{
			cout << "无法删除原始文件!" << endl;
			return;
		}
		if (rename(tempFileName, fileName) != 0) // 将临时文件重命名为原始文件的名称
		{
			cout << "无法重命名临时文件!" << endl;
			return;
		}
	}
	else
	{
		cout << "无法打开文件!" << endl;
	}
}

 6.清空通讯录

        以覆盖的形式打开文件,直接输入“”;

void clear_people()//清空通讯录
{
	locale Oldlocale = locale::global(locale("zh_CN.UTF-8"));
	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";
	ofstream file(filePath);
	if (file.is_open())
	{
		file << "" << endl;
		file.close();
		locale::global(Oldlocale);
		cout << "已成功清空联系人!" << endl;
	}
	else cout << "无法打开文件!!!" << endl;
}

最终代码

#include<iostream>
#include<fstream>
#include<locale>
#include<string>

using namespace std;

struct people
{
	string name;
	string gender;
	string address;
	string phoneNumber;
};

int show_menu();
void read_line();
void add_people();
void delete_people();
void modify_people();
void clear_people();

int main()
{
	bool flag = true;
	while (flag)
	{

		switch (show_menu())
		{
		case 1:
			read_line();
			break;
		case 2:
			add_people();
			break;
		case 3:
			delete_people();
			break;
		case 4:
			modify_people();
			break;
		case 5:
			clear_people();
			break;
		case 0:
			cout << "欢迎下次使用!!!" << endl;
			flag = false;
			break;
		default:
			cout << "您输入的数字不在范围之内!!!" << endl;
			break;
		}
	}
	return 0;
}

int show_menu()
{
	cout << "~~~~~~~~~~~~~~~欢迎使用通讯录管理系统~~~~~~~~~~~~~~~" << endl;
	cout << "\t1----显示所有联系人" << endl;
	cout << "\t2----添加联系人" << endl;
	cout << "\t3----删除联系人" << endl;
	cout << "\t4----修改联系人" << endl;
	cout << "\t5----清空联系人列表" << endl;
	cout << "\t0----退出系统" << endl;
	cout << "请您输入选项所对应的数字:" << endl;
	int i = 0;
	cin >> i;
	return i;
}

void read_line()
{

	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";
	ifstream file(filePath);
	if (file.is_open())
	{
		string line;
		while (getline(file, line))
		{
			cout << line << endl;
		}
		file.close();

	}
	else cout << "无法打开文件!!!" << endl;

}

void add_people()
{
	people x;
	cout << "请按照提示输入联系人的相关信息" << endl;
	cout << "姓名:";
	cin >> x.name;
	cout << endl;
	cout << "性别:";
	cin >> x.gender;
	cout << endl;
	cout << "住址:";
	cin >> x.address;
	cout << endl;
	cout << "电话号码:";
	cin >> x.phoneNumber;
	cout << endl;
	string line = "姓名:" + x.name + " 性别:" + x.gender + " 住址:" + x.address + " 电话号码:" + x.phoneNumber;
	cout << line << endl;

	locale Oldlocale = locale::global(locale("zh_CN.UTF-8"));
	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";
	ofstream file(filePath, ios::app);
	if (file.is_open())
	{
		file << line << endl;
		file.close();
		locale::global(Oldlocale);
		cout << "已成功添加联系人!" << endl;
	}
	else cout << "无法打开文件!!!" << endl;


}

void delete_people()
{
	string targetName;
	cout << "请输入您所要删除联系人的姓名:" << endl;
	cin >> targetName;
	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";
	fstream file(filePath, ios::in);
	if (file.is_open())
	{
		wstring tempFilePath = L"D:\\study C++\\通讯录系统\\temp.txt";
		ofstream tempFile(tempFilePath);
		string line;
		while (getline(file, line))
		{
			size_t found = line.find(targetName);
			if (found == string::npos)
			{
				tempFile << line << endl;
			}
		}
		file.close();
		tempFile.close();
		cout << "已成功删除联系人" << targetName << endl;
		const char* fileName = "D:\\study C++\\通讯录系统\\联系人目录.txt";
		const char* tempFileName = "D:\\study C++\\通讯录系统\\temp.txt";
		if (remove(fileName) != 0)
		{
			cout << "无法删除原始文件!" << endl;
			return;
		}
		if (rename(tempFileName, fileName) != 0)
		{
			cout << "无法重命名临时文件!" << endl;
			return;
		}
	}
	else
	{
		cout << "无法打开文件!" << endl;
	}
}

void modify_people()
{
	string targetName;
	cout << "请输入您所要修改联系人的姓名:" << endl;
	cin >> targetName;
	people x;
	cout << "请按照提示输入联系人的相关信息" << endl;
	cout << "姓名:";
	cin >> x.name;
	cout << endl;
	cout << "性别:";
	cin >> x.gender;
	cout << endl;
	cout << "住址:";
	cin >> x.address;
	cout << endl;
	cout << "电话号码:";
	cin >> x.phoneNumber;
	cout << endl;
	string xline = "姓名:" + x.name + " 性别:" + x.gender + " 住址:" + x.address + " 电话号码:" + x.phoneNumber;
	cout << "修改后的信息为:" << xline << endl;
	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";
	fstream file(filePath, ios::in);
	if (file.is_open())
	{
		wstring tempFilePath = L"D:\\study C++\\通讯录系统\\temp.txt";
		ofstream tempFile(tempFilePath);
		string line;
		while (getline(file, line))
		{
			size_t found = line.find(targetName);
			if (found != string::npos)
			{
				tempFile << xline << endl;
			}
			else
			{
				tempFile << line << endl;
			}

		}
		file.close();
		tempFile.close();
		const char* fileName = "D:\\study C++\\通讯录系统\\联系人目录.txt";
		const char* tempFileName = "D:\\study C++\\通讯录系统\\temp.txt";
		if (remove(fileName) != 0)
		{
			cout << "无法删除原始文件!" << endl;
			return;
		}
		if (rename(tempFileName, fileName) != 0)
		{
			cout << "无法重命名临时文件!" << endl;
			return;
		}
	}
	else
	{
		cout << "无法打开文件!" << endl;
	}
}

void clear_people()
{
	locale Oldlocale = locale::global(locale("zh_CN.UTF-8"));
	wstring filePath = L"D:\\study C++\\通讯录系统\\联系人目录.txt";
	ofstream file(filePath);
	if (file.is_open())
	{
		file << "" << endl;
		file.close();
		locale::global(Oldlocale);
		cout << "已成功清空联系人!" << endl;
	}
	else cout << "无法打开文件!!!" << endl;
}

fstream总结

fstream 是 C++ 标准库中用于文件输入输出的类。它是 iostream 类的派生类,提供了对文件的读写操作。

fstream 类定义了以下几个主要的成员函数:

  1. open():用于打开文件。可以指定文件名以及打开模式,如读取模式、写入模式、追加模式等。
  2. close():用于关闭已打开的文件。
  3. is_open():用于检查文件是否成功打开。
  4. eof():用于检查是否到达文件末尾(End-Of-File)。
  5. fail():用于检查文件操作是否失败。
  6. good():用于检查流状态是否良好,即无错误发生。
  7. seekg() 和 seekp():用于设置文件指针的位置,以便定位读写位置。
  8. tellg() 和 tellp():用于获取当前文件指针的位置。
  9. getline():用于从文件中读取一行字符串。
  10. operator<<() 和 `operator>>():重载了插入运算符和提取运算符,用于向文件中写入数据和从文件中读取数据。

使用 fstream 进行文件操作的一般步骤如下:

  1. 创建 fstream 对象,指定文件名和打开模式。
  2. 使用 open() 函数打开文件。
  3. 判断文件是否成功打开,可以使用 is_open() 函数进行检查。
  4. 使用 operator<<() 或 `operator>>() 函数向文件写入数据或从文件读取数据。
  5. 使用 close() 函数关闭文件。

代码示例:

#include <fstream>
#include <iostream>

int main() {
    std::fstream file;
    file.open("data.txt", std::ios::out); // 打开文件用于写入模式

    if (file.is_open()) {
        file << "Hello, World!" << std::endl; // 向文件写入数据
        file.close(); // 关闭文件
    } else {
        std::cout << "Failed to open the file." << std::endl;
    }

    file.open("data.txt", std::ios::in); // 打开文件用于读取模式

    if (file.is_open()) {
        std::string line;
        std::getline(file, line); // 从文件读取一行数据
        std::cout << "Data from file: " << line << std::endl;
        file.close(); // 关闭文件
    } else {
        std::cout << "Failed to open the file." << std::endl;
    }

    return 0;
}

locale总结

  locale 是 C++ 标准库中的一个类,用于处理与本地化相关的操作。它提供了一种机制来处理语言、时间、货币等与地区有关的信息。locale 类定义了一种包含了特定地区相关信息的对象,可以在程序中使用这个对象来获取地域相关的数据和格式化输出。

  locale 类的对象可以表示特定的地区,如 "zh_CN" 表示中国,"en_US" 表示美国等。通过设置合适的 locale 对象,我们可以根据当前地区的习惯方式进行字符串的转换、时间日期的格式化、货币的显示以及其他与地区有关的操作。

        C++ 标准库提供了一些与 locale 相关的类和函数,例如 std::localestd::numpunctstd::money_getstd::time_get 等。我们可以使用这些类和函数来实现与本地化相关的功能。

        在给定的代码示例中,locale 用于设置程序的默认地区为 "zh_CN.UTF-8",以便正确处理中文字符的输入和输出。具体来说,在添加联系人和清空联系人列表时,程序会将 locale 设置为 "zh_CN.UTF-8",以支持中文字符的写入和输出。设置之前会先保存原始的 locale,以便在操作完成后恢复为之前的地区设置。

        请注意,locale 的使用需要依赖操作系统的支持,不同的操作系统可能有不同的地区编码和命名规则。因此,在实际使用中,建议根据具体的需求和目标地区选择合适的 locale 设置。

locale 头文件中包含了一些重要的类和函数,用于处理与本地化相关的操作。下面是一些常用的 locale 类和函数的介绍:

  1. std::locale 类:std::localelocale 库的核心类,表示一个特定的地区设置。它提供了许多函数和成员变量,允许我们查询和修改地区相关的设置。例如:

    • std::locale():无参构造函数,创建一个默认的地区对象。
    • std::locale(const char* name):使用给定的地区名称创建一个地区对象。
    • std::locale::global(const std::locale& loc):将给定的地区对象设置为全局地区,在整个程序中生效。
  2. std::numpunct 类:std::numpunct 是一个与数值格式化相关的类,用于控制数字的显示方式(如小数点、分组符号等)。我们可以通过继承 std::numpunct 类并实现自定义的数字格式化规则来满足特定的需求。

  3. std::money_getstd::money_put 类:这两个类用于货币的输入和输出。std::money_get 类负责将字符串解析为货币值,而 std::money_put 类负责将货币值格式化为字符串。

  4. std::time_getstd::time_put 类:这两个类用于时间和日期的输入和输出。std::time_get 类负责将字符串解析为时间值,而 std::time_put 类负责将时间值格式化为字符串。

  5. std::use_facet 函数:std::use_facet 是一个模板函数,用于获取特定类型的 facet(如 std::numpunctstd::money_getstd::time_get 等)以进行定制化的操作。它可以根据当前的地区设置自动选择正确的 facet。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值