Fig. 7 List 4 のサンプルラン akida : ¯/cmaga$ java L 土 s し 4 Bar@50ce5e0 = Ba て 50Ce5e0 ab = = ab = = > false ab. equal s (ab) = > true = > true 数値型については , 演算に先立って二項 数値プロモーションが適用される。その結 果 , オペランドの型が float あるいは double であれば浮動小数等値比較が , そうでなけ れば整数等値比較が行われる。浮動小数比 較については , NaN, -0.0 と 0.0 が特別な扱 いになるが , それは比較演算子の場合に準 boolean 型については , とくに注意点は ない。比較演算子との優先順位の違いから , 「 a く b = = c > d 」といった式は意味を持ちうる が , 「 a = = b く c ! = d 」は明らかにコンパイルエ ラーになることに注意してほしい。 両オペランドが参照型あるいは nu Ⅱ型の 場合には参照型に対する等値比較となり , この場合はオプジェクトの同一性のテスト が行われる。平たくいえばこれは , 参照値 ( すなわちオプジェクトへのポインタ ) の同 値テストである。「 = 」の場合 , 両オペラン ドがともに null であるか , あるいは同一の オプジェクトへの参照であれば true が , さ もなければ false が返される。この場合 , 両 オペランドが string 型であっても , あくま でオプジェクトとしての同一性を比較して いることに注意したい。したがって , Strin g 型の変数 a , b の値がそれぞれ " a ' "b" で あったとしても , 「 "ab"==a + b 」という等値 比較の結果は常に false である。両者は文字 列としては同じ内容であるが , オプジェク トとしては別物になるからだ。文字列とし て内容の同一性を比較するには , クラス St ring の equals メソッドを用いて , 「 "ab . equ ホ ( a + b ) 」という呼び出しを行う必要がある。 List 4 にこの例を示した。このプログラム 94 C MAGAZINE 2001 3 Java フ恤クラミングリファレンス 詳説 JDK 解体新 では , 最初に変数 f00 と bar が保持している 参照値の等値比較をしている。両変数は異 なるクラス ( ただしクラスの階層関係はあ る ) 型であるにもかかわらず , 実際には同 ーオプジェクトへの参照値を保持している ため , 等値比較の結果は true となっている (Fig. 7 ) 。 ついで優先順位が高いのはビット演算子 である。実際には 3 種類のビット演算子が 定義されていて , それぞれ , ビット積「 & 」 , ビット排他的和「 ^ 」 , ビット和Ⅲであり , この順に 3 段階の優先度が設定されている。 したがって , 「 a&bAc&dle&fAg&h 」という と結合する。 ビット演算子のオペランドは , ともに基 本整数型であるか , あるいは boolean 型で なければならない。基本整数型の場合は , 演算に先立って両オペランドに二項数値プ ロモーションが施される。このプロモーシ ョン後の型が結果の型となる。そして両オ ペランドの値の 2 進表現に対してビット AN D, ExclusiveOR, OR が求められる。一方 , オペランドが boolean の場合は , 同様に真 理値に対して論理 AND , Exclusive OR, OR ピ、ト演子 が求められる。 となる。 この場合の結果は boolean 条ー論理演算子 その次には , 条件論理演算子が優先され る。こちらも実際には , 条件論理積「 & & 」 がより優先し , ついで条件論理和「旧とな る。 C / C + + とは違って , 条件論理演算子の 両オペランドは boolean でなければならな であり , いずれもまず左オペランドを評価 一方 , 評価順序については C / C + + と同様 し , その時点で式全体の値が確定できれば 右オペランドは評価しない。具体的には , 「 & & 」の場合 , 左オペランドが偽であれば ただちに式全体の値も偽となり , 「旧の場 合には左オペランドが真であればただちに 式全体の値も真となるため , これらの場合 には右オペランドが評価されない。 条件論理演算子でおもしろいのは , これ らの演算子は構文上は左から結合すること になっているが , 実質的には結合の順序に は影響を受けないという点である。すなわ 各部分式の評価の有無 , 評価順序 , 全体と しての結果などを含めて , まったく同じな のである ( 「旧でも同様 ) 。 次の優先順位は条件式である。 C / C + + と 同様に , 「 a ? b : c 」という形をした三項の演 算子である。「 ? 」の左に記される第 1 オペラ ンドは boolean でなければならない。一方 , 「 ? 」と「 : 」の間に記される第 2 オペランドと , 「 : 」の右に記される第 3 オペランドの型は , 次の 3 種類の場合がありうる。 ・両方とも基本数値型 ・両方とも b00 an 型 ・両方とも参照型か nu Ⅱ型のどちらか 式 果が true であれば第 2 オペランドを評価し , まず , 第 1 オペランドを評価する。その結 条件式の実行手順は以下のとおりである。 うに細かく分かれている。 型の組み合わせに応じて , Fig. 8 に示すよ あり , 第 2 オペランドと第 3 オペランドの 条件式自身の型を決めるルールは複雑で には記すことはできないのだ。 上 void メソッドの呼び出しが許される場所 「値」が必要な場所に記すものであり , 構文 呼び出しであってはならない。条件式は ランドの一方または両方が void メソッドの これから明らかなように , 第 2 , 第 3 オペ
渡ってきた場合無視して通過してしまいま す。 m 。 d を呼んだ側は文字列が修正され ることを期待しているので , その影響は , あとで同じ文字列データにアクセスしたと きに , 期待する形と実際のデータが異なる という形で発覚することになります。これ では , いつデータがおかしくなったのかの 特定が困難になってしまいます。なお , こに誤った引数が渡ってくるのは , ユーザ や環境のせいではなくプログラマのせいで あると期待されるので例外を投げるよりも asse れで止めてしまうほうが適切です では , B のようなコードを避け , A のよう なコードを書くにはどうすればいいでしよ うか ? もちろん最初からいい状態のコー ドが書けることはあまりありません。 C + + に限ったことではないですが , プログラム は最初に書かれたときはきれいでも機能拡 張やバグフィックスのために徐々に全体の 見通しが悪くなり , 保守性は劣化していき ます。そのため , ときどき立ち止まり , 「機 能を変えずにコードの品質を上げる」こと を目標にした作業が必要になってきます。 この作業を , ソフトウェア工ンジニアリン グの世界ではリファクトリング (refactoring) と呼びます。プログラムは自動車などと同 様 , ときどき整備・点検をしないといけな いものなのです。 リファクトリングにおいては , たとえば 次のようなことに注意が払われます。 ・クラス名 , 関数名 , 変数名には機能に 対し適切な名前が付いているか ・複数の場所で同じようなことをしてい る場合 , これを関数にまとめることは できないか ・ 1 つのクラスで多くの機能を実装して いる場合 , 分割できないか ・実行時のエラーのとき , 起こった場所 と理由がわかるようになっているか ・オブジェクトを操作する理不尽な制約 があるとき , これを取り外せないか ・関数の引数やオブジェクト間に無用な 32 C MAGMINE 2001 3 依存関係はないか ・同じ計算を何度もやっていて , 効率の 悪いことをしていないか ほかにもいろいろあると思います。リフ アクトリングを行うと , コードの品質が向 上するだけでなく , 自分自身の頭のなかで も全体の構造を整理し直すことになるので , 新機能を追加するにもどこをどう変えれば よいのかがわかりやすくなります。 私の経験では , 次のようなことが気にな りだしたらリファクトリングの実行を検討 すべき時期です。 ・コードの断片をコピーしてきて , ちょ っと修正して使うことが多い ・型のキャストを多用するようになって ・ 1 つのバグを修正するのにあちこちを 直さないといけない ・単純なコーティングミスによるバグか 多発している 機能を変えずにいろいろな修正作業を行 うという意味では , チューニングというも のもあります。こちらはパフォーマンスの 向上に主眼を置いているのに対し , リファ クトリングはプログラマの理解を高め , 次 の機能拡張への準備をすることが中心です。 コンピュータのためでも利用者のためでも なく , 製作者を助けるのがリファクトリン グの使命です。実際には , とくにビジネス の現場でのプログラミングでは , 短期間・ 低コストで完成させることが重要な課題に なりがちであるため , リファクトリングは おざなりになることがしばしばありますが 長期にわたってつきあうプログラムにおい てはときどきリファクトリングを実施する ことは高い効果があります。 「問 11 」 ②特定の型において異なる実装を与える ことができ , テンプレートの運用範囲 が広くなる ・解説 テンプレートに関する問題です。テンプ レートの specialization は , C + + のなかでもか なり高度なトピックなので知らない読者も 少なくないはずです。また , 今のところコ ンパイラによってはサポートが部分的にし かされていないこともあるので , どこでも 使えるというわけではありません。上級者 向けの話題として読んでください。 テンプレートとは , 何らかの型を引数に して初めて具体化するクラスや関数である ことを再確認しましよう。これにより , た とえば STL においてはタイプセーフなコレ クションクラスが手軽に利用可能になりま した。しかし , どのテンプレート引数にも 同じコードで期待する動作をするわけでは ありません。例題として , 2 つの引数の比 較結果を返す関数 c 。 mpare を書いてみます。 普通にテンプレートを使うと以下のよう になります。 template<class T> b06 compare (const T& l, const T& 「 ) { return ーく r; } これは , 型 T に対して " く " で比較をしてい るため , プリミテイプ型であれば通常の大 小比較を , ユーザ定義クラスであればそれ に対応した叩 erator くを起動することになり ます。しかし , T が char * である場合はど うなるでしようか ? この場合は , 単純に " く " で比較するとアドレスの大小による比 較になってしまいます。これはたいていの 場合 , char * の比較としては望ましくない 挙動でしよう。 そこでテンプレートの specialization を使 います。これは , テンプレート引数が特定 の場合に特定の実装を提供するものです。 この例の場合は , 次のように書きます。 template<> boolcompare<char* >(const char* し const char* 「 ) { return strcmp(), r) <0; } template く >" という語句が specialization
特集 プログラミング 期末試験 立性を著しく損ない , ほかのクラスへの依 び出しと同じです。オプジェクトをデータ 「問 6 」 存性が非常に高くなります。一般的には , メンバとして持つ場合は , ここにコンスト friend を利用する前にもう一度クラスの設 ラクタの呼び出しを記述します。 ①それぞれを引数に 3 回コンストラクタ 計を見直すほうがよいでしよう。 メソッドに const を付けた場合は , このメ を呼び , 配列を初期化する ②型変換ができないためコンバイルエラ ソッドは状態を変更しないという意思表示 い 5 」 になります。問題ではメソッド f00 に const ーになる が付いているので , X : : foo ( ) の定義におい ・解説 ては自身のデータメンバの変更ができませ ん。 this が const オプジェクトになるといい この問題は , 配列と explicit キーワードの ・解説 換えてもいいでしよう。たとえば , STL の 機能とを複合した問題です。まず配列から const の知識に関する問題です。 const は コレクションクラスのサイズを返すメソッ 解説しましよう。 C 言語にもあるキーワードで , 「中身が変更 ド size は内部状態にはいっさい変更を伴わ 配列は , クラスライプラリではなく , C + + されない」ことを示します。 const の目的は , ないので , const 付きで宣言されています。 言語に備わっている機能です。たいていは プログラマの不注意でおかしなデータを書 そして , 前述したように const 付きのインス ライプラリのコレクションクラスを使うほ き込むようなコードを書いてしまった場合 タンスに対しては , const メソッドの呼び出 うがすぐれていますが , 固定長かっサイズ にできるだけコンパイラが警告を出すため ししかできません。問題の ( イ ) は const メソ が比較的小さい場合には配列のほうがお手 と , 値が変わらないことを利用すると最適 ッド f 。 0 を呼び出していますが , 対象 xl は co 軽です。それは , 1 行でそれぞれに異なる 化コンパイルにおいて効率のよいコード生 nst なしなので問題ありません。しかし ( ウ ) コンストラクタ引数を与えることができる 成が可能になるためです。 は const 付きインスタンス x2 に対して非 cons からです。もし STL コレクションで同様の C + + で const を付けることのできる場所は t メソッド bar を呼んでいるのでエラーにな ことをしようとすると , 次の 3 つです。 ります。 vector<X> v ( 3 ) ; 最後に ( 工 ) です。これを見て , const テー ・テータメンバ for(int i=0; i<3; i + + ) タメンバを変更しているのでエラーになる ・メソッド と思った方もいるかもしれませんが , 実は のようにループを使って書かざるをえませ ・インスタンス インスタンスに const を付けるのは C 言語 工ラーにはなりません。データメン )Sb は ん。 にもあります。 const の付いた変数は変更で ポインタで , 参照先の型が constX であると 正確には , このような配列のまとめどり きないのと同様 , const の付いたオプジェク いうだけです。ポインタの変更はまったく はスタック上にとる場合に限られます。ヒ トは状態変更できません。具体的には , パ 問題ありません。好きな c 。 nstX * 型をセッ ープ上の配列は , プリックなデータメンバを書き換えること トできます。もし b への代入に制限を付け X * p = new X [ 3 ] ; のようにして確保しますが , この場合各要 と , const の付いていないメソッド呼び出し たいならば , constX* constb ; と書かない 素はデフォルトコンストラクタによって初 ができなくなります。 といけません。 一方 , データメンバに const を付けると 期化されるので , 個別のコンストラクタに 以上が C + + の const の使い方です。 const ( この問題のように , constinta; と書いた場 引数を渡すことはできません。 はプログラマとコンパイラの都合で導入さ 合 ) , 一度初期化するといっさいの変更は 次に explicit です。 C + + では 1 引数のコン れた仕組みなので , const_cast などを使っ ストラクタには特殊な性質ふあり , 暗黙の できなくなります。なので , ( ア ) はコンパ て本来許されていない操作をむりやり行う イルエラーになります。初期化はコンスト ことができます。もちろんこれによってプ 型変換を行います。上記の X には 1 引数のコ ラクタで次のように行います。 ログラムを読む人は混乱し , また見た目に ンストラクタがあるので , X::X(int a) : a(_a) も大変気持悪いものになります。キャスト X x = 0 ; はあくまでも抜け道なので , もし const にか と書くと , x::x(o) を呼び出して x を初期化 らむコンパイルエラーをなくすためにキャ するようなコンパイル結果が得られます。 ストを多用している場合は何か本質的な問 これが暗黙の型変換です。しかし , この挙 記法は基底クラスのコンストラクタの呼 題を抱えている可能性が高いといえます。 動が望ましくないケースもあります。たと 特集実力チェックプログラミング期末試験 c + + 言語編 27
あろう Ruby のⅱ ps というか小技はあと回し にして , まずはどんなときでも通用するよ うな大原則から述べていきます。まわりく どいと思われるかもしれませんが小技はし よせん小技 , 鉄則を知ったうえで使うべき なのです。 その高速化は本当に必要か ? 始めてみればわかりますが , どんなもの であれ高速化を狙ったプログラムの調整は とても楽しいものです。しかし , 手間瑕か けて高速化する必要が本当にあるかどうか は , あらかじめ考えておきましよう。その コードをそう何度も使わないとか , 実行時 間が非常に短いなどの理由でちょっとくら い遅くてもいい場合はそのまま放っておく べきです。なぜならこうした場所を懸命に 高速化処理を行っても , 苦労に見合いませ ん。 また , 高速化に伴ってコードに手を加え ていくと読みにくくなるかもしれません。 高速化が必要なコードは , たいていの場合 長期にわたって使う予定でしようから , メ ンテナンスコストが上がらないように読み 33.87 1 . 49 1.49 135.65 214.49 やすさを考慮することも必要です。 31.38 2 . 88 1.38 0 . 57 0 . 57 27.84 4 .10 1.23 613.28 アルゴリズムを見直す 4 . 26 4 . 29 0 .19 187.50 234.38 1 . 06 4 . 34 0 . 05 0 . 28 0 . 28 まず可能ならアルゴリズムを改良しまし 0 . 35 4 . 3 5 0 . 02 0 . 50 0 . 50 よう。小手先の改良はそのあとです。とは 0 . 35 4 . 3 7 0 . 02 0 . 52 0 . 52 0 . 25 0 .18 4 . 3 8 0 . 25 いうものの , これはなかなか難しいもので 0 .18 4 . 38 7 . 81 す。問題のサイズが可変の場合は , とくに 7 . 81 7 . 81 0 .18 4 . 39 コストのオーダに気をつけたいところです。 0 . 00 4 . 39 0 . 00 0 . 00 4 . 39 0 . 00 0 . 00 問題のサイズに対するオーダは , ビッグオ 0 . 00 0 . 00 0 . 00 0 . 00 4 . 39 ー記法で表されます ( コラム参照 ) 。 0 . 00 0 . 00 4 . 39 0 . 圓 アルゴリズムの解析法については , 誌面 0 . 00 0 . 00 0 . 00 4 . 39 では紹介しきれないので , 参考文献をいく 0 . 00 0 . 00 4 . 39 0 . 圓 0 . 00 0 . 00 つかあげておきます。まず , アルゴリズム 0 . 00 4 . 39 0 . 00 0 . 00 0 . 00 4 .39 の勉強をしたことがなければ , 「アルゴリ 0 . 00 0 . 00 0 . 圓 4 . 39 ズム』 [ ーのような教科書で一度勉強される 0 . 00 0 . 00 4 .39 ことをお勧めします。アルゴリズムの教科 0 . 00 0 . 00 4 . 39 書はたくさんあるので購入する場合は W eb などで評判を調べてから買うのがよいと 思います。また『 C 言語による最新アルゴ [ 0ku91 ] リズム事典』のような便覧には効率が よいことがわかっているアルゴリズムもた くさん載っているので , このような本をと きどきめくって , どの問題がどんな名前で 呼ばれているかを知ることができます。 実践的な議論や効果的な事例は , 近ごろ 改訂版の邦訳も出版された名著『珠玉のプ ログラミング』的で取り上げられていま す。また同時期に出版された『プログラミ ング作法』 [ ] もよいでしよう。本格的に 勉強したい人には「 le art of computer pro gramming 』。 78 や「アルゴリズムイントロダ [CL.O] クション』のような定番の教科書がお 勧めです。ちなみに筆者の場合は , 学部で [AHU&3] と Manna の教科 Aho-Hopcroft-Ullman 書 [ M " 74 ] で学んだのが最初ですが動的計画 Fig. 3 sam e / sieve. 「 b のプロファイルの結果 $ ruby - て profile sample/sieve. rb 1 圓 0 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 法などに関する高度な話題も含んでいる後 者は残念ながら大学の図書館などに行かな い限り現在では入手が困難です。 いらないことはしない あたりまえですが , しなくていいことを したら遅くなります。あからさまにいらな い処理を書く人はいないと思いますが , 紆 余曲折を経た結果 , ある部分がいらなくな ってしまっていることは , ときどきあるも のです。落ち着いたら一度点検してみては どうでしようか。 時間のかかっているところを探す アルゴリズムの改良が終わり , 不要な処 理も削ったあとは , 細かな工夫をするフェ イズに入りましよう。工夫するには工夫す べきところを探すのが先決ですが , 時間が 宅 cumu lative se げ se げ time seconds seconds ca Ⅱ s ms/ca Ⅱ 0 . 01 0 . 01 0 . 01 0 . 00 0 . 00 0 . 00 0 . 00 0 . 00 0 . 00 0 . 00 0 . 00 0 . 00 0 . 00 0 . 00 11 2410 2 1 168 31 30 1 1 1 2 1 1 1 1 1 1 1 11 1 37 , 41 , tota ー ms/call 4406 ・ 25 2070.31 0 . 00 7 . 81 43 , 47 ( ・・・以下略 ) name Fixnum# step Array# [ ] = Range#each Array#join F ixnum#to—s Fixnum# 十 Array# [ ] Fixnum# く Math. sqrt Array#compact Kerne l. I nteger IO#write F loat# く => Array# shi f t F loat#coerce F ー oat # し 0 ー土 Fixnum# く => Kerne に puts Array#cI one Fixnum# * #top 厄 v 引 伝授 ! 極めよ Ruby 道 83
みましよう。 list-t 叩が NULL ならば , list->n になり , p の次の要素がⅱ st となれば OK です。 う。つまり , 辞書順に並べるということは , ext = NULL; という処理は , list->next = list 具体的な処理は , List23 のようになります。 strcmp で比較して , 文字列を小さい順に並 リストの最後の要素として新し top ; としても同じです。また , p->next が べることになります。 最後に リストの先頭の要素のメールアドレスが , い要素を追加する場合です。リストの最後 NULL ならば , list->next = NULL; は , list->n list->email よりも大きい場合 , リストの先頭 の要素が p だとすると , p->next は NULL のは ext=p->next; としても同じです。これらの を入れ替えることになります。新しくリス ことを利用すれば , 「まだ何も登録されて ずです。したがって , strcmp の引数には NU トの先頭になるのはⅱ st で , その次の要素 いない場合」と「先頭に追加する場合」を統 LL を指定できないので , list->email と p->nex は , それまでⅱ st ー t 叩が指していた要素とな t - > email が比較できないことに注意が必要で 合し , 「途中に追加する場合」と「最後に追 す。最終的には , p の次の要素を NULL から 加する場合」を統合できます。問題のプロ ります。したがって , 具体的な処理は , Lis list に変更し , list の次の要素はないので list t 22 のようになります。 グラムはそのようになっています。 次に , リストの途中に , 新たに要素を追 ->next は NULL にすれば OK です。具体的な もう 1 つ , あまり見かけない処理ですが 加する場合を考えます。リストの途中の要 処理は , List 24 のようになります。 1 行をタブで区切った部分に分離する処理 素 p と p の次の要素 p - > next との間に list を追 このように , 要素を「まだ何も登録され のなかで , sta ⅱ c 変数のポインタ bu を利用 ていない場合」「先頭に追加する場合」「途中 しています。関数を呼び出すと , 現在 bu ゆ 加する場合です。ただし , p->next は NULL に追加する場合」「最後に追加する場合」の 4 が指しているところから , タブまたは行末 ではないとします。この場合 , p->email よ 通りをそのままコーディングすれば , List 2 りも list->email が大きく , list->email よりも p が現れるまでを調べ , その部分を ma Ⅱ。 c で 確保した領域にコピーします。このとき , ->next->email が大きいということになりま 5 のようになります。 このままでもいいのですが , 少し考えて bu ゆは取り出したデータの次の文字を指す す。変更後には , list の次の要素が p->next ように変化しています。 sta ⅱ c 変数として指 定してあるので , 次に同じ関数を呼び出し ても , 前回の値はそのまま残っていること を利用しています。 [ 問 26 」 「 getc は使わないようにする」 「インデントにこだわる」 「関数ごとにコメントを書く」 「コンバイル時の警告メッセージは必 void add—list(List * は ) ずチェックする」 List * 店 if (list-top = = もも ) ( / * 初回のみ * / など , 何でも OK 。 list—>next = NULL ・ は s セユ op = は s 場 } e lse if ( strcmp ( list—top->email , は st → e ) > 0 ) ) { ・解説 / * 先頭に追加 * / list->next = list—top; list—top = は 8 場 解答例は , 模範解答ではありません。そ } else { fO て (p = は 8 セーセ op ー p->next ! = Nt ル p = p->next) { れなりの内容なら何でもかまいませんが , if (strcmp(p->next->email, list->email ) > 0 ) { / * 途中に追加 * / 自分なりにすぐに思い浮かべるようなこと list->next = p->next• p—>next = ー土 st ー があるかどうかがポイントです。プログラ ムを実際に何度も書いていれば , 何かある はずです。実際に書けなくても , 何か思い 浮かべることができたら正解としてくださ い。 1 分以内に思いつかなかった場合は , 1 分経過ごとに 1 点減点とします。 リスト list_top → NULL List / * 最後に追加 * / list—>next = NULL ・ p->next = は 8 list->next = NULL; ゑー〉れ ex しまは 8 場 22 C MAGAZINE 2001 3
ソフトバンクバブリッシング・ダイレクト会員規約 ソフトバンクバブリッシング株式会社 ( 以下「 SBP 」といいます ) は、 その運営する通信販売サービスであるソフトバンクバブリッシン グ・ダイレクト ( 以下「本サービス」といいます ) の会員規約 ( 以下「本 規約」といいます ) を以下の通り定めます 第 1 章総則 第 1 条本規約の範囲および変更 1 . 本規約は本サービスの利用に関し、 SBP および会員 ( 第 3 条で定義します ) に適用されるものとします。 2. SBP は、会員の事前の承諾を得ることなく、 SBP が適当と判断する方法で会員に通知することにより本 規約を変更できるものとします。 第 2 条本サービスの利用 2. SBP は、会員の事前の承諾を得ることなく、本サービスの内容を変更することができるものとします。 1 、会員は、本規約および SBP が別途定める本サービスに関するルール等に従い、本サービスを利用するもの 第 3 条会員 第 2 章会員 とします。 「会員」とは、本規約を承認いただいた上、 SBP 所定の手続に従い会員登録を申請し、 SBP がこれを承認し 第 4 条会員登録 た方をいいます。 会員は、住所、氏名、電話番号、電子メールアドレス、その他 SBP に届出ている事項に変更が生じた場合に 第 5 条変更の届出 であると SBP が判断する場合には、当該登録申請を承認しない場合があります。 した場合、入会希望者の申請内容に虚偽の事項が含まれている場合、その他登録申請を承認することが不適当 3. 入会希望者が過去に本規約違反をしたことなどにより会員登録の抹消などの処分をうけていることが判明 います ) を発行することにより申請を承認するものとします。 2. SBP は前項の申請に対し、会員番号および Web サイトで使用するバスワード ( 以下「バスワード」とい または SBP 所定の会員登録申込書を利用し、 SBP の指定する方法に従い会員登録申請を行うものとします。 1 . 入会希望者は、本サービスの提供する Web サイト似下「 Web サイト」といいます ) の会員登録ページ ( 4 ) 会員番号およびバスワードを不正に使用する行為 ( 3 ) クレジットカードを不正使用して本サービスを利用する行為 ( 2 ) 本サービスの運営を妨げ、その他本サービスに支障をきたすおそれのある行為 ( 1 ) 会員登録の際に虚の登録内容を申請する行為 会員は以下の行為を行ってはならないものとします 第 7 条禁止事項 ( 4 ) その他本規約に違反した場合 ( 3 ) 3 年以上本サービスの利用がなかった場合 ( 2 ) 第 7 条 ( 禁止事項 ) の行為を行った場合 ( 1 ) 本サービスに関する料金などの支払債務の履行遅延その他の不履行があった場合 会員登録を抹消することかできるものとします。 SBP は、会員が以下の各号の一に該当する場合、会員に事前通知することなく本サービスの利用停止または 第 6 条本サービスの利用停止、会員登録の取消 は、 SBP が別途指示する方法により、すみやかに SBP に届出るものとします。 会員情報を利用する場合があります。 2. SBP は、会員に対し SBP の商品案内等の目的で電子メールおよびダイレクトメール等を送付するため、 ( 3 ) その他、本サービスの運営に必要な場合 きない形式で第三者に提供する場合 ( 2 ) S 日 P が本サービスの利用動向を把握する目的で収集した個人情報の統計を、個々の個人情報として特定で ( 1 ) 会員が、自己の氏名、住所、性別、年齢、電子メールアドレスなどの開示に同意している場合 除き、第三者に開示または提供しないものとします。 1 . 本サービスの利用に関連して SBP か知り得た会員の情報について、 SBP は以下の各号に該当する場合を 第 10 条会員情報の利用 う漏洩等の危険性を認識し、自己の責任の下にこれを行うものとします。 6. 会員は、 Web サイトで本サービスを利用する際に行うクレジットカード番号の送信行為等の決済手段に伴 ちに SBP に連絡するものとします。 5. 会員は、会員番号およびバスワードが第三者によって不正に使用されていることが判明した場合には、直 き自ら責任を負うものとします。 4. 会員は、会員番号およびバスワードの管理不十分、使用上の過誤、第三者の使用などに起因する損害につ 3. 会員は、バスワードを第三者に譲渡、貸与、開示してはならないものとします。 2. 会員は、会員番号を第三者に譲渡、貸与してはならないものとします。 1 . 会員は、 S 日 P が発行した会員番号およびバスワードの管理責任を負うものとします。 第 9 条会員番号およびバスワードの管理 に、 SBP に何等の迷惑または損害を与えないものとします。 2. 本条の規定に違反して問題が生じた場合、会員は自己の責任と費用においてかかる問題を解決するととも る会員個人の私的複製等著作権の制限規定範囲外での使用をすることはできません。 1 . 会員は、権利者の許諾を得ないで、本サービスを通じて提供されるいかなる情報も、著作権法で認められ 第 8 条著作権 ( 8 ) その他、 SBP が不適当と判断する行為 ( 7 ) 公序良俗に反する行為その他法令に違反する行為、またはそれらのおそれのある行為 それのある行為 ( 6 ) 他の会員、第三者もしくは SBP の著作権、プライバシーその他の権利を侵害する行為、またはそれらのお 行為 ( 5 ) 他の会員、第三者もしくは SBP に迷惑、不利益もしくは損害を与える行為、またはそれらのおそれのある 第 3 章商品の購入 第 1 1 条商品の購入 1 . 会員は、本サービスを利用して SBP が出版する雑誌の定期購読サービス等のサービスを含む商品 ( 以下 「商品」といいます ) を SBP から購入することができます。 2. 会員は、商品の購入を希望する場合、 SBP が指定する方法に従って申込むものとします。 3. 前項の申込に対して、 SBP から電子メール、郵便等により承諾する旨の通知が会員宛に発信された時点で 会員と SBP との間に当該商品に関する ( 継続的 ) 売買契約が成立するものとします。ただし、会員指定のクレ ジットカード会社からカード与信不履行の旨の連絡があった場合はこのかきりではありません。 4. 前項の規定に関らず、本サービス利用に関して不正行為または不適当な行為があった場合、 SBP は ( 継続 的 ) 売買契約を取消もしくは解除、その他適切な措置を取ることができるものとします。 5. SBP は、商品の購入に関するサホートを、 SBP 定期購読センターを通じて行います。 第 1 2 条商品の送付 1 . 本サービスを利用して購入した商品の配送先は日本国内にかぎります。 2 . 商品は売買契約成立後、原則として 7 日以内に利用者に到着するように発送します。ただし、定期購読サ ービスに関する商品 ( 月刊誌等 ) については、発売当日中に利用者に到着するように発送します。 3 . 郵便事情、道路事情等による商品到着の遅れについて、 SBP は責任を負わないものとします。 4 . 商品の送付先は、会員の登録住所以外を指定することができますが、同一の注文番号で同じ商品を複数購 入した場合においても複数の送付先の指定はできないものとします。 第 1 3 条決済方法 1 . 商品の購入におけるお支払い金額は、商品の購入代金、取扱手数料および消費税の合計となります。 2. 本サービスによって購入された商品のお支払いに関しては、次の各号記載の方法、その他 SBP が別途認め るお支払方法によるものとします。 ( 1 ) SBP 指定の会員本人名義のクレジットカードによるお支払い ( 2 ) SBP 指定の振込用紙を利用した郵便振替によるお支払い ( 3 ) SBP 指定のコンビニエンスストアで、 SBP 指定の払込用紙を利用してのお支払い ( 4 ) SBP 指定の銀行口座への振込によるお支払い ( 振込み手数料は会員負担とします ) 3. クレジットカードでの支払の場合は、会員がカード会社との間で別途契約する条件に従うものとします。 なお、会員と当該クレジットカード会社等の間で紛争が発生した場合は、当該当事者双方で解決するものとし、 SBP には一切責任はないものとします。 第 14 条商品の返品および交換 1 . 商品の返品および交換は、配送中の破損、商品の瑕疵、商品間違い、その他 SBP が別途認める場合を除き できないものとします。 2. 本条に基づく商品の返品および交換は、会員が商品を受領した後 5 日以内に SBP 定期購読センターに通知 をした場合にかきり行いうるものとします。 3. 会員は、本条に基づく商品の返品および交換を、 SBP の定める方法および SBP 定期購読センターの指示 に従い行うものとします。 ( 2 ) 火災、停電、第三者による妨害行為等により、システムの運用が困難になった場合 ( 1 ) システムの定期保守および緊急保守の場合 サイトの提供の全部あるいは一部を中止することができるものとします。 SBP は、 Web サイトの稼動状態を良好に保っために、以下各号の場合会員に事前に通知を行うことなく Web 第 17 条 Web サイトの保守 第 4 章 Web サイトの運用 ます。 において売買される商品に関する損害、損失、不利益に関して第 13 条に定める以外の責任を負わないものとし 2. SBP は、法律上の請求原因の如何を問わず、いなかる場合においても本サービスの利用および本サービス することにより免責されるものとします。 1 . SBP は、会員が登録している連絡先へ連絡すること、および商品購入の際指示した送付先に商品を配送等 第 1 6 条商品購入に関する免責 び消費税のうち商品毎に定める金額を中途解約後 1 ヶ月以内に、 SBP の定める方法により返金します。 2. 前項により、会員が ( 継続的 ) 売買契約を中途解約した場合、 SBP は既に受領している商品購入代金およ 購読センターに通知することにより、中途解約することができます。 1 1 条に基づき成立した ( 継続的 ) 売買契約を、解約希望日の 1 ヶ月前までに S 日 P の指定する方式で SBP 定期 1 . 会員が購入した商品が SBP の出版する雑誌を継続的に購入する定期購読サービスである場合、会員は第 第 1 5 条中途解約 任も負わないものとします。 1 . SBP は、会員が本サービスをご利用になれなかったことにより発生した一切の損害について、いかなる責 第 1 9 条その他免責事項 きないものとします。 会員は、本サービスの利用に関して有する権利および義務を第三者へ譲渡し、または担保に供することはで 第 1 8 条権利義務譲渡の禁止 第 5 章一般条項 ( 3 ) その他、止むを得ずシステムの停止が必要と SBP が判断した場合 付則 : この規約は 1999 年 1 2 月 14 日からすべての会員に適用されます。 の専属管轄裁判所といたします。 3. 本サービスの利用に関して訴訟の必要か発生した場合には、日本法の適用の下、東京地方裁判所を第一審 SBP と会員との間で双方誠意をもって話し合い、これを解決するものとします。 2. 本サービスのこ利用に関して、本規約または SBP の指導により解決できない問題が生じた場合には、 1 . SBP と会員との連絡方法は、原則として郵便によるものとします。 第 20 条その他 該会員は自己の責任と費用において解決し、 SBP には一切迷惑を与えないものとします。 4. 会員が、本サービスを利用することにより、他の会員または第三者に対して損害等を与えた場合には、当 損失、不利益等に関して資任を負わないものとします。 3. SBP は、法律上の請求原因如何を問わず、いかなる場合においても本サービスの利用に関して生じた損害、 2. SBP は、会員の登録内容に従い事務を処理することにより免責されるものとします。
定期購読か新しくなりました ーソフーンク バブリッシングの、。冖。。ヮ ~ ・お申し込みは専用ハガキかインターネットをご利用ください。 ・お申し込みいただいた内容確認のため、注文明細をお送りします。 ・郵便局またはコンビニエンスストアからお支払いください。 ( 初回配本後支払用紙を郵送します ) ・ホームページからはクレジットカードでのお支払いが可能です。 ・送付先を複数登録して、自宅や勤務先など、雑誌ごとに受け取る場所を指定できます。 お申し込み方法 ー = お申し込みの前に必ず会員規約をお読みいただき、同意いただける場合のみお申し込みください。 巻末のハガキに必要事項をご記入のうえ、切手を貼らすに投函ください。 また、インタネットでは、一工スビーピーダイレクトホームページ (http://www.sbp-direct.com/ からお申し込みできます。 ークレジットカードをご利用の場合はホームページよりお申し込みください。 専用ハガキ インターネット お支払い方法 第一回配 振込川 注文明 局ピ お近くの郵便局または コンビニエンスストア でお支払いください。 手数料はかかりません。 お申し込み内容の確認 申込締切に間に合った 第一回酉の数日後に振 のため、注文明細をお 号からお送りします。締 込用紙をお送りします。 送りします。ご確認く 切は発売日の 1 0 営業 日前 ( 土日祝日を除く ) ださい。 です。 専用ハガキまたはホー ムへージからご注文く ださい。 お問い合わせ 【社屋移転のため、下記の通り住所、電話番号等が変更になりました。】 ソフトバンクバブリッシング株式会社定期購読センター 新住所〒 107-0052 東京都港区赤坂 4-13-13 TEL: 03-5549-1202 FAX : 03-5549-1212 E-mail : marketing@softbank.co.jp 今後とも弊社雑誌・書籍をご愛読いただけますようお願い申し上げます。 インターネットでの ソフトバンクバブリッシングダイレクトーホームページ http: 〃 www.sbp-direct.com/からお願いします。 お申し込みは ソフトバンクバブリッシング株式会社 Publishing
PerI 編・解答と解説 [ 問 1 」 ③ ・解説 Perl のコメントは「 # 」が現れたところから その行の最後までとなります。 「問 2 」 ② ・解説 イ 8 C MAGAZINE 2 1 3 ロックを囲んだり , 変数名の区切りを表し 配列を生成する場合に使います。目は , プ り , 配列のスライスを指定したり , 名なし す。 [ ] は , 配列のインデックスを指定した 配列に初期値を与える場合は ( ) を使いま ・解説 ② [ 問 3 」 します。 \ $ a と書けば , $ a へのリファレンスを意味 \ a というのは意味がありません。ただし , ハッシュは % を使って表現します。 現します。配列は@を使って表現します。 通常の変数 ( スカラ変数 ) は $ を使って表 れることもあります。 ハッシュです。ハッシュは連想配列と呼ば 列をキーとして参照することのできるのが です。これに対して , 数値ではなく , 文字 与えることで , 要素を指定することが可能 明らかなので , インデックスとして数値を ているデータ構造を持っています。順序が 配列は , その要素が順に並んで格納され たり , 名なしハッシュを生成する場合に使 $b = $tmp, $tmp = $a; 使って , 変数の入れ替えを行うには , 一時変数を ・解説 ① [ 問 4 」 います。 と表現することができます。これは , @a [ 3..5 ] または , @a[3, 4 , 5 ] までの要素を持つ配列スライスは , スライスと呼びます。 @a の 3 番目から 5 番目 して抜き出すことができます。これを配列 ます。 Perl では , 配列の一部分を , 配列と 要素は , $ a [ $ i ] でアクセスすることができ 配列スライスの応用です。配列の i 番目の ・解説 [ 問 5 」 で囲みます。 ができます。リストを作るには , 変数を ( ) リストを使えばより簡単に入れ替えること のように順に実行する方法もありますが , は , と同じ意味を持ちます。 という意味になるので , ことがわかります。 [ 問 6 」 ④ ・解説 目的に合っている 演算子「 . 」は , 文字列を連結する働きを します。 $a, $ b はそれぞれ文字列として 扱われ , それらを連結した結果が表示され ることになります。 print $a + $b, とすれば , $a と $ b の値を加算した値が表 示されます。 [ 問 7 」 PerI は数値の比較と文字列の比較とで , 異なる演算子を使います。数値の比較は等 しい場合「 = 」 , 等しくない場合は「 ! = 」です が , 文字列の場合は等しい場合「 eq 」 , 等し くない場合は「 ne 」を使います。これらを間 違えても , Perl のプログラムとしては正し い書き方なので , 工ラーにはなりません。 しかし , 動作させた結果が期待どおりにな らないので , 気がつかないとかなり悩むこ とになってしまいます。 ・解説 ・解説 [ 問 8 」 実は foreach ではなくて単に for と書いて
こでは , 存在しない値を指定して添字付 けを行った結果生じる IndexError を補足す るための t Ⅳ ~ except 文が 2 つ使われている。 そして , 関数 f 。。に渡した引数の値を 3 で割 った余りに応じて , 異なる動作が行われる。 まず余りがゼロの場合には , foo の内部 では t Ⅳ文を実行せずに直接 bar ( a , n ) を呼 び出す。この関数 bar の中で「 a [ n ] 」という 参照を行っているのだが , 添字の n の値に よっては IndexError 例外が起動されること がある。もしもこのケースで IndexError 例 外が起動されると , メインプログラム側の except 節に補足され , 「 no such index in a 」 と表示される。 Fig. 2 に示したサンプルラ ンの「 3 」のケースである。 こで , メイン の変数 x の値と , 「 = = > 」という文字列は , fo 0 を呼ぶ前に出力済みであることに注意し てほしい。 次に余りが 1 および 2 の場合であるが , こ の場合は関数 foo の内側で ( 動的に ) ネストし た t 文が実行されたうえで bar が呼び出さ れるので , f00 の内側の except 節が IndexEr ror 例外を補足する。その結果「 OOPS ! 」と いう文字列が表示される。さらに , 余りが 1 の場合に限っては , 引数なしの raise 文が 実行される。この文は , 「現在のスコープ 1 5 in [ 2 , 3. 5 , 7 , 1 1 , 13. 1 7 ] = 1 3 in [ 2 , 3 , 5 , 7 , 1 1 , 13. 1 7 ] = 1 1 in [ 2 , 3.5 , 7 , 1 1 , 1 3 , 1 7 ] = 9 in [ 2 , 3 , 5 , 7 , 11. 13. 1 7 ] = 7 in [ 2.3 , 5 , 7 , 1 1 , 1 3 , 1 7 ] = 6 in [ 2 , 3. 5.7. 11. 1 3 , 1 7 ] = 3 in [ 2.3 , 5 , 7. 1 1 , 13. 1 7 ] = 1 in [ 2 , 3 , 5 , 7 , 1 1 , 1 3 , 1 7 ] = Fig. 1 List 1 のサンプルラン = > 5 = > 4 = > 3 = > 1 Fig. 2 List 3 のサンプルラン 4 = = > OOPS! nosuch indexin a 3 = = > nosuch indexina 2 = = > OOPS! 0 = > 2 で最後に起動された例外を再起動する」と いう意味である。 List 3 の例の場合は , 関 数 foo の内側で補足した IndexError 例外が 再起動され , その結果メインの側の except 節で ( 再度 ) 補足される。そのため , 出力は 「 OOPS ! 」の後ろに「 no such index in a 」が続 けて表示される。 Fig. 2 の「 4 」のケースがそ れである。 一方 , 余りが 2 の場合には , 関数 foo の内 側で補足され , 例外処理モードから通常の 実行モードに戻る ( ただし「 OOPS! 」という 表示は行われる ) 。そして関数の値としてゼ 口が返される。 Fig. 2 の「 2 」のケースがこれ に当たる。 このように , 同じ関数 bar の中で発生し た IndexError でも , その関数がどのような 経路をたどって呼び出されているのかに応 じて , どの except 節で補足されるかが変化 する。これが例外の大きな特徴であって , 単なる大域 got 。文とは違う点である。 例外の例外 List 3 の関数 foo を , List 4 のものと入れ 換えるとどうなるであろうか。 tw—finally 文は , tw—except 文とは異な る文であり , の直後の節の実行が終わる 場合には , その実行がどのような手段で終 わろうと , すなわち通常動作が行われて最 後まで到達した場合でも , 例外が起動され て飛び越す場合でも , さらには return で抜 け出す場合でも , 必ずⅱ na Ⅱ y 以下のプロッ クが実行されるのである。このため , final ly 節は , どんな場合でも必ず実行しなけれ ばならない「後始末」コードを書くのに適し 4 = = > OOPS! f00 = = > no such index in a 3 = = > f00 = = > nosuch indexin a 2 = = > OOPS! f00 = = > 0 1 = = > f00 = = > 2 0 = = > f00 = = > 1 サンプルラン List 4 のように修正した場合の ている。 こで , プログラム言語フリーク的な興 味として , return の実行とⅱ nally 節の実行 の意味をどのように説明するかという点が ある。というのも , nally 節の説明として 「 try 節のプログラムが正常に終了しても , 例外が発生して飛び出す場合でも , 必ずⅱ nally 節の内容が実行される」という表現を 用いると , return 文で飛び出す場合はどう なるかが定かではないからだ。 この問題は , 「 re ⅲ rn 文では実は例外を発 生していて , すべての関数には return 例外 を処理する特別なハンドラがデフォルトで 用意されているのだ」といった解釈をする と , 見かけ上はエレガントに解決する ( bre や continue も同様 ) 。 たとえば ModuIa -3 という言語ではそのよ うな解釈を採用している。本連載でもしば しば引き合いに出すが , Modula-3 は , Mo dula -2 の思想を受け継いで新規設計された 言語で , とくにオプジェクト機能と例外処 理機能が洗練されている。 Modula -3 では , return が例外であるために try—finally 節 による実行のトラップも統一的に解釈でき るのだ。 しかし , , thon ではそうではなく , 「 retu rn が実行された場合 , 実際に関数から抜け 出す前に fina Ⅱ y 節の内容が実行される」と いった説明を行っている。このあたりは , 説明のテクニックといえるかもしれない が , 気をつけて調べてみるとおもしろいと ころである。 List 3 の関数 f00 を修正する # List 3 の f00 を以下と差し替える def foo(), n): try : if n 宅 3 = return て ( a , 司 # 余りゼロ Li st except IndexError : return bar(), n) try : finally: print ” print ” OOPS ! ” if n 3 = # 余り 1 raise e ー se : return 0 # 余り 2 f00 = = 〉 学問のススメ千言万語 1 57
ストをソートしています。 「問 9 」 ・解説 ② 1 8 C MAGAZINE 2001 3 ① れば十分です。したがって , 解答は 16 とな ですから , 16 個入るサイズの配列を用意す きます。 16 進数を表現する文字の数は 16 個 うどのサイズで配列を初期化することがで このような場合には , 文字列の長さちょ 納する必要はありません。 用いています。したがって , 最後に和 ' を格 るのではなく , char 型の変数の配列として こでは , hex_table は文字列として用い ・解説 はそこまで意識する必要はないのです。 がめんどうを見てくれるので , プログラマ です。このような細かいことはコンパイラ といって , 8 や 16 を指定するのは考えすぎ らないなどの制限があるからです。だから を複数バイト単位でアクセスしなければな があります。システムによっては , メモリ なく 8 バイトや 16 バイト消費される可能性 と定義したときに , メモリが 7 バイトでは システムの都合上 , 実際には charstrC7]; 解です。 あります。したがって , 1 を加算した 7 が正 最後に区切りのための和 ' を格納する必要が s ⅲ ng " という文字列の長さは 6 ですが したときに 1 を戻すという勘違いをしない よう注意してください。 与えられた文字列が異なる場合 , strcmp 関数は , その大小に応じて , 正または負の 値を返します。 C 言語編の最後の問題では , この性質を使ってメールアドレスの順にリ ・・ 3 ります。 16 を指定した場合 , 値が入るのは hex-table [ 0 ] から hex-table [ 15 ] の 16 個の要 素です。 これに対して , 17 を指定した場合は , he x table [ 0 ] から hex-table [ 15 ] は同様です が , hex-table [ 16 ] にヌル文字和 ' が入りま す。 [ 問 11 」 ・解説 prin ばに与える書式文字列の問題です。 文字列すなわち s ⅲ ng を与える場合には " % s ' を指定します。 " % d " は整数を与える場合に 指定します。①のように直接指定してもう まくいくこともありますが , str の内容に " % " が含まれていると破綻してしまいます。 ・・③ ・解説 [ 問 12 」 こでは 変数を使うやり方もありますが , パーセントを求めるには , 浮動小数点の すさも増します。 ログラムを読むことができるので , 読みや ージ的にも「 a を 100 倍する」という感じにプ と書くことができます。こう書くと , イメ a * = 100 ; のような書き方は , a = a * 100 ; 【 2 】 , 【 3 】は , 複合演算子の問題です。 力の stde 仼を用いるのが一般的です。 標準出力の std 。 ut ではなく , 標準ェラー出 画面に表示されますが , このような場合は , stdout としても期待どおりのメッセージが 面に警告を出力する処理を想定しています。 【 1 】は , 与えられた値が不適切な場合に画 整数のままで計算して , 余りは切り捨てる ことにします。先に割り算をすると , 0 以 上 1 未満の結果がすべて 0 になってしまうため , 期待どおりの結果が得られません。まず要 素数を 100 倍してから , 全体の数で割れば , パーセントの値を求めることができます。 ② と書かれることもありますが , 処理は同じ while ( * s 「 c + + = * dst + + ) おくとよいでしよう。 り文句のような書き方なので , 丸暗記して while の条件判定部分に現れる式は決ま ・解説 [ 問 14 」 る必要があります。 ただし , そのような場合は運用に気をつけ 認しないプログラムを書くことがあります。 絶対に問題ないという場合にはわざわざ確 ックを入れるのは非現実的なので , 運用上 , ん。あらゆる掛け算でオーパフローのチェ でオーパフローすることは想定していませ ェックは行っていますが , 100 倍した時点 引数が 0 または負の数であるかどうかのチ る必要があります。前問では , 与えられた 整数計算では , オーパフローに気をつけ ・解説 果になっていること ) 。 発生しないこと ( 100 倍しても int の範囲の結 pa を 100 倍した時点でオーパフローが 「問 13 」 ます。 いう文字を表示したい場合は , % % と指定し う問題です。 p ⅱ n ばの書式中にパーセントと ントを表示するにはどうすればいいかとい 【 4 】は , p ⅱ n ばの書式文字列のなかでパーセ