为什么这段代码错了?我是否遗漏了有关delete
和delete[]
void remove_stopwords(char** strings, int* length)
{
char** strings_new = new char*[*length];
int length_new = 0;
for(int i=0; i<*length; i++) {
if(is_common_keyword(strings[i]) == 0) {
strings_new[length_new] = strings[i];
length_new++;
}
else {
delete strings[i];
strings[i] = nullptr;
}
}
delete[] strings;
strings = new char*[length_new];
for(int i=0; i<length_new; i++) {
strings[i] = strings_new[i];
}
delete[] strings_new;
*length = length_new;
}
解释:这段代码应该采用C风格的字符串数组并删除它们的一些特定字符串;使用new []创建C样式字符串数组,并使用new创建每个C样式字符串。代码的结果是没有单词被取消,但数组只是被切片。
答案 0 :(得分:6)
我在所显示的代码中使用new[]
或delete[]
时未发现任何问题。
不,等等。
我看到了lot¹的问题,但您的意图很明确,代码似乎正在按照您的意愿行事。
我注意到的唯一逻辑问题是你通过值传递strings
(它是char**
并在函数中重新分配它不会影响包含指针的调用者变量)。将签名更改为
void remove_stopwords(char**& strings, int* length)
所以传递引用而不是修复它。
(1)如果可能,使用std::vector<const char *>
似乎更合乎逻辑,甚至更好std::vector<std::string>
,它将负责所有分配和解除分配。
答案 1 :(得分:2)
每个C风格的字符串都是使用new创建的。
我怀疑这是你的问题 - C样式字符串是char
数组,因此您无法使用new
轻松创建它们,您需要使用new[]
。这意味着您需要使用delete[]
。
答案 2 :(得分:1)
正如@ 6502所指出的那样,你的基本问题非常简单:你正在传递一个char **
,并试图修改它(而不是它所指向的)。
您将其用作动态分配的字符串数组,因此您正在修改的只是传递给函数的指针的副本。由于您(显然)希望函数修改传递给它的内容,因此您需要传递char ***
(呃!)或char **&
(仍然非常糟糕)。
你真的应该使用vector<std::string>
来获取数据。至少在我看来,删除停用词的代码应该写成通用算法,这是一般顺序:
template <typename InIt, typename OutIt>
void remove_stop_words(InIt b, InIt e, OutIt d) {
std::remove_copy_if(b, e, d,
[](std:string const &s) { is_stop_word(s); });
}
有了这个,调用代码看起来像这样:
// read input
std::vector<std::string> raw_input { std::istream_iterator<std::string>(infile),
std::istream_iterator<std::string>() };
// Filter out stop words:
std::vector<std::string> filtered_words;
remove_stop_words(raw_input.begin(), raw_input.end(),
std::back_inserter(filtered_words));
但是,在这种情况下,您根本不需要将原始输入字存储到矢量中。您可以将istream_iterator直接传递给remove_stop_words
,并让它产生所需的结果:
std::ifstream in("raw_input.txt");
std::vector<std::string> filtered_words;
remove_stop_words(std::istream_iterator<std::string>(in),
std::istream_iterator<std::string>(),
std::back_inserter(filtered_words));
另外,您也可以考虑使用Boost filter_iterator。这将允许您在读取数据时在迭代器中进行过滤,而不是在应用于迭代器的算法中进行过滤。