getop() function K&R book p 78

余生颓废 提交于 2019-12-21 17:23:57

问题


I'm studying K&R book. Currently i'm reading function getop() at p.78. I do understand the code but i need clarifications about 2 things.

The code of getop() is as follows:

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;
}

My question is about: s[0] in:

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

The idea behind the while loop is to skip spaces and horizontal tab, so why are we saving 'c' in s[0]? Why the authors didn't simply write:

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

We are not going to use spaces and tabs later on, why do we need to save c in s[0] for? What is the need for s[0] here?

My second question is about:

s[1] = '\0';

Why are we assigning '\0' (end of string) to s[1] here?

I have read some of the previous answers posted on stackoverflow.com about it but i'm not totally convinced!

The accepted answer about the above question is: "Because the function might return before the remaining input is read, and then s needs to be a complete (and terminated) string."

Ok. But what if input has one white space at the beginning and followed by an operand or operator? In this case, s[1] = '\0' will close the string too early? isn't it?


回答1:


In answer to your first question, the assignment to s[0] in this case is a convenient coding shortcut. The value of c is copied to s[0] for every character read by getch(), regardless of whether it will be used or discarded. If it is to be discarded, no big deal; it will be overwritten on the next iteration of the while() loop. If it is to be used, then it has already been copied into its necessary location in the destination array s[].

In answer to your second question,

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

Note that the previous while() loop prevents white space characters (spaces and tabs) from appearing in s[0] after exit from the loop. Therefore, after execution of

s[1] = '\0';

the s[] string will consist of a single character that is neither a space nor a tab, followed by a string terminator.

In the next statement

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

the function will return if the character is anything but a digit or a decimal point. This is why it was necessary to terminate the string.




回答2:


But what if input has one white space at the beginning and followed by an operand or operator? In this case, s[1] = '\0' will close the string too early? isn't it?

Nope,

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

This makes sure, that if there is something to be read, it will get overwritten on \0, as i=0 and s[++i] would mean, storing in s[1], which contains the \0




回答3:


for your first question about: s[0] in:

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

because the saving 'c' in s[0] help to storing first number in advanced so that we can start our next code from simply i equal to 1.

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

the above code is used for storing next string character which is start from index i = 1

About your second question :

we can not do

s[0] = '\0';

because at that time we already stored first number in string at s[0]

see

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



回答4:


The answers given here are already good, though i would like to add one more point on the 2nd question. "Ok. But what if input has one white space at the beginning and followed by an operand or operator? In this case, s[1] = '\0' will close the string too early? isn't it?" In this case we do not care about the string at all(it would be overwritten anyway if a number is encountered) because the string is used only if a decimal number is encountered , rest of the characters such as '+' or '-' or '\n' are directly returned.

来源:https://stackoverflow.com/questions/33299349/getop-function-kr-book-p-78

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!