1. ホーム
  2. c

[解決済み] getop() 関数 K&R book p 78

2022-02-08 05:01:34

質問

K&Rの本を勉強しています。現在、p.78のgetop()関数を読んでいます。 コードは理解できるのですが、2つの点について説明が必要です。

getop()のコードは以下の通りです。

int getch(void);
void ungetch(int);

/* getop: get next character or numeric operand */
int getop(char s[])
{
    int i, c;
    while ((s[0] = c = getch()) == ' ' || c == '\t')
        ;
    s[1] = '\0';

    if (!isdigit(c) && c != '.')
        return c; /* not a number */

    i = 0;
    if (isdigit(c)) /* collect integer part */
        while (isdigit(s[++i] = c = getch()))
            ;
    if (c == '.') /* collect fraction part */
        while (isdigit(s[++i] = c = getch()))
            ;
    s[i] = '\0';

    if (c != EOF)
        ungetch(c);

    return NUMBER;
}

について質問です。 s[0] にしてください。

 while ((s[0] = c = getch()) == ' ' || c == '\t')

whileループの考え方は、スペースと水平タブをスキップすることですが、なぜs[0]に'c'を保存しているのでしょうか?著者はなぜ単純に書かなかったのか。

while (c= getch() == ' ' || c == '\t')

この後、スペースやタブを使うことはないのですが、なぜ c を s[0] のために?の必要性は何でしょうか? s[0] ここで?

2つ目の質問は、についてです。

s[1] = '\0';

なぜ、文字列の末尾に 'Ⓐ' を付けるのでしょうか? s[1] ここで?

私はそれについてstackoverflow.comに投稿された以前の回答のいくつかを読みましたが、私は完全に納得していません!私は、あなたがそれを行うことができます。

上記の質問に対する回答は、「残りの入力を読み込む前に関数が戻る可能性があるため、sは完全な(そして終了した)文字列である必要がある」です。

OK。しかし、入力の最初に空白が1つあり、その後にオペランドや演算子が続く場合はどうでしょうか?この場合 s[1] = '\0' は、文字列を早く閉じすぎてしまうのではないでしょうか?

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

最初の質問に対する答えですが、課題には s[0] この場合、コーディングのショートカットとして便利です。の値は c がコピーされ s[0] に対して あらゆる で読み取った文字は getch() 使用されるか廃棄されるかに関係なく。もし廃棄されるのであれば、大したことはありません。 while() ループを使用します。もし使用するのであれば,すでにコピー先の配列 s[] .

2つ目の質問にお答えします。

しかし、入力の最初に空白が1つあり、その後に続く場合はどうでしょうか。 オペランドまたは演算子?

なお、先ほどの while() ループは、空白文字(スペースとタブ)が s[0] ループから抜けた後 したがって

s[1] = '\0';

その s[] の文字列は、スペースでもタブでもない1文字と、その後に続く文字列の終端から構成されます。

次のステートメントでは

if (!isdigit(c) && c != '.')
    return c; /* not a number */

を指定すると、その文字が数字か小数点以外の場合、この関数が返されます。そのため、文字列を終了させる必要があったのです。