18

私の C++ コードでは、テキスト ファイル (*.txt) から読み取り、すべてのエントリをトークン化したいと考えています。より具体的には、「format」、「stack」、「Jason」、「europe」など、ファイルから個々の単語を読み取れるようにしたいと考えています。

このタスクを実行するために を使用することを選択しましたが、使用したい区切り文字 (スペース、 、ハイフン、さらには「マクドナルド」のようなアポストロフィ) をfstream区切り文字に設定する方法がわかりません。\nスペースと\nデフォルトの区切り文字を考えましたが、ハイフンはそうではありませんが、ファイルを解析するときに「何とか何とか xxx animal--cat」の単語を単に「何とか」として取得できるように、それらを区切り文字として扱いたいと考えています。何とか」、「xxx」、「動物」、「猫」。

つまり、「stack-overflow」、「you're」など\nから 2 つの文字列を取得できるようにしたいのですが、同時に区切り記号として維持およびスペースできるようにしたいと考えています。

4

2 に答える 2

24

istream は「空白」を区切り文字として扱います。ロケールを使用して、どの文字が空白であるかを伝えます。facetロケールには、文字タイプを分類する ctype が含まれています。このようなファセットは次のようになります。

#include <locale>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <sstream>

class my_ctype : public
std::ctype<char>
{
    mask my_table[table_size];
public:
    my_ctype(size_t refs = 0)  
        : std::ctype<char>(&my_table[0], false, refs)
    {
        std::copy_n(classic_table(), table_size, my_table);
        my_table['-'] = (mask)space;
        my_table['\''] = (mask)space;
    }
};

そして、それが動作することを示す小さなテスト プログラム:

int main() {
    std::istringstream input("This is some input from McDonald's and Burger-King.");
    std::locale x(std::locale::classic(), new my_ctype);
    input.imbue(x);

    std::copy(std::istream_iterator<std::string>(input),
        std::istream_iterator<std::string>(),
        std::ostream_iterator<std::string>(std::cout, "\n"));

    return 0;
}

結果:

This
is
some
input
from
McDonald
s
and
Burger
King.

istream_iterator<string>>>ストリームから個々の文字列を読み取るために使用するため、それらを直接使用しても同じ結果が得られるはずです。含める必要があるのは、ロケールの作成とimbue、ストリームでそのロケールを使用するための使用です。

于 2012-04-29T22:10:01.770 に答える
2

使用できます

istream::getline(char* buffer, steamsize maxchars, char delim)

ただし、これは単一の区切り文字のみをサポートします。異なる区切り文字の行をさらに分割するには、次を使用できます。

char* strtok(char* inString, const char* delims)  

複数のデリメータが必要です。strtokを使用するときは、最初にバッファのアドレスを渡すだけで済みます。その後はnullを渡すだけで、最後に与えられたトークンの次のトークンが与えられ、ない場合はnullポインタが返されます。もっと。

編集:特定の実装は次のようになります

char buffer[120]; //this size is dependent on what you expect the file to contain
while (!myIstream.eofbit) //I may have forgotten the exact syntax of the end bit
{
    myIstream.getline(buffer, 120); //using default delimiter of \n
    char* tokBuffer;
    tokBuffer = strtok(buffer, "'- ");
    while (tokBuffer != null) {
        cout << "token is: " << tokBuffer << "\n";
        tokBuffer = strtok(null, "'- "); //I don't need to pass in the buffer again because it remembers the first time I called it
    }
}
于 2012-04-29T21:48:57.660 に答える