これはファイルの内容です:
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
要件は、テキスト ファイルから各行を読み取り、行から単語を抽出することです。新しい単語が検出されるたびに、プログラムは動的メモリからノードのインスタンスを割り当てて単語とそのカウントを格納し、それをリンク リストに挿入して、リストが常にソートされるようにする必要があります。見つかった単語がリストに既に存在する場合、その単語のカウントをインクリメントする必要があります。「。」について考える セパレーターの場合、. 文字の左側にスペース、タブ、改行、または数字があり、右側に数字がある場合、小数点として扱われ、単語の一部になります。それ以外の場合は、ピリオドおよび単語区切りとして扱われます。
単語: 一連の英字と数字、一重引用符、アンダースコア、およびハイフン文字で、1 つまたは複数の区切り文字のシーケンスで区切られています。区切り文字のリストについては、以下を参照してください。この割り当ての入力は、単語と整数と浮動小数点数で構成されます。一重引用符は常にアポストロフィとして機能し、単語の一部として扱う必要があります。したがって、ストリーマー、ストリーマー、ストリーマーズ、ストリーマーはすべて別個の単語である必要がありますが、「ストリーマー」とストリーマーはストリーマーという単語の 2 回の出現としてカウントする必要があります。
どうやら、私は何かを下に持っていますが、ピリオドを単語区切りとして扱うことにまだ行き詰まっています。誰かが私にいくつかのヒントを提案してもらえますか?
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のみを使用してノードといくつかの基本的な文字列操作を保存する必要があります。