缘由:受朋友之托帮忙开发,而后演变成一个自娱自乐的项目
不过能够一天开发出来并且push到github上也算是一种进步啦
项目:读取txt文件之后,输入省份 / 简称 / 城市 / 区号 / 邮政编码, 能输出全部对应数据
小花哨:使用map实现logn级别的相应
效果图:
source code:
City.h:
#pragma once
#ifndef CITY_H_
#define CITY_H_
#include <string>
class city {
private:
std::string province; // 省份
std::string abbreviation; // 简称
std::string cityName; // 城市名称
int zoneDiscription; // 区号
int postalCode; // 邮政编码
public:
// 对类进行初始化
city();
city(std::string &p, std::string &a, std::string &c, int &z, int &po) :
province(p), abbreviation(a), cityName(c), zoneDiscription(z), postalCode(po) {}
// 相应类成员的构造函数
void setProvince(std::string & p);
void setAbbreviation(std::string & a);
void setCityName(std::string & c);
void setZoneDiscription(int & z);
void setPostalCode(int & po);
// 为了达到数据封装目的,提供接口函数实现对类成员的访问
std::string getProvince();
std::string getAbbreviation();
std::string getCityName();
int getZoneDiscription();
int getPostalCode();
};
#endif
City.cpp:
#pragma once
#ifndef CITY_CPP_
#define CITY_CPP_
#include "City.h"
city::city() {
province = abbreviation = cityName = " ";
zoneDiscription = postalCode = 0;
}
// 初始化类成员
void city::setProvince(std::string& p) { province = p; }
void city::setAbbreviation(std::string& a) { abbreviation = a; }
void city::setCityName(std::string& c) { cityName = c; }
void city::setZoneDiscription(int& z) { zoneDiscription = z; }
void city::setPostalCode(int& po) { postalCode = po; }
std::string city::getProvince() { return province; }
std::string city::getAbbreviation() { return abbreviation; }
std::string city::getCityName() { return cityName; }
int city::getZoneDiscription() { return zoneDiscription; }
int city::getPostalCode() { return postalCode; }
#endif
Load.cpp:
#pragma once
#ifndef LOAD_H_
#define LOAD_H_
#include <iostream>
#include <fstream>
#include <map>
using namespace std;
extern city* allCity = nullptr;
map<std::string, int> corProvince;
map<std::string, int> corAbbreviation;
map<std::string, int> corCityName;
map<int, int> corZoneDiscription;
map<int, int> corPostalCode;
// 功能:提取字符串中的数字
// 参数:字符串
// 返回:int类型数字
int transNum(string& s) {
// 例:"区号:01"
// 第一步实现数字部分的截断,即提取ASCii码形式的01
// 第二步再将ASCii码形式的数字01转换为int类型的数字01
// 第一步利用字符串的substr()函数对字符串进行截断
// 由于中英文字符不同的缘故,所以截取时长度要+ 2
string temp;
size_t pos = s.find(":");
temp = s.substr(pos + 2);
// 第二步对每个字符进行处理转换为数字形式
int ans = 0;
int sub = 0; // 标记temp的下标
int digit = 0; // 标记每个字符转化为数字的形式
while (sub + 1 <= temp.length()) {
digit = temp[sub++] - '0';
ans = ans * 10 + digit;
}
return ans;
}
// 功能:提取字符串中所需要的有用字符
// 参数:字符串
// 返回:字符串
string transString(string& s) {
string temp = " "; string ans = " ";
size_t pos = s.find(":");
temp = s.substr(pos + 2);
return temp;
}
// 功能:统计文本的行数
// 参数:ifstream对象
// 返回:文本行数
int lineCount(ifstream& temp) {
char c;
int count = 0;
while (temp.get(c)) {
if (c == '\n')
count++;
}
return count + 1; // txt文件最后一行没有'\n',所以统计时要+ 1
}
// 功能:将文本数据存储到allCity类指针所指向的内存
// 参数:ifstream对象
// 返回:void
void readData(ifstream& temp) {
// 获取文本行数并分配内存
int totalLines = lineCount(temp);
allCity = new city[totalLines];
temp.clear(); // 由于统计了行数,使文件指针指向了文件末尾,首先清除文件流状态
temp.seekg(0, ios::beg); // 其次回到文件的起始位置
// 逐步读取数据并存储
std::string s = " "; int occa = 0; int sub = 0;
while (!temp.eof()) {
// EOF是一个宏,它代表了-1这个值,如果在文件当中读到了0xff或者到了文件末尾,
// 文件结构指针里面的flags字节的_F_EOF位都会被置为1,这一位被置为1,库函数就会认为到了文件末尾了。
// 函数feof()其实是一个类函数宏,这个宏就是通过把文件结构指针的flags字节跟_F_EOF进行与运算来检测_F_EOF是否为1,并判断是否到了文件末尾的。
temp >> s; s = transString(s); corProvince[s] = sub; allCity[sub].setProvince(s);
temp >> s; s = transString(s); corAbbreviation[s] = sub; allCity[sub].setAbbreviation(s);
temp >> s; s = transString(s); corCityName[s] = sub; allCity[sub].setCityName(s);
// 提取字符串中的数字并进行存储
temp >> s; occa = transNum(s); corZoneDiscription[occa] = sub; allCity[sub].setZoneDiscription(occa);
temp >> s; occa = transNum(s); corPostalCode[occa] = sub; allCity[sub].setPostalCode(occa);
sub++;
}
}
// 功能:实现对以txt形式存储的文件,读取文本数据并存储
// 参数:void
// 返回:void
void loadTxt() {
ifstream fin;
// 对文件是否成功打开进行判断
fin.open("D:/Temp.txt", ios::in);
if (!fin) {
cerr << "Error : fail to open the file." << endl;
exit(1);
}
readData(fin);
fin.close();
}
#endif
Test.cpp:
#include "City.h"
#include "Load.cpp" // 实现对txt文件的读取
#include <iostream>
using namespace std;
void searchInterface();
void Init() {
// 注意:map不能成为city本身的数据成员,否则形成会对自身的循环调用
corProvince.clear();
corAbbreviation.clear();
corCityName.clear();
corZoneDiscription.clear();
corPostalCode.clear();
}
int main() {
Init(); // Init()与loadTxt()的先后顺序是重要的,否则所有的map映射都只能映射到第一条数据
loadTxt();
searchInterface();
return 0;
}
void print(int sub) {
cout << endl;
cout << "省份:\t" << allCity[sub].getProvince() << endl
<< "简称:\t" << allCity[sub].getAbbreviation() << endl
<< "城市:\t" << allCity[sub].getCityName() << endl
<< "区号:\t" << allCity[sub].getZoneDiscription() << endl
<< "邮政编码:\t" << allCity[sub].getPostalCode() << endl;
return;
}
// 交互界面的设计
void searchInterface() {
cout << "Welcome to search system!" << endl
<< "Dear user, you can choose and input one way to search the information you need." << endl
<< "1.\tSearch by province." << endl
<< "2.\tSearch by abbreviation." << endl
<< "3.\tSearch by city" << endl
<< "4.\tSearch by zone discription." << endl
<< "5.\tSearch by postal code." << endl
<< "$ ";
string s;
while (1) {
getline(cin, s); cout << endl;
if (s == "Search by province") {
cout << "Please input the province:" << endl
<< "$ ";
string province; getline(cin, province);
print(corProvince[province]);
break;
}
if (s == "Search by abbreviation") {
cout << "Please input the abbreviation:" << endl
<< "$ ";
string abbreviation; getline(cin, abbreviation);
print(corAbbreviation[abbreviation]);
break;
}
if (s == "Search by city") {
cout << "Please input the city:" << endl
<< "$ ";
string city; getline(cin, city);
print(corCityName[city]);
break;
}
if (s == "Search by zone discription") {
cout << "Please input the zone discription:" << endl
<< "$ ";
int zoneDiscription; cin >> zoneDiscription;
print(corZoneDiscription[zoneDiscription]);
break;
}
if (s == "Search by postal code") {
cout << "Please input the postal code:" << endl
<< "$ ";
int postalCode; cin >> postalCode;
print(corPostalCode[postalCode]);
break;
}
// 如果输入了均不符合的语句,那么抛出异常并重新输入
if (s != "Search by province" &&
s != "Search by abbreviation" &&
s != "Search by city" &&
s != "Search by zone discription" &&
s != "Search by postal code") {
cerr << "Error : Fail to search. Please input again.";
cout << endl << "$ ";
}
}
return;
}