「C言語 体当たり学習徹底入門」正誤表

このページは、拙書「C言語 体当たり学習徹底入門」技術評論社 ISBN4-7741-1200-3 の正誤表です。

あまり増えないことを祈ります。

日付順のインデックス


全般

たとえば15ページの一番上の、 「0-1-3 なぜCUIなのか」などのタイトル部分の背景などで、

Happy - go - luky
C Language

「luky」は、「lucky」のスペルミスです。

Happy - go - lucky
C Language

ページによって、直っているところといないところがあります。


表紙

表紙と扉のページだけ、「行き当たり」でなく「行き当り」になってます。


p.38

「ほげを考えるページ」は、現在オリジナルが公開されていませんので、 作者の吉田さんの許可を得まして、私のページに転載させていただきました。

URLは、
http://member.nifty.ne.jp/maebashi/programmer/hoge.html(移転済み)
http://kmaebashi.com/programmer/hoge.html(移転後)
です。


p.49

Fig.1-2の中。

meter_height = height / 10

meter_height = height / 100

p.51

「条件式」という言葉を使っていますが、規格では「条件式」とは、 ?:による式のことを指します。

if文の中に書くものも一般に条件式と呼びますが、一応補足しておきます。


p.54

  if (bmi < 17.6)
     ...

基準とする値が前のページのものと異なっています。

実は、BMIの基準値にもいくつかありまして、最初、 どこかのWebページで拾ってきたものをベースにとりあえず書いていたのですが、 最終的には「権威のあるものの方がよいだろう」ということで アメリカCDCのものに置き換えたわけです。 ...が、その時に修正漏れが発生してしまいました。申し訳ありません。


p.62〜p.63(複数箇所)

符合

符号

「間違えるのはしょうがない。 大切なのは、同じ間違いを繰り返さないことだ」 というのが小学校時代の恩師の口癖でした(嘘)。

ポインタ完全制覇のときと同じミスを繰り返してしまいました。 すみません。


p.69

誤:

(double)weight ←weightに格納されている値をdouble型に変換

いちおうこの文字は赤くあるべきなのではないかと。


p.77 上から2行目

誤:

whlie (条件式) {

正:

while (条件式) {

p.79 下から3行目

誤:

Cでは0でない値は真を意味するので、whlieの条件式が...

正:

Cでは0でない値は真を意味するので、whileの条件式が...


p.87

誤:

...ただ、例えばList2-3の24〜25行目は、 以下のように書き替えることができます。

  printf("score[%d]\n", index, score[index++]);

これは、

  printf("score[%d]\n", index, score[index]);
  index++;
と同値です。

申し訳ありません。二重に間違っています。

というわけで、p.88の2行目までを以下のように差し替えてください。

正:

...ただ、例えばList2-3の17〜18行目は、 以下のように書き替えることができます。

  score[score_count++] = temp_score;

これは、

  score[score_count] = temp_score;
  score_count++;

と同値です。

ここで、前置の++を使うと、

  score[++score_count] = temp_score;

これは、

  score_count++;
  score[score_count] = temp_score;

と同値になります。

かなり問題のあるミスをしてしまいました。お詫びいたします。


p.99

誤:

これは、カレントディレクトリからヘッダファイルを探してもらえるように するおまじないです。

正:

これは、そのソースファイルの存在するディレクトリからヘッダファイルを 探してもらえるようにするおまじないです。

p.100 7, 10行目

macro.cはcpp.cの誤りです。


p.100 下から5行目

単純に「100 」にき換えられていることがわかります。

単純に「100 」にき換えられていることがわかります。

p.102

Fig2-5の一番下の配列の図について、

1手順ごとに「ソートずみの範囲」はひとつづつ増えていきます。


p.103 Fig 2-6

左上のところ

sorted_num

sorted_count


p.107

誤:

悪いことは言いません。3の状態になったら...

ここの「3」ですが、その前の箇条書きの(3)に対応します。 黒丸に白抜き文字の(3)だと思ってください。


p.108 下から1〜2行目

プログラムが異常終了した時に最後の方のデバッグライトが出力されないことがあ る,ということもありす

プログラムが異常終了した時に最後の方のデバッグライトが出力されないことがあ る,ということもあります

p.125 ASCIIコード表
p.129 補足タイトル

誤:

「標準入出力のバッファリング」

正:

「標準ライブラリのバッファリング」

「標準入出力」というとstdin, stdoutとまぎらわしいので変更します。

p.131 3-2-5の前

「未来の自分は他人である」ということは肝に命じて おくべきでしょう。

「未来の自分は他人である」ということは肝に銘じて おくべきでしょう。

p.136 Table3-2

演算子の優先順位表の?:の結合規則

左から右

右から左

p.138

FORTRANやBASICでは、等値比較にも代入にも同じ = を使います。

BASICでは、等値比較にも代入にも同じ = を使います。

FORTRAN(FORTRAN77-ISO/IEC1539 JIS X3001)では、等値比較は.EQ.でした。 等値比較に=が使えるFORTRANはおそらく存在しません。


p.142 6行目

誤:

nを8で割った時、割り切れない分は切り捨てられるので...
ここの所に、以下のように注を入れます。
nが正の数の場合の話です。

p.142 下から8行目

誤:

Cの中で、タブを表現する場合、

正:

Cでは、タブ文字を表現する場合、

ちょっと前のままでは意味がわかりにくいので。


p.149 25行目

25:          fputc(ch, out_fp);

25:          putc(ch, out_fp);

Cにはfputc()という関数もあり、putc()と同じように動きますが、 p.148の説明の方でputc()と書いていますので。


p.150 14行目

は「'n'」という1文字で表現できなければなりません。

は「'\n'」という1文字で表現できなければなりません。

p.151 注

誤:

PCでWebページを作成し、FTPでサーバに送ったが

正:

PCでWebページを作成し、FTPでUNIXのサーバに送ったが

一応補足します。


p.153 12行目

誤:

fp = fopen(argc[1], "r");

正:

fp = fopen(argv[1], "r");

p.156 注

誤:

汎整数拡張が行なわれます

正:

汎整数拡張が行なわれます

最後のマルが抜けているようです。


p.159

誤:

そういえばWindows3.1はフロッピー12枚組みでした。

正:

そういえばWindows3.1はフロッピー12枚組でした。

どっちでもいいような気はしますが...


p.174

誤:

しかし、記述の順序に関わらず、Cではプログラムの実行はmain() 関数から開始されます...

ここのところに、以下のように注を入れてください。

「4-1-3 main()を先に書くか後に書くか」を参照

p.175 1行目

誤:

9行目のreturn文で

正:

7行目のreturn文で

p.175 注

誤:

呼び出す側では話が別で、voidを入れる必要はありません。

正:

呼び出す側では話が別で、voidを入れてはいけません。

p.176

誤:

Cでは、歴史的な事情により、()の中にはvoidを入れることになっています...

以下のように注を入れてください。

正しく言うと、関数定義の()の中は、voidを入れても入れなくても意味は同じです。 voidを入れる必要があるのはプロトタイプ宣言です。p.179も参照してください。

p.176 一番下の例

  void func()

  void func(void)

間違いと言うわけではないですが、統一性のために入れておきます。


p.179行目

誤:

そこで、ANSI Cから、引数も併せて宣言するように改められたわけです...

ここに注をいれてください。

引数がない場合、プロトタイプ宣言にvoidを入れるのは、 昔のスタイルの宣言と区別するためだったわけです。


p.188 アルゴリズムと所要時間の表

挿入ソートが初出なので、注で

挿入ソートについては「4-5-1 挿入ソート」を参照のこと

と入れます。


p.189 6行目

誤:

というわけで、2変数の内容を交換する関数(swap())関数を...

swap()をタイプライタ体にしてください。


p.193 2行目

10行目で*hoge_pに10を代入していますが、

21行目で*hoge_pに10を代入していますが、


p.198

本文がゴシック体になってしまっています。地の文なので、明朝だと思ってください。


p.203 注

その理由は、「0-1-2 なぜCUIなのか」でも書きましたが

その理由は、「0-1-3 なぜCUIなのか」でも書きましたが

p.231 Fig 5-4

ふたつめの注「arrayに文字列を設定する部分ですが...」は、リスト 5-9に対する注なので、リストの横に移動します(大差ない気もしますが...)。


p.249 221行目

  y_or_n = tolower(buf[0]);

buf[0]はcharですから、ユーザが漢字を入力した場合などには 負の数になる可能性があります。

tolower()は、引数としてunsigned charの値とEOFしか許しておらず、 それ以外の場合の挙動は未定義なので、これは問題があります。


p.237 10行目

  /* 価格を表示 */
  printf("書名..%s\n", book_data.book_name);

  /* 書名を表示 */
  printf("書名..%s\n", book_data.book_name);

p.247 List 5-12
132:  /*
133:   * 文字列を再入力させる。改行だけ押された場合は、
134:   * strには手をつけない。
135:   */
136:  void reinput_string(char *str, int size, FILE *fp)
137:  {
138:      char        buf[1024];
139:  
140:      input_string(buf, size, fp);
141:  
142:      if (buf[0] != '\0') {
143:          /*
144:           * 改行のみ叩かれたわけではないようなので、
145:           * データを変更する
146:           */
147:          strcpy(str, buf);
148:      }
149:  }
(中略)
178:  /*
179:   * data_pの指す先のデータについて、再入力させる。
180:   * 変更しない場合は returnだけ押せばよい。
181:   */
182:  void reinput_data(BookData *data_p)
183:  {
184:      printf("書名:%s>", data_p->book_name);
185:      reinput_string(data_p->book_name, BOOK_NAME_LEN, stdin);
186:  
187:      printf("著者:%s>", data_p->author);
188:      reinput_string(data_p->author, AUTHOR_LEN, stdin);
189:  
190:      printf("出版社:%s>", data_p->publisher);
191:      reinput_string(data_p->publisher, PUBLISHER_LEN, stdin);
192:  
193:      printf("価格:%d>", data_p->price);
194:      data_p->price = reinput_number(data_p->price);
195:  
196:      printf("ISBN:ISBN%s>ISBN", data_p->isbn);
197:      reinput_string(data_p->isbn, ISBN_LEN, stdin);
198:  
199:      printf("備考:%s>", data_p->note);
200:      reinput_string(data_p->note, NOTE_LEN, stdin);
201:  }

オリジナルのソースだと、reinput_string()の方にはBOOK_NAME_LEN等が渡せないため、 1024文字で受けてしまい、それをBookData構造体のbook_nameにコピーするため 領域破壊が発生します。


p.263 一番下の行〜

  enum {
      …
  } BookType;

  enum BookType {
      …
  };

p.264 下から3行目

誤:

/* 詠みかけ状態 */

正:

/* 読みかけ状態 */

p.275 List5-17

List5-17で、 '\0'の分の領域確保を忘れるというかなり情けないミスを犯していました。 input_string関数を全面的に差し替えます。

char *input_string(FILE *fp)
{
    char	*p = NULL;
    int		ch;
    int		size = 0;
    
    /* 改行までの文字を読み込む */
    do {
        /* 1文字分領域を拡張する */
        p = realloc(p, sizeof(char) * (size+1));
        ch = getc(fp);
        p[size] = ch;
        size++;
    } while(ch != '\n');

    p[size-1] = '\0';

    return p;
}

p.284 List.5-18 p.247と同様の問題があります。
p.286 225行目

  int select_y_or_n()

  int select_y_or_n(void)

間違いと言うわけではないですが、統一性のために入れておきます。


p.293 482行目(コメント)

  * 登録と一覧表示以外はとりあえずダミー

このリストでは既にダミーではありません。

このように、コメントはいとも簡単に嘘になってしまうから やたらに書くべきではない、ということを証明するためにわざと間違えた、 わけではありません。ごめんさい。


p.303 真ん中へん

しかし、"" で囲む方の書き方をすると、たいていの処理系ではまず カレントディレクトリを探しに行きます。

しかし、"" で囲む方の書き方をすると、たいていの処理系ではまず そのソースファイルの存在するディレクトリを探しに行きます。

同様に、下から4行目の「カレントディレクトリ」も、 「そのソースファイルの存在するディレクトリ」に置き換えます。


p.311 12行目

戻り値はfromと同一、まず使わないので忘れてしまってよい。

戻り値はtoと同一、まず使わないので忘れてしまってよい。

p.312 (13)

next以外は(連結リストとは無関係の)構造体の本来のメンバの意味なので、 以下のように説明を入れます。

  typedef struct Hoge_tag {
      int     a;         ┐
      char    b[32];     ┘これが構造体の内容
      struct Hoge_tag *next;
  } Hoge;

p.319 注

規格では、配列の要素を指していないポインタについて加減算を行った 場合の動作は未定義になっています。

規格では、配列の要素数をふたつ以上超えるようなポインタ演算を 行なった場合の動作は未定義になっています。

一応規格では、

配列でないオブジェクトへのポインタは、 要素型としてそのオブジェクトの型をもつ長さ 1の配列の最初の要素へのポインタと同じ動きをする

と書いてありますので、元のままの記述だと問題がありそうです。


p.333 下から9行目

誤:

scanf()は変換に成功した数を返します。

正:

scanf()は変換代入に成功した数を返します。 ファイルの終わりに達した場合、EOFを返します。

2010/8/25追記:
こちらに あるとおり、代入抑止文字*を使用した場合、変換の数と代入の数は食い違います。


p.334 getchar()の説明

標準出力から1文字読みこみ、戻り値として返します。

標準入力から1文字読みこみ、戻り値として返します。


p.335 注

入力行の長さが予測できないのなら、fgetc()でも使って

入力行の長さが予測できないのなら、getc()でも使って

fgetc()でもいいですが、この本ではgetc()を使ってきていますので。


p.344(奥付)

ご質問の歳には

ご質問の際には

「C言語 体当たり学習徹底入門」のページに戻る | トップページに戻る