C# の文字列操作の気分で C++ にやってくると、C++ の文字列操作は メモリ操作(例えば主記憶装置上の操作)なことに気づく。
このサンプルコードに 表現の著作性はないが 気になるなら MIT License で。https://opensource.org/licenses/MIT
前準備
const char* a と size_t b がやってきた
#include <string> // std::string
// ↑ファイルの冒頭あたりに置く
std::string myString(a, b);
(Visual Studio 2015)
これで a, b で渡された変数は、std::string 型の文字列 myString 変数として使える。
文字列の配列(1)
#include <string> // std::string
#include <iostream> // std::cout
// ↑ファイルの冒頭あたりに置く
static std::string a[] = {"か","きく","けこ"};
// でいける。
std::string c = a[0] + a[1] + a[2];
std::cout << c << std::endl;
// 出力:
// かきくけこ
(Visual Studio 2015)
文字列の配列(2)
#include <string> // std::string
#include <iostream> // std::cout
// ↑ファイルの冒頭あたりに置く
std::string a[10] = {};
if ("" == a[0]) { std::cout << "空0" << std::endl; }
if ("" == a[1]) { std::cout << "空1" << std::endl; }
if ("" == a[2]) { std::cout << "空2" << std::endl; }
if ("" == a[3]) { std::cout << "空3" << std::endl; }
if ("" == a[4]) { std::cout << "空4" << std::endl; }
if ("" == a[5]) { std::cout << "空5" << std::endl; }
if ("" == a[6]) { std::cout << "空6" << std::endl; }
if ("" == a[7]) { std::cout << "空7" << std::endl; }
if ("" == a[8]) { std::cout << "空8" << std::endl; }
if ("" == a[9]) { std::cout << "空9" << std::endl; }
// 結果:
// 空0
// 空1
// 空2
// 空3
// 空4
// 空5
// 空6
// 空7
// 空8
// 空9
(Visual Studio 2015)
配列の要素数を指定しておけば、空文字列で埋めてくれる実装のようだ。
文字列連結(1)
#include <string> // std::string
#include <iostream> // std::cout
// ↑ファイルの冒頭あたりに置く
std::string a = "あいう";
std::string b = "えお";
// なら単に
std::string c = a + b;
// と書けばいける。
std::cout << c << std::endl;
// 出力:
// あいうえお
(Visual Studio 2015)
文字列連結(2)
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く
static std::string a = "変";
static std::ostringstream s;
s << "あ" << 1 << " " << (3+7) << " " << false << a << std::endl;
// と書けば。
std::cout << s.str() << std::endl;
// 出力:
// あ1 10 0変
// false が 0 になっているのは面食らう。
(Visual Studio 2015)
文字列分割 半角スペース区切り
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く
std::string a, b, c;
std::istringstream("さし す せそ") >> a >> b >> c;
// と書けば
std::cout << "a=[" << a << "]" << std::endl;
std::cout << "b=[" << b << "]" << std::endl;
std::cout << "c=[" << c << "]" << std::endl;
// 出力:
// a=[さし]
// b=[す]
// c=[せそ]
(Visual Studio 2015)
この書き方だと、全角スペースでは区切ってくれない。
もう少し調べる。
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く
std::string a, b;
std::istringstream s("たち つ てと");
s >> a >> b;
// と書けば
std::cout << "a=[" << a << "]" << std::endl;
std::cout << "b=[" << b << "]" << std::endl;
std::cout << "s=[" << s.str() << "]" << std::endl;
// 出力:
// a=[たち]
// b=[つ]
// s=[たち つ てと]
(Visual Studio 2015)
ストリームで流しても、元の文字列は残っているようだ。
さらに 調べる。
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く
std::string a, b, c, d, e, f, g;
std::istringstream s("な にぬ ねの はひ ふ へほ");
s >> a;
s >> b;
s >> c;
s >> d;
s >> e;
s >> f;
s >> g;
// こう書いて
std::cout << "a=[" << a << "]" << std::endl;
std::cout << "b=[" << b << "]" << std::endl;
std::cout << "c=[" << c << "]" << std::endl;
std::cout << "d=[" << d << "]" << std::endl;
std::cout << "e=[" << e << "]" << std::endl;
std::cout << "f=[" << f << "]" << std::endl;
std::cout << "g=[" << g << "]" << std::endl;
std::cout << "s=[" << s.str() << "]" << std::endl;
// 結果:
// a=[な]
// b=[にぬ]
// c=[ねの]
// d=[はひ]
// e=[ふ]
// f=[へほ]
// g=[]
// s=[な にぬ ねの はひ ふ へほ]
(Visual Studio 2015)
どこまでコピーを終えたか、は記憶されているようだ。
比較 等しい
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::ostringstream
// ↑ファイルの冒頭あたりに置く
std::string a = "あいう";
if ("あ" == a) { std::cout << "答1" << std::endl; }
else if ("あい" == a) { std::cout << "答2" << std::endl; }
else if ("あいう" == a) { std::cout << "答3" << std::endl; }
else if ("あいうえ" == a) { std::cout << "答4" << std::endl; }
else if ("あいうえお" == a) { std::cout << "答5" << std::endl; }
else { std::cout << "答6" << std::endl; }
std::string unuse;
std::getline(std::cin, unuse);
// 結果:
// 答3
(Visual Studio 2015)
等号で比較できたが 本当にこれでいいのか知らない。
楽しいサンプル・プログラム
解析器
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::istringstream, std::ostringstream
#include <vector> // 可変長配列
// 参照 : C++での文字列の使い方まとめ(string) (Futurismo) http://futurismo.biz/archives/1856
int main()
{
// 与件
std::istringstream data("--加納 こはだ かんぱち まぐろ --木曽 あなご かっぱ --久慈 たまご あかがい とろ いか");
// データ構造: --人物 寿司ネタ(複数件)※繰り返し
// 人物、寿司ネタは可変個数設定可能
// 受け皿
std::vector<std::string> persons; // 結果はこれらの配列に入れる
std::vector<std::vector<std::string>> dishes;
// 記憶
// 別段用意無し
// 解析器
std::string a;
while (data >> a) {
if ("--"==a.substr(0,2))//先頭の2文字が「--」の場合
{
persons.push_back(a.substr(2)); // 最初の2文字「--」の次から
dishes.push_back(std::vector<std::string>()); // リストの中にリストを準備
}
else { dishes[dishes.size() - 1].push_back(a); } // 要素数-1 で最後の要素
std::cout << "a=[" << a << "]" << std::endl;
}
// 結果
int i = 0;
for(std::string person : persons)
{
for (std::string dish : dishes[i])
{
std::cout << "(" << i << ") person=[" << person << "] dish=[" << dish << "]" << std::endl;
}
i++;
}
std::cout << "Please, push any key." << std::endl;
std::string unuse;
std::getline(std::cin, unuse);
return 0;
}
(Visual Studio 2015)
g++ だと 「while (data >> a) {」の判定で止まってくれないようだ?