web-dev-qa-db-ja.com

C ++ファイルを1行ずつ読み取り、区切り文字を使用して各行を分割します

Txtファイルを1行ずつ読み取り、各行を読み取った後、タブ「\ t」に従って行を分割し、各部分を構造体の要素に追加します。

私の構造体は1 * charと2 * intです

struct myStruct
{
    char chr;
    int v1;
    int v2;
}

chrには複数の文字を含めることができます。

行は次のようになります。

randomstring TAB number TAB number NL
20
sikas

試してください:
注:chrに複数の文字を含めることができる場合は、文字列を使用してそれを表します。

std::ifstream file("plop");
std::string   line;

while(std::getline(file, line))
{
    std::stringstream   linestream(line);
    std::string         data;
    int                 val1;
    int                 val2;

    // If you have truly tab delimited data use getline() with third parameter.
    // If your data is just white space separated data
    // then the operator >> will do (it reads a space separated Word into a string).
    std::getline(linestream, data, '\t');  // read up-to the first tab (discard tab).

    // Read the integers using the operator >>
    linestream >> val1 >> val2;
}
28
Martin York

この構造体をCでも使用するつもりがない限り、目的のchar *をstd :: stringに置き換えます。

次に、ストリームから読み取ることができるように、次の関数を作成します。

std::istream & operator>>( std::istream & is, myStruct & my )
{
    if( std::getline(is, my.str, '\t') )
       return is >> my.v1 >> my.v2;
}

strをstd :: stringメンバーとして使用します。これは、最初の区切り文字としてタブを使用して、次の2つの整数の前に空白区切り文字を使用して、構造体に書き込みます。 (タブを強制的に使用できます)。

行ごとに読み取るには、これらの読み取りを続けるか、最初に行を読み取って文字列にし、次に文字列をistringstreamに入れて上記を呼び出します。

失敗した読み取りの処理方法を決定する必要があります。上記の読み取りに失敗すると、ストリームは失敗状態のままになります。

3
CashCow
std::ifstream in("fname");
while(in){
    std::string line;
    std::getline(in,line);
    size_t lasttab=line.find_last_of('\t');
    size_t firsttab=line.find_last_of('\t',lasttab-1);
    mystruct data;
    data.chr=line.substr(0,firsttab).c_str();
    data.v1=atoi(line.substr(firsttab,lasttab).c_str());
    data.v2=atoi(line.substr(lasttab).c_str());
}
2
flownt

ここでのいくつかの提案に従うのは難しいので、タブで区切られたファイルに構造体の入力演算子と出力演算子の両方をオーバーロードする完全な例を投稿しています。おまけとして、stdinまたはコマンド引数を介して提供されたファイルのいずれかから入力を取得します。

これは、演算子のセマンティクスを順守している間と同じくらい簡単だと思います。


pairwise.h

#ifndef PAIRWISE_VALUE
#define PAIRWISE_VALUE

#include <string>
#include <iostream>

struct PairwiseValue
{
    std::string labelA;
    std::string labelB;
    float value;
};

std::ostream& operator<<(std::ostream& os, const PairwiseValue& p);

std::istream& operator>>(std::istream& is, PairwiseValue& p);

#endif

pairwise.cc

#include "pairwise.h"

std::ostream& operator<<(std::ostream& os, const PairwiseValue& p)
{
    os << p.labelA << '\t' << p.labelB << '\t' << p.value << std::endl;
    return os;
}

std::istream& operator>>(std::istream& is, PairwiseValue& p)
{
    PairwiseValue pv;

    if ((is >> pv.labelA >> pv.labelB >> pv.value))
    {
        p = pv;
    }

    return is;
}

test.cc

#include <fstream>
#include "pairwise.h"

int main(const int argc, const char* argv[])
{
    std::ios_base::sync_with_stdio(false); // disable synch with stdio (enables input buffering)

    std::string ifilename;
    if (argc == 2)
    {
        ifilename = argv[1];
    }

    const bool use_stdin = ifilename.empty();
    std::ifstream ifs;
    if (!use_stdin)
    {
        ifs.open(ifilename);

        if (!ifs)
        {
            std::cerr << "Error opening input file: " << ifilename << std::endl;
            return 1;
        }
    }

    std::istream& is = ifs.is_open() ? static_cast<std::istream&>(ifs) : std::cin;

    PairwiseValue pv;

    while (is >> pv)
    {
        std::cout << pv;
    }

    return 0;
}

コンパイル

g++ -c pairwise.cc test.cc
g++ -o test pairwise.o test.o

使用法

./test myvector.tsv
cat myvector.tsv | ./test
0
vallismortis