getop()函数K& R book p 78

时间:2015-10-23 09:45:11

标签: 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;
}

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

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

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

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

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

我的第二个问题是:

s[1] = '\0';

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

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

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

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

4 个答案:

答案 0 :(得分:4)

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

回答你的第二个问题,

  

但是如果输入在开头有一个空白区域,后面跟着   操作数或操作符?

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

s[1] = '\0';

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

在下一个声明中

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

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

答案 1 :(得分:1)

  

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

不,

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

这可以确保,如果有某些内容需要阅读,它会被\0覆盖,i=0s[++i]意味着存储在s[1]中,其中包含\0

答案 2 :(得分:0)

关于你的第一个问题:s [0] in:

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

因为s [0]中的保存'c'有助于将第一个数字存储在高级中,这样我们就可以从i等于1开始下一个代码。

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

上述代码用于存储从索引i = 1

开始的下一个字符串字符

关于你的第二个问题:

我们做不到

s[0] = '\0';

因为当时我们已经将第一个数字存储在s [0]

的字符串中

(s[0] = c = getch())

答案 3 :(得分:0)

这里给出的答案已经很好了,不过我想在第二个问题上补充一点。

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

在这种情况下,我们根本不关心字符串(如果遇到一个数字,它会被覆盖),因为只有遇到十进制数时才使用该字符串,其余的字符如' +&# 39;或者' - '或者' \ n'直接退回。