Data structure course design -- ticket sales system (C + +)

Posted by motofzr1000 on Tue, 04 Jan 2022 15:17:53 +0100

introduction

The data structure course design at the end of this semester requires us to complete a simple small program. I chose a ticket sales system to realize some basic functions; Because the time is short and I make up lessons in the review week, there is nothing outstanding. I'll talk about my code implementation and what can be further improved here;

Note: the program does not use the object-oriented part of C + +, but uses process oriented programming, mainly using some containers and functions of C + +;

Implementation process

basic function

The functions are simple, including the following five types:
1. Ticket purchase
2. Refund
3. Display user information
4. Query user information
5. View flight information

Because it is a ticketing system, operations such as adding and deleting flights are not added. Of course, it is easy to add if you want to;

Although the function is very simple, the judgment of input information needs to be rigorous, so how to formulate judgment rules also needs to be considered;

data structure

Firstly, we consider what data structure is used to store user information and flight information. Because we need to quickly retrieve information and use the most basic file operation instead of database, we consider using hash table to store user information and flight information, and set the key value to the last six digits of ID card and flight number respectively; (here, the hash table operation is implemented through the map container)

structural morphology

Then consider the structure of users and flights, and the code is as follows:

// Customer information structure
struct Person {
	string name; // full name
	string age; // Age
	string gender; // Gender
	string idNum; // ID number
	string myAirNum; // User flight number
};

// Flight information structure
struct Airplane {
	string airNum; // flight number
	string startPoint; // starting point
	string destination; // destination
	string tickets; // Number of votes
	string ticketPrice; // Ticket Price
	string departureTime; // Takeoff time
};

It's very simple and there's nothing to say. Someone may find: why do all variables use string type? It is mainly considered that the contents of the file should be read into the memory during initialization, and all the strings read from the file are strings, so they are directly defined as strings;
Of course, this is not necessarily the best way. I also thought of defining a set of transformation system, but time is tight, so I don't tangle too much here; If you have a better way, you are also welcome to communicate!

file

Because I use files instead of databases here, I don't need to consider the design of table structure, but I still need to design the basic file format;

First, select two documents txt file, one is userInfo to store user information, and the other is airport to store flight information;

Next, we need to consider how to store the file. Because the initialization needs to read the contents of the file into memory, I define that each user information (flight information) occupies one line, and each attribute is divided by a space. In this way, when reading the file, you can read only one line at a time, and then divide the string based on the space;

The contents of the document are shown in the figure below:

function

Now you can think about what functions you need. I divide functions into two categories: basic function functions and tool functions;

The function comments have been very detailed. Unless I will elaborate on special ones, I won't say much about others;

1, Basic function

Function declaration:

void initInfo(); // Initialization information
void UI(); // UI interface
void showUserInfo(); // Display output user information
void showAirplaneInfo(); // Display and output flight information
void sellTickets(); // sell ticket
void selectUserInfo(string idNum); // Query user information
void refundTickets(string idNum); // to refund a ticket

UI interface

Print out the operation interface and operation summary;

/// <summary>
///UI interface
/// </summary>
void UI() {
	while (true) {
		// Print interface
		cout << "************Welcome xxxx Air ticketing system**********" << endl;
		cout << "************** 1, purchase    ticket   **************" << endl;
		cout << "************** 2, retreat    ticket   **************" << endl;
		cout << "************** 3,View ticket information **************" << endl;
		cout << "************** 4,Find user information **************" << endl;
		cout << "************** 5,View flight information **************" << endl;
		cout << "************** 6, retreat    Out   **************" << endl;
		int choose; // option
		cin >> choose; // Input selection
		switch (choose) {
			case 1 : 
				sellTickets(); // sell ticket
				break;
			case 2: {
				string id;
				while (true) {
					cout << "Please input the ID number of the refund person:";
					cin >> id;
					// Judge whether the ID number is legal.
					if (idNumIsLegal(id)) {
						break;
					}
					cout << "The ID number is not valid. Please retype it." << endl;
				}
				refundTickets(id); // to refund a ticket
				break;
			}
			case 3 :
				showUserInfo(); // View ticket information
				break;
			case 4: {
				string id;
				while (true) {
					cout << "Please enter the ID number for the user:";
					cin >> id;
					// Judge whether the ID number is legal.
					if (idNumIsLegal(id)) {
						break;
					}
					cout << "The ID number is not valid. Please retype it." << endl;
				}
				selectUserInfo(id); // View query user information
				break;
			}
			case 5 : 
				showAirplaneInfo(); // View flight information
				break;
			case 6 : 
				cout << "Welcome to use next time!" << endl;
				exit(-1); // sign out
		}
		system("pause");
		system("cls");
	}
}

Initialization information

The main purpose is to initialize the contents of the file into memory to facilitate subsequent operations;

/// <summary>
///Initialization information
/// </summary>
void initInfo() {
	ifstream ifs01;
	// Initialize flight information
	ifs01.open("airplane.txt", ios::in); // Open file
	// If file opening fails
	if (!ifs01.is_open()) {
		cout << "File opening failed!\a" << endl;
		exit(-1);
	}
	// If the flight information is not empty
	string ainfo; // Temporarily store each flight information
	// Read customer information by line
	while (getline(ifs01, ainfo)) {
		vector<string> separateInfo; // Store separate information
		separateInfo = split(ainfo, " "); // Separate flight information
		Airplane airplane; // Store temporary flight information
		airplane.airNum = separateInfo[0]; // Deposit flight number
		airplane.startPoint = separateInfo[1]; // Storage starting point
		airplane.destination = separateInfo[2]; // Storage destination
		airplane.tickets = separateInfo[3]; // Number of votes deposited
		airplane.ticketPrice = separateInfo[4]; // Deposit fare
		airplane.departureTime = separateInfo[5]; // Store takeoff time
		// Flight information storage
		string key = separateInfo[0]; // Get the key value, i.e. flight number
		airplaneInfo.insert(pair<string, Airplane>(key, airplane)); // Save flight information into map
	}
	ifs01.close(); 

	// Initialize user information
	ifstream ifs02;
	ifs02.open("userInfo.txt", ios::in); // Open file
	// If file opening fails
	if (!ifs02.is_open()) {
		cout << "File opening failed!\a" << endl;
		exit(-1);
	}
	// If user information is not empty
	string info; // Temporarily store each customer information
	// Read customer information by line
	while (getline(ifs02, info)) {
		vector<string> separateInfo; // Store separate information
		separateInfo = split(info, " "); // Separate customer information
		Person person; // Store temporary customer information
		person.name = separateInfo[0]; // Deposit name
		person.age = separateInfo[1]; // Storage age
		person.gender = separateInfo[2]; // Storage gender
		person.idNum = separateInfo[3]; // Storage ID number
		person.myAirNum = separateInfo[4]; // Deposit flight number
		// Customer information storage
		string key = separateInfo[3].substr(13); // The last six digits of the ID card are the map index value key
		userInfo.insert(pair<string, Person>(key, person)); // Store customer information in map
	}
	ifs02.close();
}

sell ticket

Add users and save files;

/// <summary>
///Ticket selling
/// </summary>
void sellTickets() {
	// 1. Enter user information
	Person person; // Ticket customer
	// Enter name
	while (true) {
		cout << "Please enter your name:";
		cin >> person.name;
		// Judge whether the name is legal
		if (nameIsLegal(person.name)) {
			break;
		}
		cout << "The name is illegal, please re-enter!" << endl;
	}
	// Enter age
	while (true) {
		cout << "Please enter age:";
		cin >> person.age;
		// Judge whether the input age is in line with common sense
		if (stringToInt(person.age)  > 110 || stringToInt(person.age) < 0) {
			cout << "Illegal age, please re-enter!" << endl;
		}
		else {
			break;
		}
	}
	// Enter gender
	while (true) {
		cout << "Please enter gender:";
		cin >> person.gender;
		// Judge whether the input gender is legal
		if (person.gender == "male" || person.gender == "female") {
			break;
		}
		cout << "Illegal gender, please re-enter!" << endl;
	}
	// Enter ID number
	while (true) {
		cout << "Please enter your ID number:";
		cin >> person.idNum;
		// Judge whether the ID number is legal.
		if (idNumIsLegal(person.idNum)) {
			break;
		}
		cout << "The ID number is not valid. Please retype it." << endl;
	}
	// Enter flight number
	while (true) {
		cout << "Please enter flight number:";
		cin >> person.myAirNum;
		// Judge whether the flight number is legal, the flight exists and the number of people is not full
		if (person.myAirNum[0] == 'x' && person.myAirNum.length() == 4
			&& airplaneInfo.find(person.myAirNum) != airplaneInfo.end() 
			&& stringToInt(airplaneInfo[person.myAirNum].tickets) != 0) {
			// If the current flight is purchased, the number of tickets for the flight should be reduced by one
			int tickets = stringToInt(airplaneInfo[person.myAirNum].tickets); // Convert to shaping
			tickets--;  // The number of votes is reduced by one
			airplaneInfo[person.myAirNum].tickets = to_string(tickets); // Convert to string
			updateAirplaneFile(); // Update flight file 
			break;
		}
		cout << "The flight number is illegal or does not exist or the number of flights is full, please select again!" << endl;
	}

	// 2. User information is stored in userInfo
	string key = person.idNum.substr(13); // Get the corresponding key value of the user: the ID number is 6 bits.
	userInfo.insert(pair<string, Person>(key, person)); // Store user information in map

	// 3. Write new user information to file
	fstream fs;
	fs.open("userInfo.txt", ios::out | ios::app); // Open file
	// write file
	fs << person.name + " " << person.age + " "
		<< person.gender + " " << person.idNum + " "
		<< person.myAirNum + " " << endl;
	cout << "Ticket purchase succeeded!!" << endl;
	fs.close();
}

Display output user information

/// <summary>
///Display output user information
/// </summary>
void showUserInfo() {
	// Judge whether the user information is empty
	if (userInfo.empty()) {
		cout << "User information is empty!!" << endl;
		return;
	}
	// If the user information is not empty, start traversal
	map<string, Person>::iterator it; // iterator 
	for (it = userInfo.begin(); it != userInfo.end(); it++) {
		cout << "full name:" + it->second.name
			 << " Age:" + it->second.age
			 << " Gender:" + it->second.gender
			 << " ID number:" + it->second.idNum
			 << " flight number:" + it->second.myAirNum 
			 << " starting point:"  + airplaneInfo[it->second.myAirNum].startPoint
			 << " End:" + airplaneInfo[it->second.myAirNum].destination
			 << " Ticket Price:" + airplaneInfo[it->second.myAirNum].ticketPrice
			 << " Departure time:" + airplaneInfo[it->second.myAirNum].departureTime
			 << endl;
	}
}

Display and output flight information

/// <summary>
///Display and output flight information
/// </summary>
void showAirplaneInfo() {
	// If flight information is empty
	if (airplaneInfo.empty()) {
		cout << "Flight information is empty!" << endl;
		return;
	}
	// If the flight information is not empty, start traversal
	map<string, Airplane>::iterator it; // iterator 
	int i = 0;
	for (it = airplaneInfo.begin(); it != airplaneInfo.end(); it++) {
		cout << "flight number:" + it->second.airNum
			 << " starting point:" + it->second.startPoint
			 << " End:" + it->second.destination
			 << " Number of votes:" + it->second.tickets
			 << " Ticket Price:" + it->second.ticketPrice
			 << " Departure time:" + it->second.departureTime
			 << endl;
	}
}

Query user information

Just find it directly;

/// <summary>
///Query user information
/// </summary>
/// <param name= "idNum" > query user ID number </param>
void selectUserInfo(string idNum) {
	string key = idNum.substr(13); // Get key value: ID number 6 after 6.
	// Judge whether the user information exists 
	if (userInfo.find(key) == userInfo.end()) {
		cout <<"The user does not exist!!" << endl;
		return ;
	}
	Person person = userInfo[key]; // Find user information through key
	// Output user information
	cout << "full name:" + person.name
		 << " Age:" + person.age
		 << " Gender:" + person.gender
		 << " ID number:" + person.idNum
		 << " flight number:" + person.myAirNum 
		 << " starting point:" + airplaneInfo[person.myAirNum].startPoint
		 << " End:" + airplaneInfo[person.myAirNum].destination
		 << " Ticket Price:" + airplaneInfo[person.myAirNum].ticketPrice
		 << " Departure time:" + airplaneInfo[person.myAirNum].departureTime
		 << endl;
}

to refund a ticket

For ticket refund, not only the user information should be deleted in the memory, but also in the file; However, the file operation does not have the function of direct deletion, so when the user information in the memory is deleted, clear all the file information, and then rewrite it, and write the user information in the memory into the file;

/// <summary>
///Refund
/// </summary>
//<param name= "idNum" > refund ticket user ID number </param>
void refundTickets(string idNum) {
	// Determine whether the user exists
	string key = idNum.substr(13); 
	// If it doesn't exist
	if (userInfo.find(key) == userInfo.end()) {
		cout << "User information does not exist!" << endl;
		return;
	}
	// If yes, the number of tickets for this flight needs to be increased by one
	int tickets = stringToInt(airplaneInfo[userInfo[key].myAirNum].tickets); // String to integer
	tickets++; // Number of votes plus one
	airplaneInfo[userInfo[key].myAirNum].tickets = to_string(tickets); // Integer to string
	updateAirplaneFile(); // Update flight file 
	userInfo.erase(key); // Delete from user information

	// Delete the user information from the file
	clearFile("userInfo.txt"); // Empty file
	// Rewrite file
	fstream fs;
	fs.open("userInfo.txt", ios::out | ios::app); // Open file
	// Traverse and rewrite user information
	for (auto i : userInfo) {
		 fs << i.second.name + " "
			<< i.second.age + " "
			<< i.second.gender + " "
			<< i.second.idNum + " "
			<< i.second.myAirNum << endl;
	}
	fs.close();
	cout << "Refund succeeded!!" << endl;
}

2, Tool function

Function declaration:

vector<string> split(const string& str, const string& delim); // String segmentation function
bool idNumIsLegal(string idNum); // Judge whether the ID number is legal.
bool nameIsLegal(string name); // Judge whether the name is legal
int stringToInt(string str); // Convert string type to int type
void clearFile(const string fileName); // Empty file contents
void updateAirplaneFile(); // Update flight file information

String segmentation function

Because there is no split function in C + +, but the corresponding functions can be realized through the strtok function of C language, I encapsulated a string segmentation function myself;

/// <summary>
///String segmentation function
/// </summary>
///< param name = "STR" > required split string < / param >
///< param name = "delim" > segmentation criteria < / param >
///< returns > string array < / returns >
vector<string> split(const string& str, const string& delim) {
	vector<string> res; // An array that holds split strings
	if ("" == str) return res; // If the string is empty, it cannot be split

	// First convert the string to be cut from string type to char * type  
	char* strs = new char[str.length() + 1];  
	strcpy(strs, str.c_str());

	char* d = new char[delim.length() + 1];
	strcpy(d, delim.c_str()); // Convert delim to char * and assign it to d

	char* p = strtok(strs, d); // The first call points to the decomposition string
	while (p) {
		string s = p; // The split string is converted to string type  
		res.push_back(s); // Save to result array  
		p = strtok(NULL, d); // After each segmentation, the decomposition string is NULL
	}
	return res;
}

Judge whether the ID number is legal.

In fact, the identification of ID number is only required to separate the ID number into several parts, and separately judge it.
But it's a bit cumbersome. You can choose a simpler regular expression to achieve judgement. Just C++ supports regular expressions, so I found the regular expression of the ID number on the Internet directly.

/// <summary>
//Judge whether the ID number is legal.
/// </summary>
/// <param name= "idNum" > ID number </param>
///< returns > legal is true, illegal is false < / returns >
bool idNumIsLegal(string idNum) {
	// Define a regular expression                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Rule of 18 digit ID number
	regex repPattern("^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$");
	// Declare matching result variables
	match_results<string::const_iterator> rerResult;
	// Match
	bool bValid = regex_match(idNum, rerResult, repPattern);
	if (bValid) {
		// Match successful
		//Cout "ID number format is legal!" endl;
		return true;
	}
	//Cout "the format of ID number is not legal!" endl;
	return false;
}

Judge whether the name is legal

Just like the ID number judgement, regular expression is used directly.

/// <summary>
///Judge whether the name is legal
/// </summary>
///< param name = "name" > name < / param >
///< returns > legal is true, illegal is false < / returns >
bool nameIsLegal(string name) {
	// Define a regular expression                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Rule of 18 digit ID number
	regex repPattern("^[\u4e00-\u9fa5]+(·[\u4e00-\u9fa5]+)*$");
	// Declare matching result variables
	match_results<string::const_iterator> rerResult;
	// Match
	bool bValid = regex_match(name, rerResult, repPattern);
	if (bValid) {
		// Match successful
		//Cout < < "the name format is legal!"<< endl;
		return true;
	}
	//Cout < < "illegal name format!"<< endl;
	return false;
}

Convert string type to int type

This uses the stoi function. For those who don't understand it, please see my article: stoi(), atoi(), to in C + +_ String () tips

/// <summary>
///Convert string type to int type
/// </summary>
///< param name = "STR" > string to be converted < / param >
///< returns > the converted integer of the string < / returns >
int stringToInt(string str) {
	// Determine whether the string is empty 
	if (str.empty()) {
		cout << "Data error, please check the file data!" << endl;
		return 0;
	}
    return stoi(str); // Convert string to integer
}

Empty file contents

/// <summary>
///Empty file contents
/// </summary>
///< param name = "filename" > file name < / param >
void clearFile(const string fileName) {
	fstream file(fileName, ios::out);
}

Update flight file information

This is the same as updating user information, that is, the rewriting is deleted, because it is written into a function separately after being used for many times;

/// <summary>
///Update flight file information
/// </summary>
void updateAirplaneFile() {
	// Remove from file
	clearFile("airplane.txt"); // Empty file
	// Rewrite file
	fstream fs;
	fs.open("airplane.txt", ios::out | ios::app); // Open file
	// Traverse and re write flight information
	for (auto i : airplaneInfo) {
		 fs << i.second.airNum + " "
			<< i.second.startPoint + " "
			<< i.second.destination + " "
			<< i.second.tickets + " "
			<< i.second.ticketPrice + " "
			<< i.second.departureTime + " "
			<< endl;
	}
	fs.close();
}

summary

Because the function implementation of this project is very simple, the code implementation is not so difficult; In fact, I think the most difficult thing at the beginning of a project is the process from 0 to 1. When the whole framework is established, there is actually no difficulty;

shortcoming

In fact, there is still a problem in the design of user information. If we get the ID number, we can get the gender and age of users directly. These two variables are redundant. If the code is further improved, I will give priority to this. This is also a problem in the initial design. It was only thought of in the end. At this time, if it was modified, there would be a lot of modified contents;
For me, this is also a lesson. The initial design must be rigorous, so as to avoid large-scale modification in the later stage;
At present, I haven't thought of any other problems. If you have other discoveries or novel ideas, you are welcome to communicate;

Code network disk link

Here is a link to obtain code and files. The software I use is vs2019. Some old gcc versions may not recognize regular expressions, so you can update the gcc version or use vs2019, that is, the above version;

Baidu online disk:
Link: https://pan.baidu.com/s/1BkLI-FhpJ05O2sTMUuf6cw
Extraction code: xxxx

Complete code

/*
 Project Name: ticket sales system
 Basic function realization:
		  1,Ticket purchase
		  2,to refund a ticket
		  3,Display user information
		  4,Query user information
		  5,View flight information
 Author:**********
 Version: 1.2
 Date: December 23, 2021
 Compilation environment: Visual Studio 2019, C++11
 
 Note: vs2019 or above is recommended. Regular expressions may not be recognized if the gcc version is too low
 You need to manually configure the latest gcc version 
*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<string.h>
#include<vector>
#include<map>
#include<regex>
#include<fstream>
#include<Windows.h>
using namespace std;

//
// structural morphology
//

// Customer information structure
struct Person {
	string name; // full name
	string age; // Age
	string gender; // Gender
	string idNum; // ID number
	//string destination; //  destination
	//vector<Airplane> airplane; //  Tickets purchased
	string myAirNum; // User flight number
};

// Flight information structure
struct Airplane {
	string airNum; // flight number
	string startPoint; // starting point
	string destination; // destination
	string tickets; // Number of votes
	string ticketPrice; // Ticket Price
	string departureTime; // Takeoff time
};

//
// global variable
//

map<string, Person> userInfo; // Global variable to store user information
map<string, Airplane> airplaneInfo; // Global variable to store flight information 

//
// Function declaration
//

void initInfo(); // Initialization information
void UI(); // UI interface
void showUserInfo(); // Display output user information
void showAirplaneInfo(); // Display and output flight information
void sellTickets(); // sell ticket
void selectUserInfo(string idNum); // Query user information
void refundTickets(string idNum); // to refund a ticket
vector<string> split(const string& str, const string& delim); // String segmentation function
bool idNumIsLegal(string idNum); // Judge whether the ID number is legal.
bool nameIsLegal(string name); // Judge whether the name is legal
int stringToInt(string str); // Convert string type to int type
void clearFile(const string fileName); // Empty file contents
void updateAirplaneFile(); // Update flight file information
// Airplane stringToAirplane(string info); //  Convert string to airplane type

//
// main function
//

int main() {
	initInfo();
	UI();
	return 0;
}

//
// Function implementation
//

/// <summary>
///UI interface
/// </summary>
void UI() {
	while (true) {
		// Print interface
		cout << "************Welcome xxxx Air ticketing system**********" << endl;
		cout << "************** 1, purchase    ticket   **************" << endl;
		cout << "************** 2, retreat    ticket   **************" << endl;
		cout << "************** 3,View ticket information **************" << endl;
		cout << "************** 4,Find user information **************" << endl;
		cout << "************** 5,View flight information **************" << endl;
		cout << "************** 6, retreat    Out   **************" << endl;
		int choose; // option
		cin >> choose; // Input selection
		switch (choose) {
			case 1 : 
				sellTickets(); // sell ticket
				break;
			case 2: {
				string id;
				while (true) {
					cout << "Please input the ID number of the refund person:";
					cin >> id;
					// Judge whether the ID number is legal.
					if (idNumIsLegal(id)) {
						break;
					}
					cout << "The ID number is not valid. Please retype it." << endl;
				}
				refundTickets(id); // to refund a ticket
				break;
			}
			case 3 :
				showUserInfo(); // View ticket information
				break;
			case 4: {
				string id;
				while (true) {
					cout << "Please enter the ID number for the user:";
					cin >> id;
					// Judge whether the ID number is legal.
					if (idNumIsLegal(id)) {
						break;
					}
					cout << "The ID number is not valid. Please retype it." << endl;
				}
				selectUserInfo(id); // View query user information
				break;
			}
			case 5 : 
				showAirplaneInfo(); // View flight information
				break;
			case 6 : 
				cout << "Welcome to use next time!" << endl;
				exit(-1); // sign out
		}
		system("pause");
		system("cls");
	}
}

/// <summary>
///Initialization information
/// </summary>
void initInfo() {
	ifstream ifs01;
	// Initialize flight information
	ifs01.open("airplane.txt", ios::in); // Open file
	// If file opening fails
	if (!ifs01.is_open()) {
		cout << "File opening failed!\a" << endl;
		exit(-1);
	}
	// If the flight information is not empty
	string ainfo; // Temporarily store each flight information
	// Read customer information by line
	while (getline(ifs01, ainfo)) {
		vector<string> separateInfo; // Store separate information
		separateInfo = split(ainfo, " "); // Separate flight information
		Airplane airplane; // Store temporary flight information
		airplane.airNum = separateInfo[0]; // Deposit flight number
		airplane.startPoint = separateInfo[1]; // Storage starting point
		airplane.destination = separateInfo[2]; // Storage destination
		airplane.tickets = separateInfo[3]; // Number of votes deposited
		airplane.ticketPrice = separateInfo[4]; // Deposit fare
		airplane.departureTime = separateInfo[5]; // Store takeoff time
		// Flight information storage
		string key = separateInfo[0]; // Get the key value, i.e. flight number
		airplaneInfo.insert(pair<string, Airplane>(key, airplane)); // Save flight information into map
	}
	ifs01.close(); 

	// Initialize user information
	ifstream ifs02;
	ifs02.open("userInfo.txt", ios::in); // Open file
	// If file opening fails
	if (!ifs02.is_open()) {
		cout << "File opening failed!\a" << endl;
		exit(-1);
	}
	// If user information is not empty
	string info; // Temporarily store each customer information
	// Read customer information by line
	while (getline(ifs02, info)) {
		vector<string> separateInfo; // Store separate information
		separateInfo = split(info, " "); // Separate customer information
		Person person; // Store temporary customer information
		person.name = separateInfo[0]; // Deposit name
		person.age = separateInfo[1]; // Storage age
		person.gender = separateInfo[2]; // Storage gender
		person.idNum = separateInfo[3]; // Storage ID number
		person.myAirNum = separateInfo[4]; // Deposit flight number
		// Customer information storage
		string key = separateInfo[3].substr(13); // The last six digits of the ID card are the map index value key
		userInfo.insert(pair<string, Person>(key, person)); // Store customer information in map
	}
	ifs02.close();
}

/// <summary>
///Ticket selling
/// </summary>
void sellTickets() {
	// 1. Enter user information
	Person person; // Ticket customer
	// Enter name
	while (true) {
		cout << "Please enter your name:";
		cin >> person.name;
		// Judge whether the name is legal
		if (nameIsLegal(person.name)) {
			break;
		}
		cout << "The name is illegal, please re-enter!" << endl;
	}
	// Enter age
	while (true) {
		cout << "Please enter age:";
		cin >> person.age;
		// Judge whether the input age is in line with common sense
		if (stringToInt(person.age)  > 110 || stringToInt(person.age) < 0) {
			cout << "Illegal age, please re-enter!" << endl;
		}
		else {
			break;
		}
	}
	// Enter gender
	while (true) {
		cout << "Please enter gender:";
		cin >> person.gender;
		// Judge whether the input gender is legal
		if (person.gender == "male" || person.gender == "female") {
			break;
		}
		cout << "Illegal gender, please re-enter!" << endl;
	}
	// Enter ID number
	while (true) {
		cout << "Please enter your ID number:";
		cin >> person.idNum;
		// Judge whether the ID number is legal.
		if (idNumIsLegal(person.idNum)) {
			break;
		}
		cout << "The ID number is not valid. Please retype it." << endl;
	}
	// Enter flight number
	while (true) {
		cout << "Please enter flight number:";
		cin >> person.myAirNum;
		// Judge whether the flight number is legal, the flight exists and the number of people is not full
		if (person.myAirNum[0] == 'x' && person.myAirNum.length() == 4
			&& airplaneInfo.find(person.myAirNum) != airplaneInfo.end() 
			&& stringToInt(airplaneInfo[person.myAirNum].tickets) != 0) {
			// If the current flight is purchased, the number of tickets for the flight should be reduced by one
			int tickets = stringToInt(airplaneInfo[person.myAirNum].tickets); // Convert to shaping
			tickets--;  // The number of votes is reduced by one
			airplaneInfo[person.myAirNum].tickets = to_string(tickets); // Convert to string
			updateAirplaneFile(); // Update flight file 
			break;
		}
		cout << "The flight number is illegal or does not exist or the number of flights is full, please select again!" << endl;
	}

	// 2. User information is stored in userInfo
	string key = person.idNum.substr(13); // Get the corresponding key value of the user: the ID number is 6 bits.
	userInfo.insert(pair<string, Person>(key, person)); // Store user information in map

	// 3. Write new user information to file
	fstream fs;
	fs.open("userInfo.txt", ios::out | ios::app); // Open file
	// write file
	fs << person.name + " " << person.age + " "
		<< person.gender + " " << person.idNum + " "
		<< person.myAirNum + " " << endl;
	cout << "Ticket purchase succeeded!!" << endl;
	fs.close();
}

/// <summary>
///Display output user information
/// </summary>
void showUserInfo() {
	// Judge whether the user information is empty
	if (userInfo.empty()) {
		cout << "User information is empty!!" << endl;
		return;
	}
	// If the user information is not empty, start traversal
	map<string, Person>::iterator it; // iterator 
	for (it = userInfo.begin(); it != userInfo.end(); it++) {
		cout << "full name:" + it->second.name
			 << " Age:" + it->second.age
			 << " Gender:" + it->second.gender
			 << " ID number:" + it->second.idNum
			 << " flight number:" + it->second.myAirNum 
			 << " starting point:"  + airplaneInfo[it->second.myAirNum].startPoint
			 << " End:" + airplaneInfo[it->second.myAirNum].destination
			 << " Ticket Price:" + airplaneInfo[it->second.myAirNum].ticketPrice
			 << " Departure time:" + airplaneInfo[it->second.myAirNum].departureTime
			 << endl;
	}
}

/// <summary>
///Display and output flight information
/// </summary>
void showAirplaneInfo() {
	// If flight information is empty
	if (airplaneInfo.empty()) {
		cout << "Flight information is empty!" << endl;
		return;
	}
	// If the flight information is not empty, start traversal
	map<string, Airplane>::iterator it; // iterator 
	int i = 0;
	for (it = airplaneInfo.begin(); it != airplaneInfo.end(); it++) {
		cout << "flight number:" + it->second.airNum
			 << " starting point:" + it->second.startPoint
			 << " End:" + it->second.destination
			 << " Number of votes:" + it->second.tickets
			 << " Ticket Price:" + it->second.ticketPrice
			 << " Departure time:" + it->second.departureTime
			 << endl;
	}
}

/// <summary>
///Query user information
/// </summary>
/// <param name= "idNum" > query user ID number </param>
void selectUserInfo(string idNum) {
	string key = idNum.substr(13); // Get key value: ID number 6 after 6.
	// Judge whether the user information exists 
	if (userInfo.find(key) == userInfo.end()) {
		cout <<"The user does not exist!!" << endl;
		return ;
	}
	Person person = userInfo[key]; // Find user information through key
	// Output user information
	cout << "full name:" + person.name
		 << " Age:" + person.age
		 << " Gender:" + person.gender
		 << " ID number:" + person.idNum
		 << " flight number:" + person.myAirNum 
		 << " starting point:" + airplaneInfo[person.myAirNum].startPoint
		 << " End:" + airplaneInfo[person.myAirNum].destination
		 << " Ticket Price:" + airplaneInfo[person.myAirNum].ticketPrice
		 << " Departure time:" + airplaneInfo[person.myAirNum].departureTime
		 << endl;
}

/// <summary>
///Refund
/// </summary>
//<param name= "idNum" > refund ticket user ID number </param>
void refundTickets(string idNum) {
	// Determine whether the user exists
	string key = idNum.substr(13); 
	// If it doesn't exist
	if (userInfo.find(key) == userInfo.end()) {
		cout << "User information does not exist!" << endl;
		return;
	}
	// If yes, the number of tickets for this flight needs to be increased by one
	int tickets = stringToInt(airplaneInfo[userInfo[key].myAirNum].tickets); // String to integer
	tickets++; // Number of votes plus one
	airplaneInfo[userInfo[key].myAirNum].tickets = to_string(tickets); // Integer to string
	updateAirplaneFile(); // Update flight file 
	userInfo.erase(key); // Delete from user information

	// Delete the user information from the file
	clearFile("userInfo.txt"); // Empty file
	// Rewrite file
	fstream fs;
	fs.open("userInfo.txt", ios::out | ios::app); // Open file
	// Traverse and rewrite user information
	for (auto i : userInfo) {
		 fs << i.second.name + " "
			<< i.second.age + " "
			<< i.second.gender + " "
			<< i.second.idNum + " "
			<< i.second.myAirNum << endl;
	}
	fs.close();
	cout << "Refund succeeded!!" << endl;
}

/// <summary>
///Update flight file information
/// </summary>
void updateAirplaneFile() {
	// Remove from file
	clearFile("airplane.txt"); // Empty file
	// Rewrite file
	fstream fs;
	fs.open("airplane.txt", ios::out | ios::app); // Open file
	// Traverse and re write flight information
	for (auto i : airplaneInfo) {
		 fs << i.second.airNum + " "
			<< i.second.startPoint + " "
			<< i.second.destination + " "
			<< i.second.tickets + " "
			<< i.second.ticketPrice + " "
			<< i.second.departureTime + " "
			<< endl;
	}
	fs.close();
} 

/// <summary>
///String segmentation function
/// </summary>
///< param name = "STR" > required split string < / param >
///< param name = "delim" > segmentation criteria < / param >
///< returns > string array < / returns >
vector<string> split(const string& str, const string& delim) {
	vector<string> res; // An array that holds split strings
	if ("" == str) return res; // If the string is empty, it cannot be split

	// First convert the string to be cut from string type to char * type  
	char* strs = new char[str.length() + 1];  
	strcpy(strs, str.c_str());

	char* d = new char[delim.length() + 1];
	strcpy(d, delim.c_str()); // Convert delim to char * and assign it to d

	char* p = strtok(strs, d); // The first call points to the decomposition string
	while (p) {
		string s = p; // The split string is converted to string type  
		res.push_back(s); // Save to result array  
		p = strtok(NULL, d); // After each segmentation, the decomposition string is NULL
	}
	return res;
}

/// <summary>
//Judge whether the ID number is legal.
/// </summary>
/// <param name= "idNum" > ID number </param>
///< returns > legal is true, illegal is false < / returns >
bool idNumIsLegal(string idNum) {
	// Define a regular expression                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Rule of 18 digit ID number
	regex repPattern("^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$");
	// Declare matching result variables
	match_results<string::const_iterator> rerResult;
	// Match
	bool bValid = regex_match(idNum, rerResult, repPattern);
	if (bValid) {
		// Match successful
		//Cout "ID number format is legal!" endl;
		return true;
	}
	//Cout "the format of ID number is not legal!" endl;
	return false;
}

/// <summary>
///Judge whether the name is legal
/// </summary>
///< param name = "name" > name < / param >
///< returns > legal is true, illegal is false < / returns >
bool nameIsLegal(string name) {
	// Define a regular expression                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Rule of 18 digit ID number
	regex repPattern("^[\u4e00-\u9fa5]+(·[\u4e00-\u9fa5]+)*$");
	// Declare matching result variables
	match_results<string::const_iterator> rerResult;
	// Match
	bool bValid = regex_match(name, rerResult, repPattern);
	if (bValid) {
		// Match successful
		//Cout < < "the name format is legal!"<< endl;
		return true;
	}
	//Cout < < "illegal name format!"<< endl;
	return false;
}

/// <summary>
///Convert string type to int type
/// </summary>
///< param name = "STR" > string to be converted < / param >
///< returns > the converted integer of the string < / returns >
int stringToInt(string str) {
	// Determine whether the string is empty 
	if (str.empty()) {
		cout << "Data error, please check the file data!" << endl;
		return 0;
	}
    return stoi(str); // Convert string to integer
}

/// <summary>
///Empty file contents
/// </summary>
///< param name = "filename" > file name < / param >
void clearFile(const string fileName) {
	fstream file(fileName, ios::out);
}

Welcome your comments!

Topics: C++ data structure map