c - getop() 函数 K&R 书第 78 页

标签 c kernighan-and-ritchie

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

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] in:

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

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

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

我们后面不会使用空格和制表符,为什么我们需要将 c 保存在 s[0] 中?这里需要什么s[0]

我的第二个问题是:

s[1] = '\0';

为什么我们在这里将'\0'(字符串结尾)分配给s[1]

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

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

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

最佳答案

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

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

But what if input has one white space at the beginning and followed by an operand or operator?

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

s[1] = '\0';

s[] 字符串将包含一个既不是空格也不是制表符的字符,后跟一个字符串终止符。

在下一条语句中

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

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

关于c - getop() 函数 K&R 书第 78 页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33299349/

相关文章:

c - 函数声明与原型(prototype)的替代 (K&R) C 语法

c - C中空格的转义序列是什么?

c - 为什么 "The C Programming Language"书说我必须转换 malloc?

c - 如何使用 scanf\fscanf 读取一行并解析成变量?

更改在 C 中循环的回调函数中的全局变量

c - 数组索引中的序列点

c - 在 C 中使用 XAudio2

c - 是什么导致了这些默认数组值?

c - 这个小的 C 程序是否满足 K&R 练习?

c - 从函数返回二维数组