摘要:
在向量上调用clear()
似乎不足以清除它。
vector_full_of_stuff.clear();
我必须先叫clear()
,然后叫shrink_to_fit()
才能完全删除其中的所有数据。
vector_full_of_stuff.clear();
// AND THEN
vector_full_of_stuff.shrink_to_fit();
有什么作用?之所以成为问题,是因为当我在向量上调用data()
时,会包含我认为在代码前面调用clear()
时应该清除的内容。
其他详细信息:
我正在进行计算机网络分配,其中必须将PASV命令结果解析为IP和端口号。在解析以逗号分隔的虚拟PASV命令结果时,我注意到,如果我解析三位数后跟两位数字,那么我在调用data()
时就可以从上一次解析中获得第三位数,即使我不应该(?)因为我之前叫过clear()
。
例如。
PASV命令结果= 209,202,252,54,19,15
解析时,“ 252”中的“ 2”会延续到“ 19”中。
代码:
// this one actually deletes data
void splitString(string str, char delimiter, vector<string> * out) {
vector<char> word_buffer;
for (int i = 0; i < str.length(); ++i) {
if (str[i] == delimiter) {
out->push_back(word_buffer.data());
word_buffer.clear();
word_buffer.shrink_to_fit();
} else {
word_buffer.push_back(str[i]);
}
}
out->push_back(word_buffer.data());
word_buffer.clear();
}
//
// this one doesn't
// the only thing that's different about this one
// is that its missing shrink_to_fit()
void splitString(string str, char delimiter, vector<string> * out) {
vector<char> word_buffer;
for (int i = 0; i < str.length(); ++i) {
if (str[i] == delimiter) {
out->push_back(word_buffer.data());
word_buffer.clear();
// word_buffer.shrink_to_fit(); // need this to delete data
} else {
word_buffer.push_back(str[i]);
}
}
out->push_back(word_buffer.data());
word_buffer.clear();
}
//
// main driver code
int main() {
vector<string> user_input_tokens;
string port = "209,202,252,54,19,15";
splitString(port, ',', &user_input_tokens);
for (string str : user_input_tokens) {
cout << str << ".";
}
}
//
预期输出:
209.202.252.54.19.15.
实际输出:
209.202.252.542.192.152.
答案 0 :(得分:3)
向量的data()
方法返回指向向量在内存中分配的数组的原始指针。 clear()
会在需要时破坏该数组的 contents 并将向量的size()
设置为0,但不会重新分配数组本身,因此不会更改向量的{{1 }}。调用向量的capacity()
方法会重新分配数组,以便其shrink_to_fit()
与其数组capacity()
匹配(如果可能的话(size()
仅是建议性的,不能保证 做任何事情)。
此外,当单独从shrink_to_fit()
指针构造std::string
时,char数据需要以空值结尾,而您的数据不是。您需要在使用char*
之前将空终止符插入向量:
data()
否则,在构造字符串时,只需考虑向量的void splitString(const string &str, char delimiter, vector<string> * out) {
vector<char> word_buffer;
for (int i = 0; i < str.length(); ++i) {
if (str[i] == delimiter) {
word_buffer.push_back('\0');
out->push_back(word_buffer.data());
word_buffer.clear();
} else {
word_buffer.push_back(str[i]);
}
}
if (!word_buffer.empty()) {
word_buffer.push_back('\0')
out->push_back(word_buffer.data());
}
}
,就不需要空终止符:
size()
话虽这么说,还有其他方法可以完全不需要void splitString(const string &str, char delimiter, vector<string> * out) {
vector<char> word_buffer;
for (int i = 0; i < str.length(); ++i) {
if (str[i] == delimiter) {
out->push_back(string(word_buffer.data(), word_buffer.size()));
// alternatively:
// out->emplace_back(word_buffer.data(), word_buffer.size());
word_buffer.clear();
}
else {
word_buffer.push_back(str[i]);
}
}
if (!word_buffer.empty()) {
out->push_back(string(word_buffer.data(), word_buffer.size()));
// alternatively:
// out->emplace_back(word_buffer.data(), word_buffer.size());
}
}
向量来实现splitString()
函数,例如:
word_buffer
void splitString(const string &str, char delimiter, vector<string> * out) {
string::size_type start = 0, pos = str.find(delimiter);
while (pos != string::npos) {
out->push_back(str.substr(start, pos-start));
start = pos + 1;
pos = str.find(delimiter, start);
}
if (start < str.size()) {
if (start > 0) {
out->push_back(str.substr(start));
} else {
out->push_back(str);
}
}
}
但是,即使您想手动缓冲单词,void splitString(const string &str, char delimiter, vector<string> * out) {
istringstream iss(str);
string word;
while (getline(iss, word, delimiter))
out->push_back(std::move(word));
}
比std::string
更有意义,尤其是因为您正在输出std::vector<char>
值:
std::string