0

これはファイルの内容です:

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のみを使用してノードといくつかの基本的な文字列操作を保存する必要があります。

4

1 に答える 1

0

作成した関数(isSeparator)を変更し、新しい関数(isDigit)を追加しました。

bool isSeparator(const char c) {
    const string pattern = ".,;:\"~!#%^*()=+[]{}\\|<>?/";
    for (unsigned int i = 0; i < pattern.size(); i++) {
        if (pattern[i] == c)
            return true;
    }
    return false;
}

bool isDigit(const char c) {
    if ((int) c >= 0x30 && (int) c <= 0x39) return true;
    else return false;
}

新しい関数isDigitは、渡された文字が数字であるかどうかを判別するためのものです。正しい方法で単語を分離していることを確認するために、考えられるすべてのテストケースを収集しようとしました。これが私が検討したケースです。

word.12word.word
word.12.3word.word
word.word12.word
12.3.

私がコードを変更したロード関数の場合、あなたの役割は、私のコードのリストノードに挿入するコードを決定し、それをニーズに統合することです。変更されたロード関数は次のとおりです。

ifstream fin;
    fin.open("file.in");
    string line, word = "";
    list<Node> node;
    while (getline(fin, line)) {
        for (unsigned int i=0; i<line.size(); i++) {
            if ((line[i] == '\t' || line[i] == ' ' || isDigit(line[i])) && (line[i+1]=='.' && isDigit(line[i+2]))) {
                word += line[i];
                word += ".";
                i+=2;
                while (!isSeparator(line[i])) word += line[i++];
                i--;
            } else if (!isSeparator(line[i])) {
                word += line[i];
                if (i==line.size()-1) {
                    node.push_back(Node(word));
                    //cout << word << endl; for debugging
                    word.clear();
                }
            } else {
                if (word.size() > 0) {
                    node.push_back(Node(word));
                    //cout << word << endl; for debugging
                    word.clear();
                }
            }
        }
    }
    fin.close();

出力は次のとおりです。

word
12word
word
word
12.3word
word
word
word12
word
12.3

これらの文字列照合の問題を解決するために従わなければならない手順は次のとおりです。

1-最初に考えられるケースを特定します。私が提供したテストケースはそれを示していると思います。
2-可能なテストケース/入力に従ってifsステートメントの作成を開始します。
3-あなたのifを減らして冗長なものをグループ化してみてください。
4-最後に、それはすべてあなたの論理とあなたの思考の仕方に依存します。

幸運を :)

using namespace std;毎回std::を埋め込む代わりにステートメントを使用していることに注意してください。私が間違っている場合は訂正してください。

于 2012-04-29T08:38:52.190 に答える