这是本人在初学C/C++过程中自编程序,用到了关联容器map、动态内存分配new/delete、文件流的ifstream类和string类及getline、strtok_s函数,刚开始也是看了CSDN许多博文才弄明白,现在分享出来给大家参考。
1. 功能概述
1.1 功能效果
在txt文件中定义好注释和数据后,懒得在程序中再逐一定义变量名了,想直接使用。
1.2 使用方法
- 输入要求:英文名在前,中文注释在后,中间用空格或制表符隔开,劝你不要用中文作为名字,除非你的文件是用GJB2312编码;
- 读入结果:通过定义MapRow类对象,使数据读入内存中,再使用map将数据进行关联。
2. 注意事项
- 需要了解map的使用方法,简单的说通过map定义关联容器,保存键/值对,将键“映射”到值上,使用“map名[“键名”]”建立映射关系,“map名.at(“键名”)”使用映射关系;
- 便捷是有代价的,当你大量调用map,会花费很长时间;
- 通过C风格指针在堆中开辟空间,用析构函数来释放空间,但仍存在未清理的可能性,后续需要改进。
3. 详细代码
MapRow.h
/*
* Auther: sanfan66
* Date | Change
*--------------------------------------------
* 230926 | <record>: None→Version 0.00,Original finished
* | (describe): MapRow needs input-file with a header in front of the data
* | (describe): '\t'or' 'to separate the words
* | !warning!: ~MapRow may not called in some cases
*/
#pragma once
#include <fstream>//ifstream
#include <map>
#include <iostream>//cout
#include <string>//getline
#define EPS 1e-7
using namespace std;//map,string,ifstream
class MapRow {
public:
MapRow(const char *path, map<string, double>&map_name);
~MapRow();
int getNum(ifstream *file, const char *path);
double getData(ifstream *file, const char *path);
private:
int nHeader;
char **header_name;
double *lines_data;
};
MapRow.cpp
#include "MapRow.h"
MapRow::MapRow(const char *path, map<string, double>&map_name) {
/* 打开文件、读入行数、读取数据、赋值地址 */
ifstream file;
file.open(path, ios::in);
if (!file.is_open()) {
cout << path << "无法打开" << endl;
system("Pause");
exit(0);
}
getNum(&file, path);
header_name = new char*[nHeader];
for (int i = 0; i < nHeader; i++) {
header_name[i] = new char[100];
}
lines_data = new double[nHeader] {};
getData(&file, path);
for (int i = 0; i < nHeader; i++) {
map_name[header_name[i]] = lines_data[i];
}
file.close();
}
MapRow::~MapRow() {
/* 清理堆空间,new对应delete,new[]对应delete[] */
delete[] lines_data;
lines_data = nullptr;
for (int i = 0; i < nHeader; i++) {
delete[] header_name[i];
header_name[i] = nullptr;
}
delete[] header_name;
header_name = nullptr;
}
int MapRow::getNum(ifstream *file, const char *path) {
/* 获取行数 */
int n = 0, k = 0;
string one_line;
while (getline(*file, one_line)) {
for (unsigned i = 0;i<one_line.size();i++) {
if (one_line[i] - '0' > -EPS && one_line[i] - '9' < EPS) {
++n;
break;
}
}
}
nHeader = n;
if (n==0) {
cout << path << "无数据" << endl;
system("Pause");
exit(0);
}
return 0;
}
double MapRow::getData(ifstream *file, const char *path) {
/* 读取数据 */
file->clear();
file->seekg(0, ios::beg);
int i1 = 0, i2 = 0;
int indexLines = 0;
char *one_line_char = nullptr;
string one_line;
while (file->peek() != EOF) {
getline(*file, one_line);
char *next_word_ptr = nullptr;
one_line_char = strtok_s(&one_line[0], "\t ", &next_word_ptr);
if (one_line_char != NULL) {
if (one_line_char[0] - '0' > -EPS && one_line_char[0] - '9' < EPS) {
lines_data[i2] = atof(one_line_char);
++i2;
}
else {
if (!((one_line_char[0] - 'a' > -EPS && one_line_char[0] - 'z' < EPS) ||
(one_line_char[0] - 'A' > -EPS && one_line_char[0] - 'Z' < EPS))) {
cout << path << "第" << indexLines + 1 << "行表头不是字母" << endl;
system("Pause");
}
strcpy_s(header_name[i1], strlen(one_line_char) + 1, one_line_char);
++i1;
}
}
++indexLines;
}
if (i1!=i2) {
cout << path << "表头个数与数据个数不一致" << endl;
system("Pause");
exit(0);
}
return 0;
}