getop() 函数 K&R 书第 78 页
getop() function K&R book p 78
我正在研究 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] = '[=10=]';
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] = '[=10=]';
if (c != EOF)
ungetch(c);
return NUMBER;
}
我的问题是关于:s[0]
在:
while ((s[0] = c = getch()) == ' ' || c == '\t')
while 循环背后的想法是跳过 spaces 和水平制表符,那么我们为什么要在 s[0] 中保存 'c'?为什么作者不简单地写:
while (c= getch() == ' ' || c == '\t')
我们后面不会用到spaces和tabs,为什么要在s[0]
中保存c呢?这里的s[0]
有什么用?
我的第二个问题是:
s[1] = '[=13=]';
为什么我们在这里将'\0'(字符串结尾)分配给s[1]
?
我已经阅读了之前发布在 whosebug.com 上的一些答案,但我并不完全相信!
关于上述问题的公认答案是:"Because the function might return before the remaining input is read, and then s needs to be a complete (and terminated) string."
好的。但是,如果输入在开头有一个白色 space 并且后面跟着一个操作数或运算符怎么办?在这种情况下, s[1] = '[=18=]'
会过早关闭字符串吗?不是吗?
But what if input has one white space at the beginning and followed by an operand or operator? In this case, s[1] = '[=16=]' will close the string too early? isn't it?
不,
i = 0;
if (isdigit(c)) /* collect integer part */
while (isdigit(s[++i] = c = getch()))
这可以确保,如果有要读取的内容,它将在 [=11=]
上被覆盖,因为 i=0
和 s[++i]
意味着存储在 [=14= 中],其中包含 [=11=]
在回答您的第一个问题时,在这种情况下分配给 s[0]
是一种方便的编码快捷方式。对于 getch()
读取的 每个 个字符,c
的值被复制到 s[0]
,无论它是被使用还是被丢弃。如果要丢弃,没什么大不了的;它将在 while()
循环的下一次迭代中被覆盖。如果要使用它,那么它已经被复制到目标数组s[]
中的必要位置。
回答你的第二个问题,
But what if input has one white space at the beginning and followed by
an operand or operator?
请注意,先前的 while()
循环会阻止白色 space 字符(space 和制表符)在退出循环后出现在 s[0]
中。因此,执行
后
s[1] = '[=10=]';
s[]
字符串将包含一个既不是 space 也不是制表符的字符,后跟一个字符串终止符。
在下一条语句中
if (!isdigit(c) && c != '.')
return c; /* not a number */
如果字符不是数字或小数点,函数将 return。这就是为什么需要终止字符串的原因。
关于你的第一个问题: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] = '[=12=]';
因为那时我们已经将字符串中的第一个数字存储在 s[0]
见
(s[0] = c = getch())
这里给出的答案已经很好了,不过我想在第二个问题上再补充一点。
"Ok. But what if input has one white space at the beginning and followed by an operand or operator? In this case, s[1] = '[=16=]' will close the string too early? isn't it?"
在这种情况下,我们根本不关心字符串(如果遇到数字,它无论如何都会被覆盖)因为只有遇到十进制数时才使用字符串,其余字符如“+”或“-”或者'\n'直接返回。
我正在研究 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] = '[=10=]';
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] = '[=10=]';
if (c != EOF)
ungetch(c);
return NUMBER;
}
我的问题是关于:s[0]
在:
while ((s[0] = c = getch()) == ' ' || c == '\t')
while 循环背后的想法是跳过 spaces 和水平制表符,那么我们为什么要在 s[0] 中保存 'c'?为什么作者不简单地写:
while (c= getch() == ' ' || c == '\t')
我们后面不会用到spaces和tabs,为什么要在s[0]
中保存c呢?这里的s[0]
有什么用?
我的第二个问题是:
s[1] = '[=13=]';
为什么我们在这里将'\0'(字符串结尾)分配给s[1]
?
我已经阅读了之前发布在 whosebug.com 上的一些答案,但我并不完全相信!
关于上述问题的公认答案是:"Because the function might return before the remaining input is read, and then s needs to be a complete (and terminated) string."
好的。但是,如果输入在开头有一个白色 space 并且后面跟着一个操作数或运算符怎么办?在这种情况下, s[1] = '[=18=]'
会过早关闭字符串吗?不是吗?
But what if input has one white space at the beginning and followed by an operand or operator? In this case, s[1] = '[=16=]' will close the string too early? isn't it?
不,
i = 0;
if (isdigit(c)) /* collect integer part */
while (isdigit(s[++i] = c = getch()))
这可以确保,如果有要读取的内容,它将在 [=11=]
上被覆盖,因为 i=0
和 s[++i]
意味着存储在 [=14= 中],其中包含 [=11=]
在回答您的第一个问题时,在这种情况下分配给 s[0]
是一种方便的编码快捷方式。对于 getch()
读取的 每个 个字符,c
的值被复制到 s[0]
,无论它是被使用还是被丢弃。如果要丢弃,没什么大不了的;它将在 while()
循环的下一次迭代中被覆盖。如果要使用它,那么它已经被复制到目标数组s[]
中的必要位置。
回答你的第二个问题,
But what if input has one white space at the beginning and followed by an operand or operator?
请注意,先前的 while()
循环会阻止白色 space 字符(space 和制表符)在退出循环后出现在 s[0]
中。因此,执行
s[1] = '[=10=]';
s[]
字符串将包含一个既不是 space 也不是制表符的字符,后跟一个字符串终止符。
在下一条语句中
if (!isdigit(c) && c != '.')
return c; /* not a number */
如果字符不是数字或小数点,函数将 return。这就是为什么需要终止字符串的原因。
关于你的第一个问题: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] = '[=12=]';
因为那时我们已经将字符串中的第一个数字存储在 s[0]
见
(s[0] = c = getch())