-
Notifications
You must be signed in to change notification settings - Fork 0
/
read_cfg.cpp
148 lines (136 loc) · 3.63 KB
/
read_cfg.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include "read_cfg.h"
#include <fstream>
#include <iostream>
using namespace std;
/*desc:
这里通过map实现了cfg文件中kv对的存取,方便操作。
注意这里的文件读取的操作,已经getline等相关函数。
注意整体的逻辑: 打开文件、从上到下获取行、注释忽略、建立map、存取kv对,这样,我们就可以得到cfg文件中所有有用的参数了。
最后FindInConfig函数中,我们将找到的kv输出,当然,在使用过程中,我们可以直接获取进行进一步的计算工作。
*/
bool IsSpace(char c)
{
if (c == ' ' || c == '\t')
{
return true;
}
else
{
return false;
}
}
bool IsCommentChar(char c)
{
if (c == COMMENT_CHAR)
{
return true;
}
else
{
return false;
}
}
// trim函数的作用是把一个字符串左边和右边的空格去掉,即为trim
void Trim(string & str) // 引用传参,这样在函数中修改该参数也会修改相应的变量
{
if (str.empty())
{
return;
}
int i, start_pos, end_pos;
for (i = 0; i < str.size(); i++)
{
if (!IsSpace(str[i]))
{
break;//跳出
}
}
if (i == str.size())//如果该行全是空格,则该行最后一个字符为"\n",此时i == str.size()
{
str = "";
return;
}
start_pos = i; // 获取到非空格的初始位置
for (i = str.size() - 1; i >= 0; i--)
{
if (!IsSpace(str[i]))
{
break;
}
}
end_pos = i;
str = str.substr(start_pos, end_pos - start_pos + 1);
}
bool AnalyseLine(const string & line, string & key, string & value) // 分析一行,如果是注释行,则不处理,如果是k-v行,则提取出key-value值。
{
if (line.empty())
{
return false;
}
int start_pos = 0, end_pos = line.size() - 1, pos;
if ((pos = line.find(COMMENT_CHAR)) != -1)
{
if (0 == pos)
{
return false; // 如果一行的开头是#,说明是注释,则 不需要
}
end_pos = pos - 1; // 可能是注释在k-v后的情况
}
string new_line = line.substr(start_pos, end_pos - start_pos + 1); // 删掉后半部分的注释 FIX_ME: 这里应该是减错了吧
// 下面pos的赋值时必要的,这样,就可在后面得到Key和value值了。
if ((pos = new_line.find("=")) == -1) //说明前面没有 = 号
{
return false;
}
key = new_line.substr(0, pos); // 获得key
value = new_line.substr(pos + 1, end_pos + 1 - (pos + 1)); // 获得value
Trim(key);
if (key.empty())
{
return false;
}
Trim(value); // 因为这里的key和value都是引用传递,可以直接被修改,所以不用返回
return true;
}
// 读取一个cfg文件并保存到map中,map中的key和value都是string类型的。
bool ReadConfig(const string & filename, map<string, string> & m)
{
m.clear(); // 删除map容器中的所有k-v对
ifstream infile(filename.c_str());
if (!infile)
{
cout << "file open failed!" << endl; // 文件打开失败,返回错误信息。
return false;
}
string line, key, value; // 为了后续保存kv对
while (getline(infile, line))
{
if (AnalyseLine(line, key, value))
{
m[key] = value; // 保存到map容器中的方法。
}
}
infile.close(); // 当读取完之后,就要关闭这个文件。
return true;
}
void PrintConfig(const map<string, string> & m)
{
map<string, string>::const_iterator mite;
for (mite = m.begin(); mite != m.end(); mite++)
{
cout << mite->first << "=" << mite->second << endl;
}
}
string FindInConfig(map<string, string> m, string key, string defaultVal) // 注意:之前用的一直都是string类型,所以这里用的也是string key,而不是char key。
{
map<string, string>::iterator it;
it = m.find(key);
if (it == m.end())
{
return defaultVal;
}
else
{
return it->second;
}
}