期末試験講評
問題1
今回は全体としての点数の平均はやや高いと思いますが、入力ファイル名の扱い、単語長の計算方法、行長判定の条件などで、仕様を満たさない記述が複数見られました
-
(1)ファイルポインタの宣言:割とよくできていると思います。
-
(2)入力ファイルの扱い:
ファイル名を直接「"in.data"など」と解答している学生がいたが、argv[2]で書くのが正解。この問題では、ユーザがコマンドライン引数で入力ファイル名を指定できる汎用的なプログラムを作成することが目的であり、ファイル名をプログラム内で固定してしまうと、入力ファイルを変更できず仕様を満たしていないので、不可とする。
また、fopenのところで、"argv[2]" を ダブルクォーテーションで囲むと文字列リテラルになり、実際に与えたコマンドライン引数とは関係なく、argv[2] という名前のファイルを開こうとする誤った動作になるため、ご注意ください。
-
(3)(4)(5)はよくできている方です。
-
(6)最大文字数判定で、ミスが多かった。
- llen <= lmax を llen < lmax としていた回答が数件。
行の長さが「ちょうど最大文字数」の場合にも、その行までは同じ行に出力できるようにする必要があります。llen < lmax としてしまうと、最大文字数ちょうどのケースが誤って改行扱いになってしまうため、この条件は不適切です。正しくは llen <= lmax とする必要があります。
- (llen <= argv[1]) としていた回答が数件あった。
argv[1] はコマンドライン引数として渡される「文字列(char *)」であり、そのまま数値と比較することはできません。
プログラム中では、argv[1] を atoi(argv[1]) によって整数に変換し、その結果を lmax に代入しています。したがって、比較に用いるべきなのは argv[1] ではなく、整数値としての最大文字数を表す変数 lmax であり、llen <= lmax が正しい条件式となります。
-
(7)は正解率が高かったものの、括弧ごと答えてしまった人が何人かいました。この場合、括弧で囲んしまったので、関数呼び出しにならず、カンマ演算子として評価されてしまいます。その結果、意図した出力が実行されません。
また、"/n" と書いてしまうと単なる文字 / と n になってしまい、改行として動作しませんので、ご注意。
-
(8)ほとんどの人はできている。
問題2
問題2-1
文字列のサイズやポインタによる文字の参照などの問題でした。
-
(1)-(4)あたりは比較的よくできていたと思います。
-
(5)以降はポインタの使い方や間接演算子の優先順位等を正しく理解している必要があります。
-
(5)はpが差すアドレスの内容に1を足すので、'i'+1 => 'j'になります。
-
(8)は表示後にpがインクリメントされるので、(9)(10)はpが+1になったことに
注意する必要があります。
問題2-2
文字列を扱う関数の問題です。
-
(1)は文字列の先頭アドレスを戻す必要があるので、char *が正解です。
-
(2)はアドレスを渡す必要があり、文字列の先頭アドレスであるs1になります。&s1[0]でも良い。
&s1とだけ書いている人がいましたが、&s1と&s1[0]は意味が異なりますので注意してください。
-
(3)は文字列のアドレスを渡すのでchar *となります。
-
(4)は壊滅的でした。文字列をコピーする場合は、ヌル文字を付加しなければならないので、
len+1にする必要があります。len*sizeof(char)+1も正解としています。
-
(5)では代入かつループ条件成立を同時に行う必要があります。*s2=*s1としておけば
代入と同時に*s1がヌル文字以外ではループすることになります。 もちろん代入とループ条件を
それぞれ書いていても構いません。
ヌル文字をNULLと書いている人がいましたが、ヌル文字とNULLは意味が異なりますので注意が必要です。
-
(7)はよくできていました。
-
(8)は、一見iに関する条件式が入りそうに思えますが、ヌル文字が出てくるまでのカウンタとしてiを使用しており、(9)でそのiをリターンします。 ここでも、ヌル文字をNULLと書いている人がいましたが、意味が異なりますので要注意です。
問題3
構造体の書き方、ポインタの扱い、配列アクセス、構造体メンバへのアクセス方法などに関する問題でした。
-
(1)(2)(3) 概ね良くできていました。
typedef を使ってしまった回答がありましたが、問題文に「typedef による名前付けは行わない」とあるため、間違いです。
また、struct を書かずに weather, stationとだけ書いた回答がありましたが、typedef を使わない場合は struct を必ずつけることを確認しましょう。
-
(4) obs とだけ書いてしまい、アドレス渡しになっていない回答、*obs と書いてしまう回答(未初期化のポインタを使う誤り)がありました。ポインタ演習の基本部分なので、今後も注意してください。
-
(5) 最終要素についての理解度を問う問題でした。obs.num_data と書いてしまい 1 つずれる回答、MAX_DATA - 1 と固定値を使ってしまう回答などが見られました。実際に読み込んだデータ数に基づいて決めるという点が大事です。
-
(6)(7)(8) 概ね良くできていました。
-
(9)(10) data[i] , data[j]という誤答が多くみられました。構造体同士の比較は不可であることに注意してください。
問題4
マクロ関数やマクロを用いた条件コンパイルに関する問題でした。授業で習った内容を覚えていればそのまま解けるはずの問題でしたが、平均点で見ると出来はそこまでよくなかったのは残念です。
-
(1) マクロ関数の定義なのに、通常の関数定義のように戻り値の型を書いてしまった人が多いです。
-
(2)(3) 数値としての0や9ではなく、文字(のASCIIコード値)の比較をするので、文字型定数としてシングルクォーテーション(')でくくってあげる必要があります。また、比較演算子ではなく数学の比較記号を書いてしまった人もいました。
-
(4) コロン(:)の代わりにカンマ(,)で書いた人がいました。
-
(5) ヘッダファイルをインクルードする際にファイル名を囲う記号、<>と""の違いを理解しておきましょう(ハンドアウトLec12-5)。
-
(6) 比較的よくできていました。
-
(7) #elifまたは#elif definedと答えていた人が多かったです。このプログラムでは(9)の条件式の真偽だけでどの部分を有効にするかが決まるので、単に#elseでよいのです。
-
(8) 比較的よくできていました。ただし、(6)-(8)を通じて時々#を書かない人がいました。
-
(9) (2)と(3)で書くべき(あるいは書いた)条件式をそのまま書いた人がいますが、問題文でマクロ関数isNumを使用することが指定されているので不可としています。
-
(10) 比較的よくできていましたが、コンパイル対象のファイルにヘッダファイルQ4.hを加えていた人がいました。
問題5
再帰関数の呼び出し等を問う問題でした。
-
採点していた感じだとちゃんと勉強した人はほぼ全部ちゃんとできていました。
-
(7),(9),(10)
でmain関数にある変数iとcollatzSteps関数にあるnがごちゃごちゃになってしまい、collatzSteps関数に宣言されていないiをnの代わりに使ってる人がいました。
-
(10)の奇数を受け取った時の再帰関数呼び出しの際に、数学の数式のように「*」をつけずに「3n+1」と答える人が多数でした。
問題6
講義で扱った連結リストを少し変更して、格納するデータを構造体にした場合の
プログラムの問題でした。連結リストの難しさからか、2-3問しか正解できない人
が多かったようです。
-
(1) 意外にできている人が少なかったです。名前の文字列を引数に渡すので、
型は文字型ポインタになります。なお、char [] だと後の方の関数定義部分が
finditem(char []keyname) となってしまうため、うまくいきません。
-
(2)(3) はよくできていました。
-
(5)(6) は、すぐ後の finditem関数のforループと同じにしている誤答が多かった
です。仕様で「表示はheadの次のノードから行う」となっていることに注意。
-
(7) は難しかったと思います。できた人はごく少数でした。
-
(8) は sizeof(node) とか struct node のみを書いている人が多かった印象です。
malloc関数の引数にすべき「ノード構造体のサイズ」がどんな式になるか、
落ち着いて考えてください。