HOWTO · C++

C++ でカンマ区切りの文字列を分割する方法

std::stringstream と std::getline、または std::string::find と std::string::substr を使って、C++ で単純なカンマ区切りの文字列を分割します。

このページの内容

単純なカンマ区切りの文字列については、std::stringstream と std::getline を使うのが、各値を std::vector<std::string> に集める分かりやすい方法です。各断片の抽出方法を制御する必要がある場合は、std::string::find と std::string::substr が手動の代替手段となります。これらの方法は区切り文字で分割するもので、引用符で囲まれたフィールド内のカンマなど、完全な CSV 構文を解析するものではありません。

std::stringstream と std::getline でカンマ区切りの文字列を分割する

入力文字列からストリームを構築するには <sstream> を、断片を格納するには <vector> をインクルードします。カンマを std::getline の第 3 引数として渡します。各呼び出しはその区切り文字まで読み取り、抽出したテキストを item に格納します。ループは各要素をベクターに追加し、集めた値を出力します。

後のコードでトークンにインデックスでアクセスしたり、再度イテレートしたりする必要がある場合は std::vector<std::string> を使用します。各抽出値は入力順に個別の文字列として格納されます。

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

int main() {
    const std::string input = "apple,banana,cherry,dates";
    std::stringstream stream(input);
    std::vector<std::string> items;
    std::string item;

    while (std::getline(stream, item, ',')) {
        items.push_back(item);
    }

    for (const std::string& value : items) {
        std::cout << value << '\n';
    }
}
apple
banana
cherry
dates

この例ではカンマを区切り文字として使用し、抽出した 4 つの文字列を順番に格納します。区切り文字付きの std::getline は、連続するカンマの間に空の要素を生成することがありますが、末尾の区切り文字はこのループでは最終要素を生成しません。入力でそのようなケースを異なる方法で扱う必要がある場合は、各区切り文字の位置が何を意味するかを決め、解析ロジックに反映してください。抽出された文字列は入力の一部である空白を保持するため、周囲の空白を破棄する場合は各要素を個別にトリミングしてください。ソースがセミコロンなどの別の 1 文字を使用している場合は、区切り文字の引数を変更してください。

std::string::find と std::string::substr でカンマ区切りの文字列を分割する

std::string::find メンバーは次のカンマを検索し、std::string::substr はその前の文字をコピーします。処理しながら文字を削除するのではなく、元の入力に対する開始インデックスを保持します。find が std::string::npos を返した場合、カンマはもう存在しないため、残りのサフィックスを最終要素として取得して終了します。

#include <iostream>
#include <string>
#include <vector>

int main() {
    const std::string input = "apple,banana,cherry,dates";
    std::vector<std::string> items;
    std::string::size_type start = 0;

    while (true) {
        const std::string::size_type comma = input.find(',', start);
        if (comma == std::string::npos) {
            items.push_back(input.substr(start));
            break;
        }

        items.push_back(input.substr(start, comma - start));
        start = comma + 1;
    }

    for (const std::string& value : items) {
        std::cout << value << '\n';
    }
}
apple
banana
cherry
dates

最後の substr(start) 呼び出しは重要です。これは最後のカンマの後のテキストを追加します。これには、区切り文字がもうない場合の最後の値も含まれます。このバージョンでは、末尾にカンマがある入力も、上のストリームループとは異なり、最終要素が空であるものとして扱います。完全に空の入力についても同様に空の文字列を 1 つ格納するため、アプリケーションでその入力を値なしとして扱うべき場合はループ条件を調整してください。検索は各カンマの次の文字から開始されるため、解析中に入力を変更することがなく、元の文字列を後の使用のために保持しやすくなります。どちらの方法も引用符内のカンマやエスケープされた引用符は処理しません。そのような規則が入力形式の一部である場合は CSV パーサーを使用してください。