【发布时间】:2019-06-01 16:07:04
【问题描述】:
请考虑这个 C++ 问题:
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
class ParseURL{
private:
int qualify; // 0 means we qualify
public:
string node;
string service;
bool primary;
bool health;
string epoch;
// methods
ParseURL(string URL);
~ParseURL();
};
ParseURL::ParseURL(string URL){
vector<string> g2 = {"node", "service", "primary", "health", "epoch"};
for (string tag : g2){
auto found = URL.find(tag);
if ( found != string::npos ){
auto cut_from = found + 1 + tag.size() ;
auto meh = URL.substr(cut_from, URL.substr(cut_from).find("&") );
// is there a way we can avoid these lines below?
if (tag.find("node",0) == 0){
this->node = meh;
} else if (tag.find("service",0) == 0 ){
this->service = meh;
} else if (tag.find("epoch",0) == 0) {
this->epoch = meh;
} else if (tag.find("health",0) == 0){
this->health = (meh == "OK");
} else if (tag.find("primary",0) == 0 ){
this->primary == (this->node == meh);
}
}
}
}
ParseURL::~ParseURL(){
cout << "Tearing Down the class\n";
}
int main(){
char req[] = "GET /register?node=hostrpi3&service=potatoservice&primary=node1&health=OK&epoch=1559345106 HTTP";
string Request = req;
Request = Request.substr(Request.find_first_of(" ") );
Request = Request.substr(0, Request.find(" HTTP"));
ParseURL *a = new ParseURL(Request);
cout.width(12);
cout << "a->node: " << a->node << endl;
cout.width(12);
cout << "a->service: " << a->service << endl;
cout.width(12);
cout << "a->epoch: " << a->epoch << endl;
cout.width(12);
cout << "a->health: " << a->health << endl;
cout.width(12);
cout << "a->primary: " << a->primary << endl;
delete(a);
return 0;
}
我需要基于 URL 查询字符串来表示一个对象,我需要的标签在向量 g2 中表示,如您所见,我从这些标签中创建了 ParseURL 的数据成员。
o/p 看起来像:
a->node: hostrpi3
a->service: potatoservice
a->epoch: 1559345106
a->health: 1
a->primary: 0
Tearing Down the class
虽然这个版本有效,但感觉可以改进很多。尽管这一切都在 Vector 中,但我反复为每个属性执行 tag.find。一定有更好的方法,我希望。你能指出正确的方向吗?谢谢!
编辑 1
谢谢,我按照建议更新了构造函数:
ParseURL::ParseURL(string URL){
char tags[10][100] = {"node", "service", "primary", "health", "epoch"};
int i = 0;
for (auto tag : tags){
auto found = URL.find(tag);
if ( found != string::npos ){
auto cut_from = found + 1 + strlen(tag);
auto tag_info = URL.substr(cut_from, URL.substr(cut_from).find("&") );
switch (i){
case 0:
this->node = tag_info;
break;
case 1:
this->service = tag_info;
break;
case 2:
this->primary = (this->node == tag_info);
break;
case 3:
this->health = (tag_info == "OK");
break;
case 4:
this->epoch = tag_info;
break;
}
}
i++;
}
}
例如,bash 提供了变量的间接引用——也就是说,一个变量可能包含另一个变量的名称:
$ cat indirect.sh
#!/bin/bash
values="value1 value2"
value1="this is value1"
value2="this is value2"
for i in $values; do
echo "$i has value ${!i}"
done
$ ./indirect.sh
value1 has value this is value1
value2 has value this is value2
我希望在这样的案例中存在类似的情况,但是,我在这里学到了宝贵的经验。谢谢!
【问题讨论】:
-
整个
for循环与if语句不是适得其反吗?meh可以更好地命名。 -
if (tag.find("node",0) == 0)应该改为if (tag == "node"),对于其他标签检查也是如此。但是,我建议在正在处理的tag的index 上使用switch:for (size_t i = 0; i < g2.size(); ++i) { string tag = g2[i]; ... switch (i) { case 0: this->node = meh; ... } }。或者,完全摆脱单个类数据成员并使用单个map<string, string>或map<string, variant>键控在tag,或string[5]或variant[5]由tag索引的数组向量 -
附带说明,当静态
string[5]就足够时,使用vector代替g2是多余的 -
@RemyLebeau,谢谢。你为什么说向量与字符串相比是多余的 - 这是部落知识,还是在适当的容器选择上存在常见问题解答?
-
@struggling_learner 您使用的是固定值数组,但
vector是动态数组。您可以在编译时静态设置固定数组,而不是在运行时动态分配它。这就是为什么我说在这种情况下使用vector是多余的。此外,在您的更新中,char[10][100]过度分配,char[5][8]就足够了。至少,数组的第 1 维需要匹配数组中字符串的数量,所以 10 对于只有 5 个值来说太多了,尤其是在使用基于范围的for循环时。
标签: c++ datamember