「C言語」の「文字列操作関数」が難解だった・・・
「文字列の操作」について学び忘れていたので、今回からは、「C言語」の「文字列操作」を学んでいきたいと思います。
もうほとんど学んだと思っていたのですが、学び忘れていたことが後からどんどん出くるので、きちんと学んでいきたい。
あと、「データ型の変換」も勉強していかないと・・・
「文字列操作」の関数
文字列を操作するための「専用の関数」が用意されているのですが、少しずつ関数の使い方について学んでいきたいと思います。
「strlen」関数
「strlen」関数は、「文字サイズ(バイト数)」を調べることができる関数です。
ただ、「バイト数」なので、「文字列の長さ」ではありません。
例えば、
#include <stdio.h> int main(void) { char data[2048] = "abcde"; int size = strlen(data); printf("string size=%d\n", size); return 0; }
と書いて実行すると、
string size=5
のようになります。
半角文字だけだと「バイト数=文字数」となっているのですが、全角文字が含まれていると、「文字数」ではなくなってしまいます。
例えば、
#include <stdio.h> int main(void) { char data[2048] = "おはよう"; int size = strlen(data); printf("string size=%d\n", size); return 0; }
のように、「日本語文字」を入れて、バイト数を見てみると、
string size=8
のようになるので、「日本語の全角文字」は、2バイトとして計算されているのがわかりますね。
ただ、「半角文字」と「全角文字」が混ざったらどうすればいいんでしょうか。
と思っていろいろと調べてみました。
すると、「_ismbblead」という関数で「マルチバイト文字」の1文字目かを判定でき、「_ismbbtrail」関数で「マルチバイト文字」の2文字めかを判定できるそうです。
なるほど。これを使って判定すると、文字数を数えることができそうですね。
と言いつつ、プログラムを書いてみても全くうまくいきませんでした。
プログラミング初心者にはちょっと難しい内容(^^;)
と思いながら2時間ほど悩んで、なんとか文字数を数えられるプログラムを作ってみました。
#include <stdio.h> int main(void) { int size = 0; // 全角と半角文字の混合 char data2[2048] = "おaは漢字一よqです。うq2"; size = strlen(data2); printf("size=%d\n", size); int i = 0; int count = 0; while(1){ printf("i=%d\n",i); if(data2[i] == '\0'){ break; } else { // 全角(漢字)文字の1文字目かどうかを確認 if( _ismbblead(data2[i]) != 0 ){ printf("先頭\n"); if(data2[i+1] == "\0"){ break; } i++; count++; // 全角(漢字)文字の2文字目かどうかを確認 } else if ( _ismbbtrail(data2[i]) != 0 ){ printf("後尾(%c)\n", data2[i]); count++; } else { printf("半角文字\n"); count++; } i++; } } printf("文字数=%d\n", count); return 0; }
何を判定しているのか見てみたかったので、判定結果も出力をしてみました。
すると、
size=24 i=0 先頭 i=2 後尾(a) i=3 先頭 i=5 先頭 i=7 先頭 i=9 先頭 i=11 先頭 i=13 後尾(q) i=14 先頭 i=16 先頭 i=18 先頭 i=20 先頭 i=22 後尾(q) i=23 半角文字 i=24 文字数=14
のようになり、全角と半角文字が混在している場合でも、「文字数」が無事に数えられています。
文字数を数えるだけなのに、「C言語」だとこんなに複雑なプログラムになるんですね。
「C言語」の難しさをこんなところでも実感したり・・・
「strcat」関数
ある文字列の後ろにさらに文字列を追加できるのが「strcat」関数です。
この関数は、
strcat(ベースの文字列, 追加する文字列);
のように指定していきます。
例えば、
#include <stdio.h> int main(void) { // 全角と半角文字の混合 char data[2048] = "あいうえお"; printf("文字列追加前=%s\n", data); strcat(data, "かきくけこ"); printf("文字列追加後=%s", data); return 0; }
のようにプログラムを作成し、実行してみると、
文字列追加前=あいうえお 文字列追加後=あいうえおかきくけこ
のようになります。
この関数を利用する場合は、「配列のサイズ」に気を付けて利用する必要があり、「文字列を追加後の文字サイズ」が、あらかじめ作成した「配列のサイズ」に収まっているかを確認しながら利用していく必要があります。
もし、サイズをオーバーしてしまったら・・・「バッファオーバーフロー(バッファオーバーラン)」と呼ばれる、「メモリ内容の上書きによるデータ破壊」が起こってしまいます。
「C言語」の関数を調べていると、こういう注意書きをしているドキュメントが結構多いので、初心者の自分は「ドキッ」としてしまいますね(^^;)
「strcpy」関数
「文字列データのコピー」が行えるのが「strcpy」関数です。
「文字列のデータを格納した配列」と「コピー先の配列」を用意しておき、「strcpy」関数で値をコピーするのですが、プログラムを書いてみると、
#include <stdio.h> int main(void) { // 全角と半角文字の混合 char data1[2048] = "あいうえお"; char data2[2048] = ""; printf("before data1=「%s」\n", data1); printf("before data2=「%s」\n", data2); strcat(data2, data1); printf("after data1=「%s」\n", data1); printf("after data2=「%s」\n", data2); return 0; }
のようになり、これを実行してみると、
before data1=「あいうえお」 before data2=「」 after data1=「あいうえお」 after data2=「あいうえお」
のように表示されて、「data2」の配列に「data1」の文字列がコピーされているのがわかりますね。
この関数も、「コピー先の配列のサイズ」が、「コピー元のサイズ」より小さいと、メモリの内容を上書きしてしまうそうなので、使う時には気を付けないといけませんね。
初めは「代入演算子」でコピーができるんでは?と思っていたのですが、配列の変数には「配列の先頭要素のメモリアドレス」が入っているので、代入演算子が使えないことに気が付きました。
「strcmp」関数
「strcmp」関数は、「文字列の格納された配列変数」の文字列が等しいかを調べることができる関数です。
この関数は、
strcmp(文字列配列1, 文字列配列2);
のように利用していきます。
文字列の配列の値が等しいと、戻り値には「0」が返ってきます。
例えば、さっきのプログラムに追加をして、
#include <stdio.h> int main(void) { // 全角と半角文字の混合 char data1[2048] = "あいうえお"; char data2[2048] = ""; printf("before data1=「%s」\n", data1); printf("before data2=「%s」\n", data2); int i = strcmp(data1, data2); if( i == 0 ){ printf("data1とdata2の文字列は等しい\n"); } else { printf("data1とdata2の文字列は等しくない\n"); } strcat(data2, data1); printf("after data1=「%s」\n", data1); printf("after data2=「%s」\n", data2); i = strcmp(data1, data2); if( i == 0 ){ printf("data1とdata2の文字列は等しい\n"); } else { printf("data1とdata2の文字列は等しくない\n"); } return 0; }
のように書くと、
before data1=「あいうえお」 before data2=「」 data1とdata2の文字列は等しくない after data1=「あいうえお」 after data2=「あいうえお」 data1とdata2の文字列は等しい
のように表示されます。
「文字列操作」の関数について学んできましたが、「C言語」の文字列操作は、他のプログラム言語と比べると、難しいという印象でした。
特に「バッファサイズ」の管理が大変ですね(^^;)
初心者には「学ぶハードルが高い言語」というのが正直な感想ですが、もっと勉強していきたいと思います。
→(前へ)「C言語」の「ファイル操作の仕組み」とプログラムの書き方を学ぼう!