1. ホーム
  2. c

[解決済み] この1988年のC言語のコードは何が問題なのでしょうか?

2023-02-12 21:37:40

質問

The C Programming Language" (K &; R)という本から、このコードをコンパイルしようとしています。これは、UNIX プログラムの基本的なバージョンです。 wc :

#include <stdio.h>

#define IN   1;     /* inside a word */
#define OUT  0;     /* outside a word */

/* count lines, words and characters in input */
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);
}

で、以下のようなエラーが出ています。

$ gcc wc.c 
wc.c: In function ‘main’:
wc.c:18: error: ‘else’ without a previous ‘if’
wc.c:18: error: expected ‘)’ before ‘;’ token

この本の第2版は1988年のものですが、私はC言語についてはかなり初心者です。コンパイラのバージョンと関係があるのか、私がナンセンスなことを言っているだけなのかもしれません。

最近のC言語のコードでは、違う使い方の main 関数の別の使い方を見ました。

int main()
{
    /* code */
    return 0;
}

これは新しい規格なのでしょうか、それともまだタイプレスメインを使うことができるのでしょうか?

どのように解決するのですか?

あなたの問題は、プリプロセッサーで定義された INOUT :

#define IN   1;     /* inside a word */
#define OUT  0;     /* outside a word */

これらのそれぞれに、末尾のセミコロンがあることに注意してください。プリプロセッサがこれらを展開すると、あなたのコードはおおよそ次のようになります。

    if (c == ' ' || c == '\n' || c == '\t')
        state = 0;; /* <--PROBLEM #1 */
    else if (state == 0;) { /* <--PROBLEM #2 */
        state = 1;;

この2つ目のセミコロンによって else を持たないことになります。 if をマッチングさせることはできません。なぜなら、中括弧を使っていないからです。そこで、プリプロセッサの定義からセミコロンを削除して INOUT .

ここで得られた教訓は プリプロセッサー文はセミコロンで終わる必要はないということです。

また、中括弧は常に使用すべきです!

    if (c == ' ' || c == '\n' || c == '\t') {
        state = OUT;
    } else if (state == OUT) {
        state = IN;
        ++nw;
    }

吊り下げはありません。 else のようなあいまいさはありません。