C++で文字列から先頭の文字を効率的に削除する方法を徹底解説
計算言語学、機械学習、データ分析などの分野では、大量のテキストデータを扱う必要があることがよくあります。C++では、こうしたデータ処理に文字列(string)やリストが広く使われています。その中で「文字列や文字リストから最初に出現する特定の文字を削除したい」というケースも少なくありません。
本記事では、C++で文字列の先頭の文字(最初の1文字)を削除するためのさまざまな手法を、具体的なサンプルコードとともにわかりやすく解説します。いずれの方法も元の文字列から先頭の1文字を取り除き、より短い新しい文字列を得るという同じ結果を実現します。
例1:C++のerase()メソッドを使って文字列の先頭文字を削除する
string::erase関数は、文字列から文字を直接(in placeで)削除する際に最も推奨される方法です。eraseには複数のオーバーロードがあり、ここでは範囲を指定して削除する形式を見ていきます。
まずmain関数の中で、std::stringクラスを使って文字列変数「StrValue」を定義し、文字列で初期化しています。続いてcout文により、初期化された直後の文字列を出力します。
その後、eraseメソッドを呼び出します。引数として「0」と「1」を渡しています。「0」は文字列StrValueの最初の文字を指すインデックス、「1」は削除する文字数です。つまりeraseメソッドは、指定された位置から指定された長さ分の文字を文字列から削除します。最後に、先頭の文字が削除された後の文字列を出力しています。
#include <iostream>
#include <string>
int main()
{
std::string StrValue = "Happy Me";
std::cout << "String Before:" << StrValue << std::endl;
StrValue.erase(0, 1);
std::cout << "String After:" << StrValue << std::endl;
return 0;
}
以下の出力結果を見ると、eraseメソッドによって指定した文字列の先頭の文字が正しく削除されていることが確認できます。

例2:C++のイテレータを使ったerase()で文字列の先頭文字を削除する
erase()メソッドにはもう一つのオーバーロードがあり、イテレータを引数として受け取る形式があります。この形式では、イテレータが指し示す位置の文字を削除できます。文字列の先頭の文字を指すイテレータを渡せば、先頭の1文字だけを削除できるわけです。
次のプログラムでは、main関数内でstd::string型の変数「StringIs」を定義し、文字列で初期化しています。まずeraseメソッドを適用する前の文字列を出力します。
続いてeraseメソッドを呼び出します。ここではStringIs.begin()を引数に渡しています。begin()は文字列の先頭の文字を指すイテレータを返すため、eraseメソッドはその位置にある文字、すなわち先頭の1文字を削除します。その後、先頭文字が取り除かれた文字列が出力されます。
#include <iostream>
#include <string>
int main()
{
std::string StringIs = "Programming Example";
std::cout << "String Before: " << StringIs << std::endl;
StringIs.erase(StringIs.begin());
std::cout << "String After: " << StringIs << std::endl;
return 0;
}
実行結果はシェルに表示されており、eraseメソッド(イテレータ版)を適用する前と、先頭の文字を削除した後の文字列がそれぞれ確認できます。

例3:空文字列チェックを行ってからC++で先頭文字を削除する
string::erase関数を使用する前に、対象の文字列が空でないことを確認しておくことが重要です。空の文字列に対してeraseを実行すると、プログラムはstd::length_error例外を送出してしまいます。
次のプログラムでは、main関数内で文字列変数「MyStr」を宣言し、宣言と同時に文字列で初期化しています。まず現在の文字列の値をシェルに出力します。
その後、if文を使って条件判定を行います。if条件の中ではempty()メソッドを呼び出し、文字列が空でないことを確認しています。この条件を満たす場合のみ、eraseメソッド(イテレータ版)を実行して先頭の文字を削除します。最後に、先頭文字が削除された文字列を画面に出力します。
#include <iostream>
#include <string>
int main()
{
std::string MyStr = "rainbow";
std::cout << "String Before:" << MyStr << std::endl;
if (!MyStr.empty()) {
MyStr.erase(MyStr.begin());
}
std::cout << "String Now:" << MyStr << std::endl;
return 0;
}
実行すると、以下のような出力が得られます。

例4:先頭の文字が特定の文字と一致する場合のみ削除する(C++)
次に、「先頭の文字が特定の文字と一致する場合にだけ削除する」という条件付きの削除を行う例を紹介します。
次のプログラムのmain関数では、文字列値で初期化した変数「Name」を定義し、coutコマンドでその内容を表示しています。続いてchar型の変数「ch」を定義し、比較用の文字「k」を代入します。この文字が、元の文字列の先頭の文字と一致するかどうかを調べます。
if文では、「Name.front() == ch」という条件で、文字列の先頭の文字と変数chの値が一致しているかを判定しています。front()関数は、文字列の先頭の文字への参照を取得するために使われる便利な関数です。条件が成立した場合は、eraseメソッド(イテレータ版)によって先頭の文字を削除します。
#include <iostream>
#include <string>
int main()
{
std::string Name = "Kalsoom";
std::cout << "Name Before: " << Name << std::endl;
char ch = 'K';
if (Name.front() == ch) {
Name.erase(Name.begin());
}
std::cout << "Name Now: " << Name << std::endl;
return 0;
}
出力結果を見ると、条件に一致した先頭の文字だけが削除されていることがわかります。

例5:C++のsubstr()メソッドを使って文字列の先頭文字を削除する
これまで紹介したstring::eraseメソッドは、元の文字列を直接変更する(in place)方式でした。一方、string::substr関数を使うと、先頭の1文字を含まない新しい文字列のコピーを取得できます。
次のプログラムでは、if条件ブロック内でsubstr関数を文字列「MyString」に対して呼び出しています。substr関数には「開始位置=1」と「文字列の長さ-1」を引数として渡しています。これにより、呼び出し元の文字列オブジェクトから、指定された範囲の文字を含む新しい文字列が生成されます。
#include <iostream>
#include <string>
int main()
{
std::string MyString = "Bringing";
std::cout << "Original String: "<< MyString << std::endl;
std::string n;
if (!MyString.empty()) {
n = MyString.substr(1, MyString.size() - 1);
}
std::cout << "Changed String: " << n << std::endl;
return 0;
}
以下のシェル出力のように、substrメソッドによって文字列の先頭の文字が削除された新しい文字列が得られました。

まとめ
本記事では、C++で文字列から先頭の文字を削除するためのさまざまな方法を学びました。erase()メソッドのインデックス指定版・イテレータ版、empty()による安全チェック、front()との組み合わせによる条件付き削除、そしてsubstr()による新しい文字列の生成など、いずれも同じ結果を返しながら実装アプローチが異なる効率的な手法です。用途に応じて使い分けることで、文字列操作のコードをより堅牢かつ読みやすくできます。皆さんの開発作業に役立てば幸いです。
-
【C++】二分探索木(BST)でk番目に小さい要素を検索する方法
問題概要二分探索木(BST)と整数 k が入力として与えられたとき、木の中で k番目に小さい要素 を見つける問題を解説します。例えば、以下のようなBSTを考えてみましょう。この木に対して k = 3 を指定した場合、出力は 15 になります。木の要素を昇順に並べると「9, 13, 15, 17, 19, 25, 27」となり、3番目の値が15であるためです。アルゴリズムの考え方二分探索木には、「中順走査(in-order traversal)」を行うと要素が昇順に訪問されるという重要な性質があります。この性質を利用し、走査中に訪問したノード数をカウントしていき、k番目に到達した時点でそのノード
-
DAG(有向非巡回グラフ)のランダム線形拡張を生成するC++プログラム
この記事では、有向非巡回グラフ(DAG: Directed Acyclic Graph)のランダム線形拡張(Random Linear Extension)を作成する方法を解説します。線形拡張とは、DAGの位相ソート(トポロジカルソート)に相当するものです。以下のようなグラフを例に考えてみましょう。トポロジカルソートとは有向非巡回グラフにおけるトポロジカルソートとは、頂点を線形に並べた順序のことです。有向グラフのすべての辺 u-v に対して、並び順の中で頂点 u が必ず頂点 v よりも先に現れるような順序を指します。始点の頂点は必ず終点の頂点よりも先に配置される必要があるため、処理済みの頂点を