Version 5.07
C ランタイムライブラリ
「では前回の続き」
void ReplaceTo_strlen()
{
TRACE( "%d\n", strlen( "ABC" ) );
// 3
}
『この strlen() ってのが、文字列の長さを調べる謎の関数なのね。あ、
strlen って string の length ってこと?』
「そうそう、その略ね。この strlen() を MSDN で調べてみて」
『あ、載ってるんだ。ダブルクリックしてF1!』
【strlen、wcslen、_mbslen、_mbstrlen】というページが表示される。
『うわ、〈文字列の長さを取得します〉だって。べたな関数だわ……。あれ、
戻り値が size_t っていうのになってるよ』
「これは unsigned int と同じ。えっと、それ選択してF1押して」
『あ、そーやっても見られるんだ』
【標準型】というページが表示される。
『うおいっぱい。あ、 size_t あった。あー unsigned int 、 sizeof 演算
子の結果だって。はれ、 sizeof って演算子だったの? 関数だと思ってた』
「まあ、 + とかの演算子とは違うけどね。 C++ 言語そのものには、関数っ
て入ってないから」
『関数がないの? なんで?』
「プログラミング言語に余計なものは付けない、っていうのが C++ 言語の
基本姿勢、ってところかな。代わりに他が付けてくれればいいから」
『ってことは、他が付けてくれた関数があるんだ』
「そう、たとえばこの strlen() とか」
『あ、これがそれなんだ!』
「えっと、ひとつ前に戻って、 strlen() のページ表示して、その下の方
に【文字列操作ルーチン 】っていうのがあるから」
『そのページを表示っと』
【文字列操作】というページが表示される。
『うお、またいっぱいなんかある……』
「で、そしたら左上の【同期】ってアイコンを押して」
『アイコン? あ、【編集】メニューの下にあるのね』
押すと、左の枠が【目次】に代わり、ツリーが表示される。
【カテゴリ別ランタイム ルーチン】の【文字列操作】が反転表示されてい
る。
『これって本の目次みたいなもん?』
「そう、たとえば【時間管理】っていうのあるでしょ」
『うんある』
【時間管理】ページが表示される。
「ここに表示されている関数を使うと、時間が取得できたりするから」
『ほー、なるほど』
「こういった、この【カテゴリ別ランタイム ルーチン】にある関数群を
【 C ランタイムライブラリ】って言います」
『しーらんたいむ?』
「あ、あと【標準 C ライブラリ】とか言うこともあるし、【ランタイム】
って略して言うことが一番多いかな」
『ランタイム……』
「〈ランタイム〉っていうのは実行中って意味だけど、これはそう考えると
混乱の元かも。ランタイムのいいところは、いろんな開発環境に入ってるこ
と」
『どゆこと?』
「ウィンドウズだけじゃなくて、マックとかでもアプリを作る必要があるわ
けで、そういうマック向け開発環境とかでも C ランタイムライブラリは使
えるってこと」
『だから標準 C ライブラリ、なわけね』
「そう、でもこれも色々あるライブラリのひとつ。 Ver 2.14 ( No.025 )を
読み返してみて」
『うお、タイトルが【いろんなライブラリ!】だ! あ、このランタイムと
MFC って同じよーなもんなんだ』
「そういうこと。プログラミングをするってことは、基本的には〈ある機能
を持つ関数やクラスを使うこと、なければ作ること〉なわけ」
『そのいろんな関数が、いろんなライブラリに入ってるんだ』
「ここで重要なのは、どのライブラリにどんな機能があるのか、ってことを
憶えておくこと」
『げ、それって憶えておかないとダメ?』
「駄目。プログラムを組んでるときに〈あ、この機能はあのライブラリのを
使えば〉って思い付く必要があるから」
『あー、思い付かなかったら自分で作るハメになるわけだ、あたしみたいに』
「そういうこと。ちょっと前まで MFC と API の使い方を見てきたのも、ダ
イアログの操作とかは MFC のクラス使えばいいんだ、っていうのを分かっ
てもらうため」
『そーゆーのが MFC の得意分野なんだね。ランタイムの得意分野は?』
「 strlen() みたいな文字列操作とか、時間管理とか、ファイル処理とか。
でも……」
『でも?』
「そういうのって MFC にもあるんだよね」
『じゃ、ランタイム要らないじゃない!』
「それは火美ちゃんが決めること」
『へ?』
「両方ともちゃんと知って、自分で、どっちを使えばいいのか、決める必要
があるってこと」
『な、なんかそれって重荷でなくない?』
「ま、そういうところも教えていくから。さてここで、文字列を受け取る、
ってことを考えてみましょう」
『あ、そう言えば受け取るってしたことないね』
「たとえば、文字列のコピーをするランタイム strcpy() の例で見てみよう
か」
void Use_strcpy()
{
const char chSourceAry[] = "ABC";
char chDistAry[256];
strcpy( chDistAry, chSourceAry ); // ここで使ってます。
TRACE( "%s\n", chDistAry );
}
『 strcpy() がコピーしてるの?』
「そう、第2引数の文字列から、第1引数の文字配列にね。 MSDN 見れば分
かるけど、第2引数は const char * 、第1引数は char * になってるから」
『なるほど、コピー元は書き換えないから const なんだ』
「さて、ここで注目して欲しいのは、 chDistAry の要素数が256ってこと」
『お、256という数字に何か意味が』
「ない」
『ないんかい!』
「とりあえず〈ある程度大きな数字〉っていうだけ」
『もし、たとえば要素数1にしたらどうなるの?』
「はみ出る」
『げ、つまりあのメモリ上で考えると、隣に書き込んじゃうってことよね』
「そういうこと。前も言ったけど、配列の要素数を知る術はないから」
『ポインタにしちゃうと sizeof 効かないのよね。じゃーさ、こういうのは
どう?』
void CannotChangeLength()
{
const char chSourceAry[] = "ABC";
char chDistAry[ strlen( chSourceAry ) ]; // エラー。
// error C2057: 定数式が必要です。
}
『ぎゃ、エラー出ちゃった!! なんでぇ?』
「前に言ったでしょ、配列は、作るときに要素数がしっかり分かってないと
ダメなの」
『あ、前回 const char chAry[] = pch はダメだったもんね。それと同じな
んだ』
「そういうこと。配列を使うと、こんなふうにサイズが固定されちゃうから」
『仕方なくおっきな数字? なんか不安〜』
「ま、少ししたら教えてあげるけど、 new や CString っていうを使うと問
題ないから」
『あ、どっちも見たことある! new は Ver 4.13 ( No.063 ) で見たよ。
あ、変数を新しく作るのなんだ』
「だから、これなら好きなサイズだけメモリを確保できるわけ」
『おお!!』
「 CString は Ver 3.20 ( No.045 ) で文字列リソースから読み込んだりし
たときに使ったよね」
『うん、そうそう。考えてみたら、あれが今使ってる文字配列の代わりに
なってるんだ』
「 CString が文字列関係の中で一番使いやすいと思うから、も少ししたら
ちゃんと使えるように解説することにします」
『はーい』
「というわけで、文字列を受け取るときには?」
『とりあえずの大きさの文字配列を用意する! だよね』
「そういうこと。付け加えると、文字列のコピーって言っても」
chDistAry = chSourceAry
「じゃできないから」
『当たり前じゃん、どっちもポインタなんだから。たぶん strcpy() は、要
素ひとつひとつを = で渡してるんじゃないかなー。なんか面倒ね』
「その辺大事。文字列は配列どうしの処理になるから、このコピーだけじゃ
なく、比較とか結合とかそういうのも全部特別な処理が必要になるわけ」
『あ、だからランタイムの【文字列操作】にあんなに関数があったんだ』
「そのページにある strcmp() が文字列比較、つまり〈同じ文字列か〉を調
べる関数で、 strcat() がふたつの文字列をくっつけるもの」
『 strlen() もそうだもんねー。文字列処理にランタイムは欠かせないわけ
だ』
「そのランタイムのひとつ、 sprintf() を使ってみましょう」
void Use_sprintf()
{
const int iSource = 123;
char chDistAry[256];
sprintf( chDistAry, "%d", iSource ); // ここで使用。
TRACE( "%s\n", chDistAry );
// 123
}
「これは、整数値を文字列に変換する関数」
『って、それって最初に言ってた目的じゃない!! なんだ、この sprintf()
ってのを使うとそれが簡単にできるのねー』
「ちなみに変換できるのは、整数値だけじゃないから。どっかで見たことな
い? %d とか」
『 TRACE() で使ってるのだ……あ、 sprintf() って TRACE() を真似した
んだ!』
「ちが〜う! sprintf() が先で、それに合わせて TRACE() がこういう設
計になってるの!」
『なんだ、逆なんだ』
「あーでも、これも正確には違うんだよね。左の目次から【入出力】
−【ストリーム入出力】を開いて、その中の printf() っていう関数を見
てみて」
『うん』
【 printf() 】のページが表示される。
「このページの真ん中へんに【書式指定】ってあるでしょ」
『うんある』
「このページに〈 %d は整数値を表示する〉とか書かれてるから。 R.3 て
ページに書いてあるよ」
『あ、ホントだ。 %d の他にもいろんなのあるんだね』
「 printf() は普通に文字列を出力する関数で、たいがいの C 言語の本に
はまず最初に書いてあるもの」
『? じゃーなんであたしには教えないの?』
「ウィンドウズのアプリは、ほとんどこれ使えないんだよね。他のOSなら
使う機会多いんだけど。その代わりに TRACE() 、ってこと」
『ほー、確かにアウトプットは便利だもんねぇ』
「と、話がそれたんでまとめ」
『えっと、ランタイムにはいろんな関数、特に文字列操作の関数がある』
「文字列を受け取るときは、文字配列を使う」
『んで sprintf() を使うと簡単に整数を文字列に変換できる、と』
/*
Preview Next Story!
*/
『なんかあっけないね、数字を文字列に変換するの』
「確かに関数ひとつだからね。でもベースの知識が大切だから」
『水希ちゃんそればっかり』
「というわけで次回」
< Version 5.08 LPCTSTR >
『につづく!』
「来週も基本的なことするよー」
『げげ』