C++ stringクラス 書いて覚えるための初心者自己中記事
革命だ!!
文字列リテラルめんどくさいってずっと考えてたけど、こんな便利なものがあるなんて、class の勉強乗り越えてよかった・・・
いや、ど素人じゃなきゃこんなん常識なんでしょうけど、わたしど素人なので。
C++に標準で用意されているstringクラス。
#include <string>
で使える。
---------------------------------------------
int main(){
string str = "なんらかの文字列";
cout << str << endl;
str = "少し変えた文字列";
cout << str << endl;
str += "の後に追加した文字列";
cout << str << endl;
cout << "サイズを出したいときは" << endl;
cout << str.size() << endl;
cout << "文字コードを出したいときは" << endl;
str = "Dragon Quest";
for (int i(0) ; i < str.size() ; ++i){
cout << (int)(unsigned char)str[i] << " : " << flush;
}
cout << endl;
}
------------------------
(結果)
なんらかの文字列
少し変えた文字列
少し変えた文字列の後に追加した文字列
サイズを出したいときは
54
文字コードを出したいときは
68 : 114 : 97 : 103 : 111 : 110 : 32 : 81 : 117 : 101 : 115 : 116 :
---------------------------------------------
便利だ。
日本語の文字コードはまだよく分からないけど。
この便利なstringクラスは、コンストラクタでconst char* を仮引数としているそうなのでこうやって文字列リテラルで渡してちゃんと初期化してくれるのだそうです。
そして新たに別の文字リテラルを代入したり、さらに足したり出来るのは演算子オーバーロードでそういう処理をさせているらしい。
メンバ関数として登場しているのがsize関数。
このメンバ関数はバイト数を返してくれる。
さらに何気無く行った str [ i ] は普通に考えたらおかしい。
stringというクラスの型ってだけなんだから
例えば文字列リテラルの入ったアドレスの先頭を保管しているconst char* だったら[ i ] で1単位づつアドレスをずらしているとわかるけど、これはクラスの型なんだから。
---------------------------------------------
void Test(const char* str){
cout << str << endl;
}
int main(){
string str = "hello";
Test(str); //エラーになる
}
---------------------
(結果)
エラー
---------------------------------------------
stringクラスはコンストラクタで const char* を仮引数にしているがstringクラス型のオブジェクトがconst char* というわけではない。
ただし、上記の目的に対してはstringクラスのメンバ関数 c_str(); で対応できる。
---------------------------------------------
void Test(const char* str){
cout << str << endl;
}
int main(){
string str = "hello";
Test(str.c_str());
}
---------------------
(結果)
hello
---------------------------------------------
この c_str 関数と同じようなメンバ関数で data 関数がある。
両者の違いはヌルターミネータ( \0 ) が付くことに対しての保証の有無。
( c_str関数は保証されているらしい )
getline 関数
---------------------------------------------
int main(){
string str;
getline(cin,str);
cout << str << endl;
}
---------------------
(結果)
aaa
aaa
---------------------------------------------
入力から1行を拾ってstringクラスのオブジェクトに入れることができる。
入力から1行を拾って。
入力から1行を拾って・・・?
次に比較
---------------------------------------------
int main(){
string str;
getline(cin,str);
if(str == "end"){
cout << str << endl;
}
}
---------------------
(結果)
end
end
---------------------------------------------
stringクラスのオブジェクトは文字列リテラルと比較ができる。
これは凄いことだ。
stringクラスのメンバ関数が色々あると書いてあった。
重要なものだけ記載するとあり、書かれているの見たけど見方が分からない!
・・・色々見てたら少しだけわかるようになってきた。
戻り型が size_type ってのとかあるのね。
この size_type型ってやつで戻ってきた返り値を受け取りたければsize_typem型の変数を用意しなければとなるが、その方法が今までと違う。
size_type i ; ではなく
string::size_type i と、こんな感じ
スコープ解決演算子なのか?
なのか?
テキストだとあとで説明するからまだ分からなくて良いって。
---------------------------------------------
int main(){
string str;
string::size_type i;
getline(cin,str);
cin >> i;
cout << str.operator[](i) << endl;;
}
---------------------
(結果)
mario world
6
w
---------------------------------------------
楽しい。
out_of_range例外を投げる・・?
キャッチ・・・?
ここら辺はまだだな。
---------------------------------------------
int main(){
string str = "hello";
cout << str.size() << endl;
cout << str.length() << endl;
str = "日本語だと?";
cout << str.size() << endl;
cout << str.length() << endl;
}
---------------------
(結果)
5
5
18
18
---------------------------------------------
日本語だとlength( ) 文字列の長さはちゃんと出ないのかな・・
---------------------------------------------
int main(){
string str = "hello";
cout << str.size() << endl;
cout << str.length() << endl;
str.resize(3);
cout << str << endl;
cout << str.size() << endl;
cout << str.length() << endl;
}
---------------------
(結果)
5
5
hel
3
3
---------------------------------------------
おぉ、リサイズできた。
---------------------------------------------
int main(){
string str = "hello";
cout << str.size() << endl;
cout << str.length() << endl;
str.resize(8);
cout << str << str << endl;
cout << str.size() << endl;
cout << str.length() << endl;
}
---------------------
(結果)
5
5
hellohello
8
8
---------------------------------------------
文字列のサイズを実際よりも大きくしたら、 ちゃんと大きくなるけど特にスペース入ったりはないんだ。
---------------------------------------------
int main(){
string str;
cout << str.size() << endl;
cout << str.length() << endl;
string::size_type i = 8;
str.reserve(i);
cout << str << endl;
cout << str.size() << endl;
cout << str.length() << endl;
cout << (int)(unsigned char)str.capacity() << endl;
}
---------------------
(結果)
0
0
0
0
22
---------------------------------------------
んん・・?
reserve( ) の使い方がよく分からない。
8を指定したらcapacity( ) が22になった。
---------------------------------------------
int main(){
string str = "もじもじ";
cout << str << endl;
str = ""; //clear() と比べっこ
//str.clear();
cout << str << endl;
cout << str.size() << endl;
cout << str.length() << endl;
cout << str.empty() << endl;
}
---------------------
(結果)
もじもじ
0
0
1
---------------------------------------------
clear( ) と str = "" で結果が同じっぽいなぁ。
---------------------------------------------
int main(){
string str = "もじもじ";
cout << str << endl;
str.insert(str.size()/2,"[いんさーと]");
cout << str << endl;
string::size_type i(3),j(7);
str.erase(i,j);
cout << str << endl;
}
---------------------
(結果)
もじもじ
もじ[いんさーと]もじ
もんさーと]もじ
---------------------------------------------
日本語でもsize()/2 で間に行けるのか。
erase( ) は上手くいかないなぁ。
やっぱり一文字1バイトじゃないと難しい。
---------------------------------------------
int main(){
string str = "もじもじ";
cout << str << endl;
str.insert(str.size()/2,"[いんさーと]");
cout << str << endl;
string::size_type f = str.find("[");
string::size_type e = str.rfind("]") - f + 1;
str.replace(f,e,"");
cout << f << "バイト目から~ " << e << "バイト目まで" << endl;
cout << str << endl;
}
---------------------
(結果)
もじもじ
もじ[いんさーと]もじ
6バイト目から~ 17バイト目まで
もじもじ
---------------------------------------------
こうか。
---------------------------------------------
int main(){
string str = "もじもじ";
cout << str << endl;
string str2 = str.substr(str.size()/2);
cout << str << endl;
cout << str2 << endl;
}
---------------------
(結果)
もじもじ
もじもじ
もじ
---------------------------------------------
substr( ) は指定範囲の文字列をstring型で返す。
stringstreamクラス
#include <sstream> が必要
---------------------------------------------
int main(){
stringstream sstr;
int x(5),y(3);
sstr.str(""); //strメンバ関数で初期化のような感じ
sstr << x << " + " << y << " = " << x+y << flush; //cout感覚でオブジェクト名から始めると文字列が入っていく
cout << sstr.str() << endl;
}
---------------------
(結果)
5 + 3 = 8
---------------------------------------------
このクラスを使うと文字列の作成と代入がcoutのような使い方でできてしまう。便利。
cin のようなこともできる
---------------------------------------------
int main(){
stringstream sstr("1 2"); //sstr.str() = "1 2"; としなくてもstringstreamクラスのコンストラクタの引数に入れてしまえば出来る
int x,y;
sstr >> x >> y; //cin のようにしてstringstreamクラスのオブジェクト内の文字列を変数に代入できる
cout << x << endl;
cout << y << endl;
}
---------------------
(結果)
1
2
---------------------------------------------
sstrへ入れる文字列にスペースがある。
---------------------------------------------
int main(){
stringstream sstr("12");
int x,y;
sstr >> x >> y;
cout << x << endl;
cout << y << endl;
}
---------------------
(結果)
12
0
---------------------------------------------
スペース入れないと1と2じゃなくて12扱い。
---------------------------------------------
int main(){
stringstream sstr("hy");
char x,y;
sstr >> x >> y;
cout << x << endl;
cout << y << endl;
}
---------------------
(結果)
h
y
---------------------------------------------
char型の場合は繋げても大丈夫。
stringクラス
stringstreamクラス
超便利。
ここまで