web-dev-qa-db-ja.com

std :: fstreamでテキストファイルを読み取るときに、デフォルト以外の区切り文字を使用するにはどうすればよいですか?

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

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

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

18
FrozenLand

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

#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を使用してストリームにそのロケールを使用させることです。

20
Jerry Coffin

あなたが使用することができます

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
    }
}
1
QuantumRipple