記事内にはプロモーションが含まれています

【C++】文字列切り出しを極める!substr関数の使い方や後ろからの取得など徹底解説

【C++】文字列切り出しを極める!substr関数の使い方や後ろからの取得など徹底解説 C++

C++でアプリケーション開発を行う際、テキストデータの処理は避けて通れない重要なテーマです。

特に「文字列の一部を取り出したい」「特定の文字で分割したい」というシーンは頻繁に訪れますが、C++の標準ライブラリである std::string には他の言語にあるような splitslice といった直感的な名前の関数が用意されていない場合があります。

そのため、「どうやって切り出せばいいの?」「効率的な方法は?」と迷ってしまう方も多いのではないでしょうか。

この記事では、C++における文字列切り出しの基本関数 substr の使い方から、後ろから切り出すテクニック、区切り文字での分割方法、さらにはコピーコストを抑えるモダンな std::string_view の活用まで、現在の開発環境に即したベストプラクティスをサンプルコード付きで徹底解説します。

【本記事の信頼性】
プロフィール
執筆者:マヒロ
  • 執筆者は元エンジニア
  • SES⇒大手の社内SE⇒独立
  • 現在はこじんまりとしたプログラミングスクールを運営
  • モットーは「利他の精神」

文字列切り出しの基本!substr関数の使い方

C++で std::string 型の文字列から特定の部分を取り出すには、メンバ関数である substr を使用するのが最も一般的です。

引数の指定方法によって、「どこから」「何文字」切り出すかを制御できます。

指定した位置から文字数を指定して切り出す

substr 関数の基本的な構文は substr(開始位置, 文字数) です。 開始位置は0から始まるインデックスで指定します。

#include <iostream>
#include <string>

int main() {
    std::string text = "Hello, C++ World!";

    // インデックス7('C')から3文字切り出す
    std::string sub = text.substr(7, 3);

    std::cout << "元の文字列: " << text << std::endl;
    std::cout << "切り出し後: " << sub << std::endl;

    return 0;
}

実行結果

元の文字列: Hello, C++ World!
切り出し後: C++

text.substr(7, 3) は、文字列 text の7番目の文字(0始まりなので8文字目)からスタートし、そこから3文字分を取り出して新しい文字列を生成します。

この操作は元の文字列 text を変更せず、新しい std::string オブジェクトを返します(非破壊的操作)。

指定した位置から「最後まで」切り出す

第2引数(文字数)を省略すると、指定した開始位置から文字列の末尾まですべてを切り出すことができます。

#include <iostream>
#include <string>

int main() {
    std::string text = "Hello, C++ World!";

    // インデックス7から最後まで切り出す
    std::string sub = text.substr(7);

    std::cout << "切り出し後: " << sub << std::endl;

    return 0;
}

実行結果

切り出し後: C++ World!

substr(7) と記述することで、7番目の文字以降すべての文字列を取得しています。

ファイルパスからファイル名を取得したり、特定のプレフィックス(接頭辞)を除去したりする場合によく使われる記述です。

「後ろから」文字列を切り出すテクニック

「ファイル名の拡張子だけ取得したい」「末尾の3文字だけ確認したい」といった場合、後ろからの位置指定が必要になります。

Pythonなどの言語ではマイナスのインデックスを使えますが、C++の substr はマイナス指定に対応していません

そのため、文字列の長さ(length())を使って計算する必要があります。

文字列長を使って末尾から切り出す

#include <iostream>
#include <string>

int main() {
    std::string filename = "report_2026.txt";
    
    // 後ろから3文字(拡張子)を取り出したい
    // 開始位置 = 全体の長さ - 切り出したい文字数
    size_t len = filename.length();
    std::string ext = filename.substr(len - 3);

    std::cout << "拡張子: " << ext << std::endl;

    return 0;
}

実行結果

拡張子: txt

filename.length() - 3 を計算することで、「末尾から3文字手前のインデックス」を求めています。

そこを開始位置として substr を呼ぶことで、結果的に「後ろから3文字」を取得することができます。

計算結果が負にならないよう、文字列の長さチェックを入れるのが安全な実装です。

特定の「区切り文字」で分割・抽出する方法

CSVデータのようにカンマ , で区切られた文字列や、スペースで区切られた単語を分割して取り出したいケースも多々あります。

C++には標準の split 関数はありませんが、find 関数と substr を組み合わせることで実装可能です。

findとsubstrを使った分割(Split)の実装例

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

int main() {
    std::string data = "Apple,Banana,Cherry,Date";
    std::string delimiter = ",";
    std::vector<std::string> result;
    
    size_t pos_start = 0;
    size_t pos_end;
    
    // カンマが見つかる間繰り返す
    while ((pos_end = data.find(delimiter, pos_start)) != std::string::npos) {
        // 見つかった位置までの文字列を切り出し
        std::string token = data.substr(pos_start, pos_end - pos_start);
        
        result.push_back(token);
        
        // 次の検索開始位置を更新(カンマの次から)
        pos_start = pos_end + delimiter.length();
    }
    
    // 最後の要素を追加
    result.push_back(data.substr(pos_start));

    // 結果の表示
    for (const auto& item : result) {
        std::cout << item << std::endl;
    }

    return 0;
}

実行結果

Apple
Banana
Cherry
Date

data.find(delimiter, pos_start) を使い、区切り文字(カンマ)が出現する位置を検索しています。

見つかった位置を使って substr で単語を切り出し、リスト(vector)に追加します。

ループが終了した後、最後の区切り文字以降に残った文字列(ここでは “Date”)を追加することを忘れないようにしましょう。

【C++20以降】rangesを使ったモダンな分割方法

C++20以降の環境であれば、Rangeライブラリを使用することで、より現代的でスマートな記述が可能になります。

#include <iostream>
#include <string>
#include <string_view>
#include <ranges>

int main() {
    std::string_view data = "Apple,Banana,Cherry,Date";

    // split_viewを使って分割
    for (const auto& word : data | std::views::split(',')) {
        // wordはサブレンジなので、string_viewとして表示
        std::cout << std::string_view(word.begin(), word.end()) << std::endl;
    }

    return 0;
}

std::views::split を使うと、区切り文字での分割を遅延評価(必要な時に処理)で行うことができます。

従来のループ処理よりも直感的で、メモリ効率も良い方法です。

現在の新規開発であれば、積極的に採用したいテクニックです。

パフォーマンス改善!コピーを避ける string_view の活用

substr は非常に便利ですが、新しい std::string オブジェクトを作成してメモリをコピーするため、巨大な文字列を大量に処理する場合にコストがかかります。

C++17から導入された std::string_view を使うと、文字列のコピーを発生させずに「参照」だけで切り出し操作を行えます。

string_viewを使ったゼロコピー切り出し

#include <iostream>
#include <string>
#include <string_view>

int main() {
    std::string heavy_text = "This is a very long text data..."; 
    
    // string_viewでラップする(コピーは発生しない)
    std::string_view sv = heavy_text;

    // substrを使っても新しい文字列は作られない(参照範囲が変わるだけ)
    std::string_view sub_sv = sv.substr(0, 4);

    std::cout << "切り出し: " << sub_sv << std::endl;

    return 0;
}

実行結果

切り出し: This

std::string_view は、文字列の実体を持たず、「どこからどこまでを見るか」という情報だけを持っています。

そのため、substr を呼んでもメモリの確保やデータのコピーが発生せず、非常に高速です。

読み取り専用の文字列操作であれば、std::string よりも std::string_view を使うのが現代C++の定石です。

C++のスキルを活かして年収を上げる方法

以上、C++での文字列切り出しの方法について解説しました。

なお、C++のスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。

C++を扱えるエンジニアは希少価値が高いため、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。

なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。

今すぐ転職する気がなくとも、とりあえず転職エージェントに無料登録しておくだけで、スカウトが届いたり、思わぬ好待遇の求人情報が送られてきたりするというメリットがあります。

併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなC++の案件を探しやすくなります。

転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。