在DOS屏幕上用C++的文件流操作写了一个简易的客户账户管理系统

整个系统用到的C++语法有:
1.C++高级文件输入输出(包括文件的常用打开模式)
2.C++数据类型time_t
3.C++结构体
程序中遇到的一些问题及解决
1.string类对象的赋值。
比如string x=“sdfsf”+数字型变量;
这样显然是不可取的,此时就需要用到string类对象的数字转换函数to_string(T value)来将T类型的数字值转换为字符串形式(详见精通C++820页)
2.time_t数据类型的使用见678页
3.在进行删除操作时,遇到从把一个文件的内容写入另一个文件时总会在eof()判断结束后又执行一次while循环的问题,这是因为当时吧eof()函数的判断写到了while()表达式中所造成的的(详见程序),
判断一个文件结束标志(即eof()函数)的合理使用参考博客:https://blog.csdn.net/ungoneless/article/details/51280072
代码如下:

#include<iostream>
#include<fstream>
#include<string>
#include<iomanip>
#include<cctype>//toupper()函数
#include<ctime>//设置时间
using namespace std;

void showClient();//显示所有账户
void addNewClient();//新增账户
void showMenu();//显示菜单
void deleteClient();//删除账户
void changeClient();//更改某账户信息
void lookupClient();//查看某账户信息
const int NAME_SIZE = 15, ADDR_SIZE = 50, POSTAL_SIZE = 10, CITY_SIZE = 20, DATE_SIZE = 50;//账户各数组大小

struct clientAccount
{//客户账户
	char name[NAME_SIZE];
	char address[ADDR_SIZE];
	char city[CITY_SIZE];
	char postalcode[POSTAL_SIZE];
	int balance;
	char date[DATE_SIZE];
};
	time_t epSeconds;//C++数据类型time_t表示自时间原点(1900年1月1日)以来所经过的秒数
int main()
{
	
	//showMenu();//如果只显示1次菜单,do循环中的showMenu()移出即可
	do
	{
		showMenu();
		int choice;//业务代号
		cout << "请选择相应序号进行业务处理! ";
		cin >> choice;
		cin.ignore();//清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响
		cout << endl;
		switch (choice)
		{//业务代号进入不同业务处理
			case 1:
				addNewClient();
			break;
			case 2:
				showClient();
			break;
			case 3:
				deleteClient();
				break;
			case 4:
				changeClient();
				break;
			case 5:
				lookupClient();
				break;
			case 6:exit(0);
		}
		cout << endl;
	} while (1);
	return 0;
}
void showMenu()
{
	//菜单显示格式
	cout << fixed << showpoint << setprecision(2);
	cout << "-----------------客户账户管理系统----------------" << endl;
	cout <<setw(22)<< "1.创建客户账户记录";
	cout <<setw(25)<< "2.显示全部客户账户记录" << endl;
	cout <<setw(22)<< "3.删除客户账户记录";
	cout <<setw(21)<< "4.更改客户账户记录" << endl;
	cout << setw(22)<<"5.查找客户账户记录";
	cout <<setw(13)<< "6.退出程序" << endl;
	cout << endl;
}
void addNewClient()
{
	fstream input("clientAccountSystem.dat", ios::in | ios::binary);//判断是否存在文件clientAccountSystem.dat
	if (!input)
	{
		fstream output;
		output.open("clientAccountSystem.dat", ios::out | ios::binary);//同时使用ios::in和ios::out文件的当前内容将被保留,且读写位置最初在文件的开头
		if (!output)
		{//判断文件是否打开
			cout << "文件未打开!" << endl;
			exit(0);
		}
		output.close();
	}
	else { input.close(); }
	epSeconds = time(0);//自时间原点(计算机科学设定日历时间标记时间原点为1970年1月1日午夜)到现在的秒数
	tm *pCalendarTime = new tm;
	//cout << epSeconds;
	localtime_s(pCalendarTime, &epSeconds);
	
	fstream output;
	output.open("clientAccountSystem.dat",ios::in|ios::out | ios::binary);//同时使用ios::in和ios::out文件的当前内容将被保留,且读写位置最初在文件的开头
	if (!output)
	{//判断文件是否打开
		cout << "文件未打开!" << endl;
		exit(0);
	}
	bool add = 0;//是否继续新增客户账户
	clientAccount client;//客户账户
	string inputString;//输入字符串
	output.seekp(0,ios::end);//将文件写入位置调整到文件末尾(如果不进行位置调整,由于是以ios::in|ios::out方式打开,文件始终在最开始的位置,会使新增的用户覆盖原有用户)
	do
	{
		cout << "请输入客户姓名:";
		getline(cin, inputString);
		strcpy_s(client.name, inputString.c_str());//完全可以换种方式输入,书上这样写的就照搬过来了
		cout << "请输入客户地址:";
		getline(cin, inputString);
		strcpy_s(client.address, inputString.c_str());
		cout << "请输入所在城市:";
		getline(cin, inputString);
		strcpy_s(client.city, inputString.c_str());
		cout << "请输入充值金额:";
		cin >> client.balance;
		cin.ignore();
		cout << "请输入邮政编码:";
		getline(cin, inputString);
		strcpy_s(client.postalcode, inputString.c_str());
		inputString = "添加于";
		inputString +=to_string(1900+pCalendarTime->tm_year)+"年" + to_string(pCalendarTime->tm_mon) + "月" + to_string(pCalendarTime->tm_mday) + "日" + to_string(pCalendarTime->tm_hour) + "时" + to_string(pCalendarTime->tm_min) + "分" + to_string(pCalendarTime->tm_sec) + "秒";
		strcpy_s(client.date, inputString.c_str());
		output.write(reinterpret_cast<char*>(&client), sizeof(client));//写入文件操作
		cout << "\n是否继续添加客户?|  1.继续请输入1  |  2.不继续请输入0  |";
		cin >> add;
		cin.ignore();
	} while (add == 1);
	output.close();//关闭文件
}

//同类型不再注释,参照上面的代码注释

//查找某客户账户信息
void lookupClient()
{
	char name[NAME_SIZE];
	clientAccount client;
	int i = 0;//用来移动读操作的位置
	int count = 0;//用来判断客户是否存在
	cout << "请输入客户姓名:";
	cin >> name;
	cin.ignore();
	fstream lookup("clientAccountSystem.dat", ios::in | ios::out | ios::binary);
	if (!lookup)
	{
		cout << "文件未打开!" << endl;
		exit(0);
	}
	while (!lookup.eof())
	{
		lookup.seekg(sizeof(clientAccount)*i++, ios::beg);//移动读操作位置
		lookup.read(reinterpret_cast<char *>(&client), sizeof(client));//读取该位置客户账户
		if (!strcmp(name, client.name))
		{
			//如果有和输入账户名相同账户,则count加1,表示客户账户存在
			count++;
			//输出客户账户信息
			cout << "客户姓名:" << client.name << endl;
			cout << "客户当前余额:" << client.balance << endl;
			cout << "客户地址:" << client.address << endl;
			cout << "客户所在城市:" << client.city << endl;
			cout << "邮政编码:" << client.postalcode << endl;
			cout << client.date << endl;
		}
	}
	char response = 'N';//判断是否创建账户
	string inputString;
	if (count == 0)
	{
		cout << "客户账户不存在!" << endl;
		cout << "是否创建账户?|  是请输入'Y'  |  否请输入'N'  |";
		cin >> response;
		cin.ignore();
		if (toupper(response) == 'Y')
		{
			fstream output;
			output.open("clientAccountSystem.dat", ios::out|ios::in | ios::binary);
			if (!output)
			{
				cout << "文件未打开!" << endl;
				exit(0);
			}
			epSeconds = time(0);//自时间原点(计算机科学设定日历时间标记时间原点为1970年1月1日午夜)到现在的秒数
			tm *pCalendarTime = new tm;
			//cout << epSeconds;
			localtime_s(pCalendarTime, &epSeconds);
			clientAccount client;
			string inputString;
			output.seekp(0, ios::end);
			strcpy_s(client.name, name);
			cout << "请输入客户地址:";
			getline(cin, inputString);
			strcpy_s(client.address, inputString.c_str());
			cout << "请输入所在城市:";
			getline(cin, inputString);
			strcpy_s(client.city, inputString.c_str());
			cout << "请输入充值金额:";
			cin >> client.balance;
			cin.ignore();
			cout << "请输入邮政编码:";
			getline(cin, inputString);
			strcpy_s(client.postalcode, inputString.c_str());
			inputString = "添加于";
			inputString += to_string(1900 + pCalendarTime->tm_year) + "年" + to_string(pCalendarTime->tm_mon) + "月" + to_string(pCalendarTime->tm_mday) + "日" + to_string(pCalendarTime->tm_hour) + "时" + to_string(pCalendarTime->tm_min) + "分" + to_string(pCalendarTime->tm_sec) + "秒";
			strcpy_s(client.date, inputString.c_str());
			output.write(reinterpret_cast<char*>(&client), sizeof(client));
			output.close();
		}
	}
	lookup.close();
}

//删除账户
void deleteClient()
{
	char confirm = 'N';//确认删除
	clientAccount client;
	fstream clear("clientAccountSystem.dat", ios::in | ios::out | ios::binary);
	if (!clear)
	{
		cout << "文件未打开!" << endl;
		exit(0);
	}
	showClient();//显示所有账户,以供选择待删除账户代号
	int number;
	cout << "请输入待删除客户编号:";
	cin >> number;
	cin.ignore();
	//找到待删除账户的位置
	clear.seekg(sizeof(clientAccount)*(number-1), ios::beg);
	clear.read(reinterpret_cast<char*>(&client), sizeof(client));
	
	//确认删除客户账户
	cout << "客户姓名:" << client.name << endl;
	cout << "客户当前余额:" << client.balance << endl;
	cout << "客户地址:" << client.address << endl;
	cout << "客户所在城市:" << client.city << endl;
	cout << "邮政编码:" << client.postalcode << endl;
	cout << client.date << endl;
	cout << "请确认是否删除当前账户?|  确认删除请输入'Y'  |  不删除请输入'N'  |";
	cin >> confirm;
	cin.ignore();
	if (toupper(confirm) == 'Y')
	{//若确认删除,则将未删除部分写入另一个文件(即跳过待删除的账户)
		fstream output;
		output.open("clientAccountSystem1.dat", ios::out | ios::binary);
		if (!output)
		{
			cout << "文件未打开!";
			exit(0);
		}
		int i = 0,//用i的增加进行移动以匹配输入的删除选择代号,
			j=0;//如果找到了要删除的账户时,不增加j,已和写入位置匹配
		while (1)
		{
			clear.seekg(sizeof(clientAccount)*i, ios::beg);
			clear.read(reinterpret_cast<char *>(&client), sizeof(client));
			if (clear.eof()) break;//先判断是否到了原文件结束标志处,必须这样写,否则循环会多进行一次而将程序的最后一个账户重复存储一次
			if (i ==(number-1) )
			{
				i++;
			}
			else
			{//写入新文件
				clear.seekp(sizeof(clientAccount)*j, ios::beg);
				output.write(reinterpret_cast<char *>(&client), sizeof(client));
				i++;
				j++;
			}
		}
		output.close();
	}
	clear.close();
	if (confirm == 'Y')
	{
		remove("clientAccountSystem.dat");//删除源文件
		rename("clientAccountSystem1.dat", "clientAccountSystem.dat");//重命名新文件为源文件名
	}
	
}


//更新账户信息
void changeClient()
{
	int number;
	clientAccount client;
	fstream change("clientAccountSystem.dat", ios::in | ios::out | ios::binary);
	showClient();
	cout << "请输入要更正的客户账户编号:";
	cin >> number;
	cin.ignore();
	change.seekg(sizeof(clientAccount)*(number - 1), ios::beg);
	change.read(reinterpret_cast<char*>(&client), sizeof(client));
	int choice;//更新信息编号
	char response = 'N';
	string input;
	do
	{
		cout << "请选择要更正的内容编号:|1.姓名|2.地址|3.城市|4.余额|5.邮政编码| ";
		cin >> choice;
		cin.ignore();
		switch (choice)
		{
		case 1:cout << "请输入:"; getline(cin, input); strcpy_s(client.name, input.c_str()); break;
		case 2:cout << "请输入:"; cin >> client.address; cin.ignore(); break;
		case 3:cout << "请输入:"; cin >> client.city; cin.ignore(); break;
		case 4:cout << "请输入:"; cin >> client.balance; cin.ignore(); break;
		case 5:cout << "请输入:"; cin >> client.postalcode; cin.ignore(); break;
		}
		cout << "是否继续更正当前账户?|  是请输入'Y'  |  否请输入'N'  |";
		cin >> response;
		cin.ignore();
	}while (toupper(response) == 'Y');
	//更新后账户数据写入文件
	epSeconds = time(0);//自时间原点(计算机科学设定日历时间标记时间原点为1970年1月1日午夜)到现在的秒数
	tm *pCalendarTime = new tm;
	//cout << epSeconds;
	localtime_s(pCalendarTime, &epSeconds);
	string inputString = "更新于";
	inputString += to_string(1900 + pCalendarTime->tm_year) + "年" + to_string(pCalendarTime->tm_mon) + "月" + to_string(pCalendarTime->tm_mday) + "日" + to_string(pCalendarTime->tm_hour) + "时" + to_string(pCalendarTime->tm_min) + "分" + to_string(pCalendarTime->tm_sec) + "秒";
	strcpy_s(client.date, inputString.c_str());
	change.seekp(sizeof(clientAccount)*(number - 1), ios::beg);
	change.write(reinterpret_cast<char *>(&client), sizeof(client));
	change.close();
}

//所有客户账户数据陈列
void showClient()
{
	int i = 1;
	fstream input("clientAccountSystem.dat", ios::in | ios::binary);
	if (!input)
	{
		cout << "文件读入失败!";
		exit(0);
	}
	clientAccount client;
	input.read(reinterpret_cast<char*>(&client), sizeof(client));
	while (!input.eof())
	{
		cout << i++ << ".";
		cout << "客户姓名:" << client.name << endl;
		cout << "客户当前余额:" << client.balance << endl;
		cout << "客户地址:" << client.address << endl;
		cout << "客户所在城市:" << client.city << endl;
		cout << "邮政编码:" << client.postalcode << endl;
		cout << client.date << endl << endl;
		input.read(reinterpret_cast<char*>(&client), sizeof(client));
	}
	input.close();
}

参考文献:精通C++第9版,Tony Gaddis(黄刚等译)

猜你喜欢

转载自blog.csdn.net/qq_44713855/article/details/103207125
今日推荐