C++文字列自家製常用ツール関数(フォーマット組立、各タイプの回転文字列、配列の分割、サブ列の置換、文字の除去、大文字と小文字の変換)
5798 ワード
文字列フォーマット組立汎用関数
C++は文字列の組み立てに対して1つのとても直接で使いやすい関数がなくて、ここでCのsnprintf()関数を利用して、1つの利用可能な関数を提供します:
ここでstringFormat関数はテンプレート関数であり、int、float、long、stringなど様々なタイプの変数をつなぎ合わせることができる様々な形式のフォーマット組立を受け入れることができる.
ここでテンプレートパラメータと関数の最後のパラメータが省略記号である理由は、Cが許可するパラメータ表現形式であり、最後に置かなければならず、後続のパラメータの個数が不定であることを示す前に確定したパラメータが必要である.ここではテンプレート,すなわちパラメータの個数やタイプが定まらない.任意のタイプの変数を組み立てることができます
snprintf()もCの関数で、使い方は以下の通りです.
int snprintf(char *str, int n, char * format [, argument, ...]);
パラメータ: str:組立後のchar配列アドレスを格納するための宛先アドレス; n:保存された文字数(最後の'0'を含まない)は、後にどれだけの文字が組み立てられているかにかかわらず、最終的な結果はここのn文字しか保持されず、最後に'0'を加えて終了することに注意する必要があります. format:フォーマットchar配列、つまり私たちがよく使う「hello%s」のような組み立て対象フォーマットです. argument...:フォーマットchar配列に必要な変数を適合させるための不定個数のパラメータ.
戻り値:アセンブリ後のchar配列の長さを返します.最後の'0'は含まれません.注意はnの数値ではありません.そうしないと、この戻りは意味がありません.ここでは、本来あるべきchar配列の長さ、すなわちformatが変数を組み立てた全長を返します.nは、strに前の文字を切り取るように設定します.
これで明らかになりますが、ここでは目的のアドレスにNULLが置かれており、残された文字の個数は0なので、残されたstrを切り取る必要はありません.ただ、組み立てに必要な長さを単純に計算するだけです.関数は'0'を含まないので、ここで追加します.
次にcharタイプの配列を作成し,計算した長さで初期化した.コンパイラのC++バージョンによっては、一意のポインタまたは自動ポインタが使用されます.ユニークポインタはC++11のプロパティで、同じオブジェクトは1つのunique_しか使用できません.ptrは所有し,コピー構造と付与構造の操作を禁止する.unique_ptrポインタオブジェクトがその役割ドメインを離れると、ライフサイクルが終了し、内部で指定された削除器(deleter)deleteが指すオブジェクトが自動的に使用されるため、関数が終了すると、その申請されたリソースが自動的に削除されます.
char配列を作成したら、実際の組み立てを行い、再びsnprintf関数を使用します.今回は、必要な長さが私たちが前に計算した長さであることを知り、前に作成したchar配列を目的のchar配列のパラメータ位置に置いて組み立てます.前に長さを計算する理由は、実際に使用するときにどのくらいの文字列が組み立てられるか分からないためです.長さのchar配列を勝手に作成すると、無駄にしたり、足りなかったりします.
最後に,組み立てた結果char配列を用いて文字列を初期化し,ここでは前の実際の文字だけが最後の'0'ではないことを返す.
数値タイプ変換文字列
C++11以前は直接的な数値タイプの文字列を回転する関数はありませんでしたが、ここではいくつか提供します.
実はsprintf関数を利用してフォーマットを行い、数値タイプをchar配列に変換し、stringタイプに変換して返します.
各タイプの回転String
もう1つの一般的なStringを回転する方法があります.
テンプレート関数を作成しstringstreamを用いて,様々なタイプのパラメータを受信し,文字列を返す.
文字列は、特定の文字に基づいて配列共通関数に分割されます.
splitは他の言語で文字列を配列に変換する一般的な関数ですが、C++にはありません.ここでは、文字列を特定の文字に基づいて配列に分割できる汎用関数を提供します.
関数は、分割する文字列と指定した区切り文字列を受信します.これはconst形式です.変更したくないからです.分割された配列、すなわちstringタイプのvectorを返します.
必要な変数を初期化した後、無限ループでstringのfind関数を使用して区切り記号が現れる位置を探し、2番目のパラメータは探し始める位置を指し、ここで最初は0です.find関数は最初に見つけた場所を返し、見つからない場合はstring::nposを返します.ここのnposは一般的にsize_です.tの最大値は、文字列の中で文字列の最後の位置である.
したがって、以下はstring::nposであれば、begin位置の後に見つからないことを示し、beginから文字列の最後の位置までサブ列を切り取り、配列に置く.
そうでなければ、説明が見つかったので、beginから必要な長さを切り取り、長さはend-beginで計算します.substr関数は、切り取りの開始位置と長さを受け入れ、デフォルトでは文字列の末尾まで最大値です.切り取りが終わったら、beginを区切り記号の後の位置に更新して、次の探しやすいようにします.
最後に、分割された文字列を返します.
置換文字列のサブストリング
文字列のサブストリングをすべて別のサブストリングに置き換えます.
文字列に置換するサブ列を絶えず見つけ、位置を得た後、replace関数で目的のサブ列に置き換え、見つからないまで置換する方法です.この関数はソース文字列を変更するのではなく、実パラメータをコピーし、変更して返します.
スペースを削除(または他の文字)
文字列のスペースを削除することは、上の関数でも実現できますが、ある文字を削除する汎用関数に相当します.
単純な遍歴判断では、デフォルトではスペースを削除したり、他の文字を削除したりすることができます.
大文字と小文字の変換
文字列のすべての文字を大文字または小文字に変換します.
toupper/tolower関数を使用して、各文字を反復器で巡り、変更します.ここで変更したのは元の文字列で、新しい文字列を返す必要はありません.
toupper/tolower関数のソースコード自体はアルファベットに属する文字のみを変更し、アルファベット以外の文字はそのまま返されるので、文字列にアルファベット以外の文字が含まれている心配はありません.
作者のトップページを見る
C++は文字列の組み立てに対して1つのとても直接で使いやすい関数がなくて、ここでCのsnprintf()関数を利用して、1つの利用可能な関数を提供します:
template
std::string stringFormat(const std::string& format, Args ... args ) {
size_t size = (size_t)snprintf( NULL, 0, format.c_str(), args ... ) + 1; // Extra space for '\0'
#ifdef C11
std::unique_ptr buf(new char[size]);
#else
std::auto_ptr buf(new char[size]);
#endif
snprintf( buf.get(), size, format.c_str(), args ... );
return std::string(buf.get(), size - 1); // We don't want the '\0' inside
}
ここでstringFormat関数はテンプレート関数であり、int、float、long、stringなど様々なタイプの変数をつなぎ合わせることができる様々な形式のフォーマット組立を受け入れることができる.
ここでテンプレートパラメータと関数の最後のパラメータが省略記号である理由は、Cが許可するパラメータ表現形式であり、最後に置かなければならず、後続のパラメータの個数が不定であることを示す前に確定したパラメータが必要である.ここではテンプレート,すなわちパラメータの個数やタイプが定まらない.任意のタイプの変数を組み立てることができます
snprintf()もCの関数で、使い方は以下の通りです.
int snprintf(char *str, int n, char * format [, argument, ...]);
パラメータ:
戻り値:アセンブリ後のchar配列の長さを返します.最後の'0'は含まれません.注意はnの数値ではありません.そうしないと、この戻りは意味がありません.ここでは、本来あるべきchar配列の長さ、すなわちformatが変数を組み立てた全長を返します.nは、strに前の文字を切り取るように設定します.
これで明らかになりますが、ここでは目的のアドレスにNULLが置かれており、残された文字の個数は0なので、残されたstrを切り取る必要はありません.ただ、組み立てに必要な長さを単純に計算するだけです.関数は'0'を含まないので、ここで追加します.
次にcharタイプの配列を作成し,計算した長さで初期化した.コンパイラのC++バージョンによっては、一意のポインタまたは自動ポインタが使用されます.ユニークポインタはC++11のプロパティで、同じオブジェクトは1つのunique_しか使用できません.ptrは所有し,コピー構造と付与構造の操作を禁止する.unique_ptrポインタオブジェクトがその役割ドメインを離れると、ライフサイクルが終了し、内部で指定された削除器(deleter)deleteが指すオブジェクトが自動的に使用されるため、関数が終了すると、その申請されたリソースが自動的に削除されます.
char配列を作成したら、実際の組み立てを行い、再びsnprintf関数を使用します.今回は、必要な長さが私たちが前に計算した長さであることを知り、前に作成したchar配列を目的のchar配列のパラメータ位置に置いて組み立てます.前に長さを計算する理由は、実際に使用するときにどのくらいの文字列が組み立てられるか分からないためです.長さのchar配列を勝手に作成すると、無駄にしたり、足りなかったりします.
最後に,組み立てた結果char配列を用いて文字列を初期化し,ここでは前の実際の文字だけが最後の'0'ではないことを返す.
数値タイプ変換文字列
C++11以前は直接的な数値タイプの文字列を回転する関数はありませんでしたが、ここではいくつか提供します.
std::string itoString(int i) {
char buf[30] = {0};
sprintf(buf, "%d", i);
return std::string(buf);
}
std::string ltoString(long i) {
char buf[30] = {0};
sprintf(buf, "%ld", i);
return std::string(buf);
}
std::string lltoString(long long i) {
char buf[30] = {0};
sprintf(buf, "%lld", i);
return std::string(buf);
}
実はsprintf関数を利用してフォーマットを行い、数値タイプをchar配列に変換し、stringタイプに変換して返します.
各タイプの回転String
もう1つの一般的なStringを回転する方法があります.
template
static string ToString(const T& tmp)
{
stringstream ss;
ss << tmp;
return ss.str();
}
テンプレート関数を作成しstringstreamを用いて,様々なタイプのパラメータを受信し,文字列を返す.
文字列は、特定の文字に基づいて配列共通関数に分割されます.
splitは他の言語で文字列を配列に変換する一般的な関数ですが、C++にはありません.ここでは、文字列を特定の文字に基づいて配列に分割できる汎用関数を提供します.
#include
#include
using std::string;
using std::vector;
vector split(const string &str, const string &separtor) {
size_t begin = 0, end = 0;
vector result;
while (true) {
end = str.find(separtor, begin);
if (end == string::npos) {
result.push_back(str.substr(begin));
break;
} else {
result.push_back(str.substr(begin, end-begin));
begin = end + separtor.size();
}
}
return result;
}
関数は、分割する文字列と指定した区切り文字列を受信します.これはconst形式です.変更したくないからです.分割された配列、すなわちstringタイプのvectorを返します.
必要な変数を初期化した後、無限ループでstringのfind関数を使用して区切り記号が現れる位置を探し、2番目のパラメータは探し始める位置を指し、ここで最初は0です.find関数は最初に見つけた場所を返し、見つからない場合はstring::nposを返します.ここのnposは一般的にsize_です.tの最大値は、文字列の中で文字列の最後の位置である.
したがって、以下はstring::nposであれば、begin位置の後に見つからないことを示し、beginから文字列の最後の位置までサブ列を切り取り、配列に置く.
そうでなければ、説明が見つかったので、beginから必要な長さを切り取り、長さはend-beginで計算します.substr関数は、切り取りの開始位置と長さを受け入れ、デフォルトでは文字列の末尾まで最大値です.切り取りが終わったら、beginを区切り記号の後の位置に更新して、次の探しやすいようにします.
最後に、分割された文字列を返します.
置換文字列のサブストリング
文字列のサブストリングをすべて別のサブストリングに置き換えます.
std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
return str;
}
文字列に置換するサブ列を絶えず見つけ、位置を得た後、replace関数で目的のサブ列に置き換え、見つからないまで置換する方法です.この関数はソース文字列を変更するのではなく、実パラメータをコピーし、変更して返します.
スペースを削除(または他の文字)
文字列のスペースを削除することは、上の関数でも実現できますが、ある文字を削除する汎用関数に相当します.
std::string Trim(const std::string& str, const char target = ' ') {
string retStr = "";
for (size_t i = 0, n = str.length(); i < n; ++i) {
if (str[i] != target) {
retStr += str[i];
}
}
return retStr;
}
単純な遍歴判断では、デフォルトではスペースを削除したり、他の文字を削除したりすることができます.
大文字と小文字の変換
文字列のすべての文字を大文字または小文字に変換します.
void toUpperCase(string &s) {
for (string::iterator it = s.begin(); it != s.end(); it++) {
char c = (char)std::toupper(*it);
*it = c;
}
}
void toLowerCase(string &s) {
for (string::iterator it = s.begin(); it != s.end(); it++) {
char c = (char)std::tolower(*it);
*it = c;
}
}
toupper/tolower関数を使用して、各文字を反復器で巡り、変更します.ここで変更したのは元の文字列で、新しい文字列を返す必要はありません.
toupper/tolower関数のソースコード自体はアルファベットに属する文字のみを変更し、アルファベット以外の文字はそのまま返されるので、文字列にアルファベット以外の文字が含まれている心配はありません.
作者のトップページを見る