getop()函数K&R book p 78

Hus*_*ada 5 c kernighan-and-ritchie

我正在学习K&R书.目前我正在阅读函数getop(),第78页.我理解代码,但我需要澄清两件事.

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;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:s[0]在:

 while ((s[0] = c = getch()) == ' ' || c == '\t')
Run Code Online (Sandbox Code Playgroud)

while循环背后的想法是跳过空格和水平制表符,那么我们为什么要在s [0]中保存'c'?为什么作者不简单地写:

while (c= getch() == ' ' || c == '\t')
Run Code Online (Sandbox Code Playgroud)

我们以后不打算使用空格和标签,为什么我们需要保存c in s[0]?这需要什么s[0]

我的第二个问题是:

s[1] = '\0';
Run Code Online (Sandbox Code Playgroud)

我们为什么要s[1]在这里指定'\ 0'(字符串结尾)?

我已经阅读了stackoverflow.com上发布的一些先前的答案,但我并不完全相信!

关于上述问题的公认答案是:"因为函数可能在读取剩余输入之前返回,然后s需要是一个完整的(并终止)字符串."

好.但是,如果输入在开头有一个空格,后面跟一个操作数或运算符怎么办?在这种情况下,s[1] = '\0'是否会过早关闭字符串?不是吗?

sif*_*man 6

在回答你的第一个问题时,在这种情况下分配s[0]是一个方便的编码快捷方式。对于读取的每个字符,的值c都会被复制到,无论它是被使用还是被丢弃。如果要丢弃,也没什么大不了的;它将在循环的下一次迭代中被覆盖。如果要使用它,那么它已经被复制到目标数组中的必要位置。s[0]getch()while()s[]

在回答你的第二个问题时,

但是,如果输入开头有一个空格,后跟一个操作数或运算符怎么办?

请注意,前面的循环可防止退出循环后while()出现空白字符(空格和制表符) 。s[0]因此,执行后

s[1] = '\0';
Run Code Online (Sandbox Code Playgroud)

s[]字符串将由一个字符组成,该字符既不是空格也不是制表符,后跟字符串终止符。

在下一个声明中

if (!isdigit(c) && c != '.')
    return c; /* not a number */
Run Code Online (Sandbox Code Playgroud)

如果字符不是数字或小数点,则该函数将返回。这就是为什么有必要终止字符串。