Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getop() function K&R book p 78

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?

like image 682
Hussein Barada Avatar asked Oct 23 '15 09:10

Hussein Barada


1 Answers

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.

like image 121
sifferman Avatar answered Sep 29 '22 13:09

sifferman