这是文件的内容:
12.34.
.3
3..3
.3.4
..8
.this
test.this
test.12.34
test1.this
test1.12.34
这是预期的输出:
COUNT | WORD
------+------
1 | .3
1 | .3.4
2 | 12.34
2 | 3
1 | 8
2 | test
1 | test1
1 | test1.12.34
3 | this
要求是从文本文件中读取每一行,然后从行中提取单词。每当遇到一个新单词时,程序应该从动态内存中分配一个节点实例来包含该单词及其计数,并将其插入到一个链表中,以便该列表始终是排序的。如果遇到的单词已经存在于列表中,那么该单词的计数应该增加。考虑到'。分隔符,如果 . 字符在左边有一个空格、制表符、换行符或数字,在右边有一个数字,那么它被视为小数点,因此是单词的一部分。否则,它将被视为句号和单词分隔符。
单词:是由一个或多个分隔符序列分隔的字母和数字字符、单引号、下划线和连字符的序列。请参阅下面的分隔符列表。此分配的输入将由单词、整数和浮点数组成。单引号字符将始终充当撇号,并应被视为单词的一部分。因此,streamer、streamers、streamer's 和 streamers' 都应该是不同的词,但是“streamers”和 streamers 应该算作词 streamers 的两次出现。
显然,我在下面得到了一些东西,但我仍然坚持将句点视为单词分隔符。谁能给我一些提示?
bool isSeparator(const char c) {
if (std::isspace(c)) return true;
const std::string pattern = ",;:\"~!#%^*()=+[]{}\\|<>?/";
for (unsigned int i = 0; i < pattern.size(); i++) {
if (pattern[i] == c)
return true;
}
return false;
}
void load(std::list<Node> &nodes, const char *file) {
std::ifstream fin;
std::string line = "";
std::string word = "";
fin.open(file);
while (std::getline(fin, line)) {
for (unsigned int i = 0; i < line.size(); i++) {
if (isSeparator(line[i]) || i == (line.size() - 1)) {
if (word.find('.') < word.size()) { // if there is a '.' in a word
if (word.find('.') == word.size() - 1) { // if '.' at the end of word
word.erase(word.find('.'), 1); // remove '.' in any case
}
}
if (word.size() != 0) {
nodes.push_back(Node(word));
word.clear();
}
} else {
word += line[i];
}
}
}
fin.close();
}
我刚开始使用 c++,因此,分配只需要使用 std::list 来存储节点和一些基本的字符串操作。