演習5-1 K&R プログラミング言語C

演習5-1

問題文の意味がいまいちわかりにくかったが、 +/- と数字の間に空白があっても +/- 記号が機能するように変更すると解釈した。

+/- 記号があれば sign_c に一時保存して次の文字を読みにいく。
次の文字が数字でなければ(スペースなどの場合)sign_c に一時保存した +/- 記号を ungetch() で入力に戻し、入力が数でないという印の 0 を返す。

#include <stdio.h>
#include <ctype.h>

#define SIZE 100
#define BUFSIZE 100

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

int main(void)
{
    int n, m, array[SIZE], getint(int *);
    int i;

    n = 0;
    while (n < SIZE && (m = getint(&array[n])) != EOF) {
        if (m > 0) {
            n++;
        }
    }

    for (i = 0; i < n; i++) {
        printf("%d\n", array[i]);
    }

    return 0;
}

/* getint : 入力から次の整数を取り出して *pn に入れる */
int getint(int *pn)
{
    int c, sign, sign_c;

    while (isspace(c = getch())) /* 空白を飛ばす */
        ;
    if (!isdigit(c) && c != EOF && c != '+' && c != '-') {
        ungetch(c); /* 数字ではない */
        return 0;
    }
    sign = (c == '-') ? -1 : 1;
    if (c == '+' || c == '-') {
        sign_c = c;
        c = getch();
    }
    if (!isdigit(c) && c != EOF) {
        ungetch(sign_c);
        return 0;
    }
    for (*pn = 0; isdigit(c); c = getch())
        *pn = 10 * *pn + (c - '0');
    *pn *= sign;
    if (c != EOF)
        ungetch(c);
    return c;
}

char buf[BUFSIZE]; /* ungetch 用のバッファ */
int bufp = 0;      /* buf 中の次の空き位置 */

int getch(void) /* (押し戻された可能性もある)1文字をとってくる */
{
    return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)
{
    if (bufp >= BUFSIZE) {
        printf("ungetch: too many characters\n");
    } else {
        buf[bufp++] = c;
    }
}

実行結果

$ cat hoge.txt
123
+456
+ 789
-321
- 654
-       987
$ ./ex5-1 <hoge.txt
123
456
789
-321
-654
-987
プログラミング言語C 第2版 ANSI規格準拠
B.W. カーニハン D.M. リッチー
共立出版
売り上げランキング: 9726
«
»