4

私はCと、ブライアン・カーニハンデニス・リッチーThe C Programming Languageによって提案された私の友人(私より年上)を学び始めました。

ただし、いくつかの例を試している間、それらは予想とは異なる動作をし、本に書かれているとおりには動作しません。

たとえば、これは機能していないようです(何も出力されません):

#include <stdio.h>

#define IN 1
#define OUT 0

/* count lines, words, and characters in input */

int main()
{
   int c, nl, nw, nc, state;
   state = OUT;
   nl = nw = nc = 0;

   while ((c = getchar()) != EOF) {
      ++nc;
      if (c == '\n')
         ++nl;
      if (c == ' ' || c == '\n' || c == '\t')
         state = OUT;
      else if (state == OUT) {
         state = IN;
         ++nw;
      }
   }
   printf("%d %d %d\n", nl, nw, nc);
   return 0;
}

私はこの本を読み続けるべきだと思いますか、たぶんほんの少しの間違いがあり、それは読む価値がありますか?または、Cスターター向けのより良い本があります。

編集:私の仮定は、ENTERキーを使用して入力を送信すると、がシミュレートさEOFれるというものでしたが、そうではありません。CTRL+Z します。

助けてくれてありがとう。

4

7 に答える 7

9

わたしにはできる。

$ gcc c.c -o c
$ echo hello world | ./c
1 2 12
$ 

プログラムは、標準入力からファイルの終わりに達するまでテキストを読み取ります。キーボードから読み取るときに、ファイルの終わりの状態を正しく通知していないのではないかと思います。Linuxおよびその他のUnixライクなシステムでCtrl-Dは、1行だけを入力します。Windowsでは、と入力しCtrl-Zます。

IDEからプログラムを起動すると、プログラムが終了すると閉じる、新しく起動されたターミナルウィンドウでプログラムが実行される場合があります。その場合、出力が表示される前にウィンドウが消える可能性があります。IDEがこの誤動作をオーバーライドする方法を提供しない場合は、シェルを実行しているターミナルウィンドウから直接実行するか、次のような行を追加できます。

getchar();

プログラムの最後、前にreturn 0;。これにより、終了する前に入力の文字が読み取られます(無視されます)。Enter出力を見た後で入力できます。この種のことは、シェルからプログラムを実行するときにプログラムの実行をより厄介にする可能性があることに注意してください。したがって、これは必要な場合にのみ行ってください。

K&Rと一般に呼ばれるKernighanとRitchieによる「Cプログラミング言語」は優れたC本です。結局のところ、Ritchieは主に言語を発明しましたが、既存のプログラミング知識を前提としている傾向があります。第2版​​があることを確認してください。1つ目は、以前のバージョンの言語について説明しています。(K&R2が公開されてから2つの新しいISO C標準がありますが、導入テストに重要なものは何も追加されていません。)

その他のCオンラインチュートリアルおよび書籍のリストについては、comp.lang.cFAQの質問18.9および18.10を参照してください。

于 2012-08-08T03:18:20.780 に答える
4

K&Rは、懐かしさとデニス・リッチーによって書かれたため、多くの「時流の誇大宣伝」を受けてきました。そして、それは間違いなくこれまでに書かれた最も有名なプログラミング本です。しかし、私の意見では、それは初心者にとって良い本ではありません。

主な理由は、この本が優れたプログラミングスタイルが発明される前に書かれたことです。ほとんどの例は、ほとんどの最新のCプログラマーがかなり厄介なコーディングスタイルであると感じるもので書かれています。良いコーディングスタイルと悪いコーディングスタイルは確かに主観的なトピックです。しかし、あなたの例を見てください。これは次のように書き直すことができます。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

/* count lines, words, and characters in input */

int main (void)
{
   int  ch;
   int  linefeeds_n = 0;
   int  words_n     = 0;
   int  chars_n     = 0;
   bool new_word    = true;


   while ((ch = getchar()) != EOF) 
   {
     if (ch == '\n')
     {
       new_word = true;       
       linefeeds_n++;
     }
     else if (ch == ' ' || ch == '\t')
     {
       new_word = true;
     }
     else if (new_word)
     {
       new_word = false;
       words_n++;
     }

     chars_n++;
   }

   printf("%d %d %d\n", 
          linefeeds_n, 
          words_n, 
          chars_n);

   return EXIT_SUCCESS;
}

上記のスタイルの方が読みやすく、正しいと思います。変更点は次のとおりです。

  • 正気の変数名。
  • 読み取り可能な変数宣言リスト。
  • 不思議な状態変数はありません。代わりにbool型を使用してください。
  • 多くの古典的なバグを防ぐために、すべてのステートメントには常に{}を使用してください。
  • '\ n'(より高速なコード)に対する複数のチェックはありません。
  • whileループの終了時のカウンター増分(一般的なコーディングスタイル)。
  • C99に従ってmain()を終了する正しい方法。
  • main()についてのNitpickは、空の括弧ではなくvoidとして宣言されています。

それらは大きな変化ではなく、大きな問題でもありませんが、すべてがすぐに積み重なっていきます...

このコードも、最新のC99 / C11標準の機能を使用して記述されています。これは、この本も最新のC標準に対応していないため、K&Rにはありません。

さらに、K&Rには、本が正しくない場合や、露骨に危険な慣行を説いている場合がいくつかあります。そのような完璧な例の1つは、mallocの結果を型キャストすることです。この本に対する正当な批判のある他の例は、この記事にあります。

バグ、エラー、タイプミスが多数あるため、K&Rを読むときは、常にエラッタを手の届くところに置いてください。

于 2012-08-08T07:45:58.190 に答える
3

そのプログラムは正常に動作します。何かを印刷する前に、何らかの入力を期待していることに注意してください。入力内の行、単語、および文字の数をカウントします。したがって、コードをコンパイルして実行した場合example

echo this has four words | example

出力として表示されます:

1 4 20

(これは1行、4ワード、20文字です)。

于 2012-08-08T03:15:21.417 に答える
2

したがって、プログラムはおそらく何も出力しませんが、Ctrl + Cなどを押すまでプロンプトは表示されませんよね?これは、whileループを終了しないことを意味します。つまり、入力にEOFが含まれていません。

その本は、EOFを構成するものについて異なる規則を持っているかもしれない古いアーキテクチャに基づいています。この本に関する私のアドバイスは、エラーを解釈して回避できるように柔軟な心を保ちながら、それを継続することです。本から学ぶことは素晴らしいことですが、それをいじって自分でデバッグし始めるまで、実際には統合しません。たとえば、このプログラムで何が起こっているのかわからない場合は、whileループ内にprintfを配置して、ループ動作に関するフィードバックを取得することができます。また、EOFを別のもの(おそらく-1、。、//)に変更して実験することもできます。あなたが物事で遊んでいるだけの小さな子供であると想像してください、そしてあなたはおそらくもっと速く学ぶでしょう。それは少なくとも私の経験です。

他に学ぶべき本については、ジョンエリクソンの「ハッキング、搾取の芸術」という本を強くお勧めします。プログラミングの経験は必要ありません。第2章は、Cの非常に徹底的な紹介です。私は、私立大学のコンピュータープログラミングコースの3学期よりも、本のその1章からコンピューターが実際にどのように機能するかについて学びました。非常に明確ですが、密度の高い方法で、GNUデバッガーの使用方法、コンパイラーが作成したコードを解釈する方法、メモリがどのように機能するか(スタック、bssなど)を説明し、最も重要なこととして、人生の他のものを見る方法を説明しますプログラム(法、生物学など)として。また、あなたがそれを通り抜ける忍耐力を持っているならば、本の残りはあなたに膨大な量の有用な情報を教えるでしょう。

幸運と幸せなハッキング!

于 2012-08-08T03:36:04.137 に答える
0

それは私にとってはうまくいきます。言語はかなり長い間あまり変わっていないので、それは本当に時代遅れであるべきではありません。インターネットや書籍に存在するいくつかの例は、オペレーティングシステム固有のものである可能性があります。この典型的な例はsystem("PAUSE");、Windowsでのみ機能しますが、センチネルループに変換して、再度実行するか、オプションのメニューを表示するかを尋ね続けることです。この例を実行してctrl-dを押すと、出力され5 3 14ました。以下は私の入力です。最後の2行は空白行です。

bla
blah
2

./a.out < a.in私は通常、*nixなどの入力をリダイレクトすることによってこれらのようなプログラムを実行します

于 2012-08-08T03:17:49.213 に答える
0

《 Cプログラミング言語》はあなたにとってとても良い本です、あなたの友人を信頼してください。何も表示されない理由は、入力を終了しないためです。このようなUnixでは、Ctrl+Dを入力して入力を終了できます。プログラムは大丈夫です、私はそれをテストします。

于 2012-08-08T03:22:33.707 に答える
-2

Cプログラミング言語は、DennisRitchieによる優れた本です。ただし、満足できない場合は、別の本を使用できます
。Let Us C-Yashwant Kanetkar著本を読み終えた後、実際に知っているCの量(つまり、どれだけ知っているか)を確認したい場合その構文と癖について)、あなたはこれを試すことができます:
あなたのCスキルをテストしてください-YashwantKanetkarによる

于 2012-08-08T03:24:52.450 に答える