我正在尝试创建一个按文件长度排列的文件列表。为此,我试图使用std :: set和自定义比较器。
class Longer {
public:
bool operator() (const string& a, const string& b)
{ return a.size() > b.size();}
};
set<string, Longer> make_dictionary (const string& ifile){
// produces a map of words in 'ifile' sorted by their length
ifstream ifs {ifile};
if (!ifs) throw runtime_error ("couldn't open file for reading");
string word;
set<string, Longer> words;
while (ifs >> word){
strip(word);
tolower(word);
words.insert(word);
}
remove_plurals(words);
if (ifs.eof()){
return words;
}
else
throw runtime_error ("input failed");
}
由此,我希望文件中所有单词的列表按其长度排列。相反,我得到一个非常短的列表,输入中出现的每个长度只有一个单词:
polynomially-decidable
complexity-theoretic
linearly-decidable
lexicographically
alternating-time
finite-variable
newenvironment
documentclass
binoppenalty
investigate
usepackage
corollary
latexsym
article
remark
logic
12pt
box
on
a
知道这里发生了什么?
答案 0 :(得分:3)
使用比较器,等长字是等效的,并且您不能在一组中有重复的等效条目。
要保持多个单词,您应该修改比较器,以便在长度相同的情况下执行词典比较。
答案 1 :(得分:0)
您的比较器仅按长度进行比较,这意味着同等大小但不同的字符串被std::set
视为等效。 (std::set
如果a < b
和b < a
都不为真,则<
同等对待它们,std::tuple
是您的自定义比较函数。)
这意味着您的比较器也应该考虑字符串内容以避免这种情况。此处的关键字是词典比较,这意味着您可以考虑多个比较条件。第一个标准是你的字符串长度,第二个标准是字符串本身。编写字典比较的一种简单方法是使用operator<
,它提供了一个比较运算符,通过重载operator>
来对组件进行字典比较。
让你的&#34;反向&#34;您使用operator<
编写的长度排序与常用的a.size() > b.size()
兼容,只需取字符串的负大小,即首先将-a.size() < -b.size()
重写为<
,并且然后将字符串本身组合成元组,最后将元组与class Longer {
public:
bool operator() (const string& a, const string& b)
{
return std::make_tuple(-a.size(), a )
< std::make_tuple(-b.size(), b );
// ^^^^^^^^^ ^^^
// first second
// criterion criterion
}
};
进行比较:
{{1}}