さ ん ぷ る -------------------------------------------------------------------- STL & iostream 入門 (C)KAB-studio 2000 ALL RIGHTS RESERVED. http://www.kab-studio.com/ info@kab-studio.com 送信日: 2000/04/05(Wed) No.01 ( 全25回 ) 配信数: ???? 発行元: まぐまぐ( URL: http://www.mag2.com/ ID: 0000028819 ) -------------------------------------------------------------------- ・初めての方へ  このメールマガジンを初めて読むという方は http://www.kab-studio.com/Programing/STLiostream/  のページを必ず読んでください。このメールマガジンに掲載したサンプル プログラムの使用方法などが書かれています。 -------------------------------------------------------------------- STL アルゴリズムとは  STL は主に次の5つから構成されています。アルゴリズム、関数オブジェ クト、イテレーター、コンテナ、サポートクラスです。この中で最も重要な のが「アルゴリズム」です。他の4つはアルゴリズムのためにある、と言っ ても過言ではありません。というわけで、 STL の中でもまずこのアルゴリ ズムから見ていくことにします。  「アルゴリズム」は、一般的に「特定の結果を求めるための処理方法」と いう意味で使われています。たとえば「配列上のデータをソートする」など がアルゴリズムの一例です。  STL のアルゴリズムは、基本的に「別物」と考えた方が分かりやすいと思 います。使いこなせるようになれば「ああ、アルゴリズムだ」と思うように なるかもしれませんが、当分の間は「いわゆる一般的なアルゴリズムとは違 うもの」と考える方がいいと思います。  じゃあなんなのかというと、それはズバリ「 for などのループを代わり にしてくれる関数」です。 STL のアルゴリズムは、 for や while を使っ たループ処理を、代わりにしてくれる関数を集めたライブラリなんです。  というわけで、試しにひとつ使ってみましょう。 ///////////////////////////// // std::fill() の使用例。 #include #include // をインクルードしましょう。 void Use_fill() { int iAry[10]; std::fill( iAry, iAry + 10, 7 ); printf( "%d\n", iAry[3] ); // 試しに3番目を出力。 } // 結果 7 /////////////////////////////  この中で使われている std::fill() が、アルゴリズムに含まれている関 数のひとつです。何をやっているか順に見ていきましょう。  まず int 型の配列を作ります。要素の数は10個です。これはなんの初 期化もしていませんから、当然ゴミが入っています。  そこで出てくるのが std::fill() です。この関数は「配列の全要素に特 定の値を代入する」という仕事をしてくれます。ここでは、直前に作った配 列の全要素に、 7 という数字を代入しています。つまり、 std::fill() を 呼んだこの1行だけで、 iAry の初期化が完了したということです。  最後は試しに3番目の要素だけ出力してみたものです。もちろんすべての 要素に 7 が入っています。  std::fill() をもう少し詳しく見てみましょう。この関数の引数は3つ。 次のようになっています。 std::fill ( iAry // 1: 開始位置へのポインタ。 , iAry + 10 // 2: 終了位置+1へのポインタ。 , 7 ); // 3: 代入する値。  std::fill() は、「第1引数から第2引数−1までの各要素に第3引数を 代入する」という仕様になっています。  通常は、第1引数には「配列の先頭ポインタ」を、第2引数には「配列の 先頭ポインタ+全要素数」を渡します。この「全要素数」が使えるように、 第2引数は「終了位置+1」を受け取る仕様になっています。これはアルゴ リズム全体の仕様です。  さらに、 std::fill() の中身について見てみましょう。 std::fill() は、 呼ばれたときこんな感じの実装になっています。 void fill ( int *p_pBegin , int *p_pEnd , const int &p_rValue ) { for( ; p_pBegin != p_pEnd; ++p_pBegin ) *p_pBegin = p_rValue; }  配列へは、 for ループとポインタを使って値を埋めていきます。  第1引数の「配列の先頭ポインタ」は、第3引数を入れてはインクリメン トする、ということの繰り返しを for ループで行われます。そして、イン クリメントされたポインタが第2引数の「終了位置」と同じになったら for ループを終了させ、関数が終了します(なので「終了位置」には値が入らな い仕組みになっています)。  このように、 for ループを使った思いっきりべたべたな方法で、配列の 各要素に値を入れています。  このようにアルゴリズムは、単に「 for ループを代わりにしてくれる」 だけの機能です。次回は「なんでこれが役立つのか」を見ていきましょう。 *********************************************[かぶスタCM]*********  なにぃ、かぶスタを知らん!?  http://www.kab-studio.com/ *********************************************[かぶスタCMでした]*** C++ 名前空間&ヘッダーファイル名  STL でも iostream でも、 std::fill() とか std::strstream だとか、 どれも頭に std:: っていうものがついています。これを「名前空間」とい います。  例えば、 namespace Name { void Func() {} // なんかの関数。 }  とすると、 Func() 関数は Name:: という「苗字」が付いて Name::Func()  という関数名になります。これを「関数 Func() を名前空間 Name で囲ん だ」と表現します。  名前空間が違えば、同名の関数も別の関数だとコンパイラは判断します。 「田中太郎」と「佐藤太郎」を別人だと判断するのと同じですね。  STL や iostream などの「標準 C++ ライブラリ」に含まれる関数やクラ スは、すべて std という名前空間で包まれています。なので、 std:: とい う苗字がついているわけです。そのため、もしうっかり fill() という関数 をあなたが作っても、問題なくどちらも使えるというわけです。  std:: を付けるのが面倒という人は、 using namespace std;  とすると、付けずに使うことができます。  ただ、この「 STL & iostream 入門」では「どれが STL や iostream の ものなのか」を簡単に識別できるように、 using を使わずに、すべて std:: を付けることにしています。  もうひとつ、ヘッダーファイル名について。  サンプルコードでは #include #include  といった感じにインクルードされています。これは誤字脱字ではなく、こ ういうヘッダーファイル名なのです。  標準 C++ ライブラリのヘッダーファイルは、すべて拡張子が付いていま せん。これは他のライブラリと競合しないようにするためです。これは名前 空間と同じ理由ですね。  ちなみに、標準 C++ ライブラリは完全に標準 C ライブラリを含んでいて、 標準 C ライブラリのヘッダーファイルは「拡張子が取れて、頭に c が付く」 形式になっています。なので #include  でも構いません。  あと、古い標準 C++ ライブラリでは、拡張子付きのヘッダーファイル名 のままでした。他のサイトのサンプルコードがいつ頃の仕様かを判別するの に役立つかもしれません。 *********************************************[かぶスタCM]*********  2年目へと突入する #pragma twice  最強の Visual C++ 講座として爆進中!  http://www.kab-studio.com/Info/MailMagazine/ *********************************************[かぶスタCMでした]*** iostream 文字列操作  C 言語には「文字列型」が存在しません。「文字列」を格納する場合、通 常「char 型の配列」を使用します。配列の要素ひとつひとつが、文字ひと つひとつに当たるとみなして操作します。  ですがこの文字配列は、文字列を操作するのには不便すぎます。たとえば 「文字配列に文字列をコピーする」ということを直感的に行おうとすると、 次のようになります。 void BadCharCopy() { char ch[128]; ch = "Nya"; // 文字列をコピー……できません。 }  このコードはコンパイルエラーが発生するでしょう。これは「ポインタど うしの処理」と見なされてしまい、文字列とはまったく関係がないからです。  そこで登場するのが iostream です。  文字列操作には iostream に含まれる std::strstream というクラスを使 用します。 std::strstream は文字配列に文字列をコピーするためのクラス です。使い方は簡単。 std::strstream 型の変数を作って、そのときに文字 配列へのポインタを渡してしまえばいいだけです。 ///////////////////////////// // std::strstream の使用例。 #include #include #include // をインクルードしてください。 void CharCopy() { char ch[130]; std::strstream cStrStrm ( ch // 文字配列へのポインタ。 , 128 // 書き込める範囲。 , std::ios::out ); // 書き込み専用。 cStrStrm << "Written.." << std::endl << std::ends; printf( "%s", ch ); // 文字配列を渡していることに注意。 } // 結果 Written.. /////////////////////////////  まず空の文字配列を作成します。この文字配列は「文字列を受け取る」た めのものです。操作された文字列は、すべてこの文字配列へと送られてきま す。  次に std::strstream 型変数(ここでは cStrStrm )を作成します。  cStrStrm を作成するときに、同時に引数を渡す必要があります。 std::strstream は「特定の文字配列と読み書きする」というクラスだから です。そのために、cStrStrm を操作する前に「相手の文字配列へのポインタ」 を渡しておく必要があります。 cStrStrm を作成しているときに第1引数に渡 しているものが、文字配列へのポインタです。このポインタを通じて、文字 列を書き込むことになります。  また、文字配列を超えて書き込まないよう、文字配列のサイズを渡します。 cStrStrm を通じてデータを送っても、決してこの値を超えて文字配列へと書 き込むことはありません。  初期化の最後、「 std::ios::out 」は「書き込み専用」という意味です。 これから文字列を書き込むので、このフラグを渡します。  さて、 cStrStrm の準備ができました。では、 cStrStrm を通じて文字配列 へと文字列をコピーします。  まず cStrStrm へ文字列を渡します。渡す時には << という演算子を使い ます。 cStrStrm に向けて << を、その後ろに文字列を置きます。こうする と、 cStrStrm は文字列を受け取り、文字配列へとコピーしてくれます。  文字列をコピーしたあと、文字配列を閉じておきましょう。ダブルクォー テーションで閉じた文字列は「最後に終端文字( '\0' )が入っている」と 見なされますが、 std::strstream は、この「終端文字」はコピーしません。 代わりにちゃんと加えておく必要があります。  まず「 std::endl 」を渡します。これは「改行文字( '\n' )」を追加 します。次に「 std::ends 」を渡します。これが「終端文字( '\0' )」 を加えます。これを加えないと、文字配列が閉じられません。  さて、以上で「文字列のコピー」は終了です。文字列は文字配列へとコピー されました。つまり std::strstream は単なる仲介役です。 cStrStrm には 文字列はありません。文字配列の方に文字列があります。なので、文字配列 の方に文字列が入っているか、最後に確認します。  以上をまとめると、次のようになります。 1:文字配列を用意する。 2:「仲介役」 std::strstream 型変数を作る。 3:このとき「出力先」文字配列へのポインタを渡す。 4: << を使って文字列を std::strstream 型変数に渡す。 5: std::ends を渡して文字配列を閉じる。 6:文字配列に文字列がコピーされている。  さて、今回は文字列をコピーしましたが実際にはいろんな型の値をコピー できます。次回はその方法について見ていきましょう。 -------------------------------------------------------------------- ご注意!! ・このメールを返信しないでください。 ・ご意見・ご希望・ご感想・ご質問は[鏑矢の憂鬱]にお送りください。 http://www.kab-studio.com/Programing/KabuU/ ・購読登録を解除したいときにはこのページで行なってください。 http://www.mag2.com/m/0000028819.htm ・解除は自分で行なってください。 ・バックナンバーはこのページにあります。ただし最新版のみです。 http://jazz.tegami.com/backnumber/frame.cgi?id=0000028819 -------------------------------------------------------------------- STL & iostream primer. Weekly Mail Magazine. Written by Kaburaya Seiden. (C)KAB-studio 2000 ALL RIGHTS RESERVED. http://www.kab-studio.com/ info@kab-studio.com --------------------------------------------------------------------