1

6テキスト ファイルを解析し、情報の一部をオブジェクトの配列にフィードするプログラムを作成しようとしています。私にとっての問題は、テキスト ファイルの処理方法を理解するのに問題があることです。最初に行う必要があるのは、各エントリの文字数を数えるコードを書くことだと言われました。txtファイルの形式は次のとおりです。

"thing1","thing2","thing3","thing4","thing5","thing6"

これは私のコードの現在のバージョンです:

#include<iostream>
#include<string>
#include<fstream>
#include<cstring>

using namespace std;

int main()
{
ifstream myFile("Book List.txt");

while(myFile.good())
{
    string line;

    getline(myFile, line);

    char *sArr = new char[line.length() + 1];
    strcpy(sArr, line.c_str());

    char *sPtr;

    sPtr = strtok(sArr, " ");

    while(sPtr != NULL)
    {
        cout << strlen(sPtr) << " ";
        sPtr = strtok(NULL, " ");
    }
    cout  << endl;
}
myFile.close();
return 0;
}

ですから、今私にとって難しいことが 2 つあります。

1) 区切り記号はどのように処理すればよいですか?

2) 各行の最初の引用符を「スキップ」するにはどうすればよいですか?

4

3 に答える 3

1

まず、strtok回避できる場合は使用しないでください (ここでは簡単に使用できます。また、find一連の関数の使用を回避することもできます)。

行全体を読み取ってから解析する場合:

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

// defines a new ctype that treats commas as whitespace
struct csv_reader : std::ctype<char>
{
    csv_reader() : std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());
        rc['\n'] = std::ctype_base::space;
        rc[','] = std::ctype_base::space;
        return &rc[0];
    }
};

int main()
{
    std::ifstream fin("yourFile.txt");
    std::string line;
    csv_reader csv;
    std::vector<std::vector<std::string>> values;
    while (std::getline(fin, line))
    {
        istringstream iss(line);
        iss.imbue(std::locale(std::locale(), csv));
        std::vector<std::string> vec;
        std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(), std::back_inserter(vec));
        values.push_back(vec);
    }
    // values now contains a vector for each line that has the strings split by their commas
    fin.close();
    return 0;
}

それはあなたの最初の質問に答えます。2 つ目は、引用符をマスクに追加してすべての引用符をスキップするrcか (空白として扱うこともできます)、後で (直接または を使用してtransform)削除することもできます。

std::transform(vec.begin(), vec.end(), vec.begin(), [](std::string& s)
{
    std::string::iterator pend = std::remove_if(s.begin(), s.end(), [](char c)
    {
        return c == '"';
    });
    s.erase(pend, s.end());
});
于 2013-10-05T02:36:04.743 に答える