Home > Enterprise >  Why the increment step inside the for loop is being executed, since not all conditions were met?
Why the increment step inside the for loop is being executed, since not all conditions were met?

Time:01-23

I'm studying C using the "C Programming Language" book, and I got into character arrays (section 1.9) from chapter 1. This is the getline() function it presents:

/* getline: read a line into s, return length */
int getline(char s[], int lim)
{
    int c, i;

    for (i = 0; i < lim-1 && (c = getchar()) != EOF && c != '\n';   i)
        s[i] = c;
    if (c == '\n') {
        s[i] = c;
          i;
    }
    s[i] = '\0';
    return i;
}

Take the word "Hi" as example.

In my point of view, s[1] should be equal to '\n', because the i should be only incremented when all conditions are met, however, when c is equal to '\n', the for loop exits, and i should contain a value of 1 and not 2.

So, why it is being incremented with only 2 of 3 conditions met?

I already tried using pre-increment operators and post-increments operators, and testing the i value inside certain lines of code.

CodePudding user response:

The loop variable i is incremented at the end of the loop body. You can write your for-loop:

for(i = 0; i < lim-1 && (c = getchar()) != EOF && c != '\n'; i  )
    s[i] = c;

as an equivalent while-loop:

i = 0;
while(i < lim-1 && (c = getchar()) != EOF && c != '\n') {
    s[i] = c;
    i  ;
}

Also, I suggest you rename your function to not conflict with the exiting function of the same name. Consider swapping the arguments so you can express how the lim and s variables are related and use size_t instead of int as negative lim probalby doesn't make sense:

size_t my_getline(size_t lim, char s[lim]);

The loop condition to i < lim - 1 is wrong as may write 2 bytes after the loop which will overflow the buffer. If lim <= 0 you overflow the buffer. if lim < 1 you have undefined behavior as c is uninitialized. I suggest you handle the newline in the loop like this, and only write the '\0' if s has room for at least 1 byte:

size_t my_getline(size_t lim, char s[lim]) {
    size_t i = 0;
    while(i < lim - 1) {
        int c = getchar();
        if(c == EOF) break;
        s[i  ] = c;
        if(c == '\n') break;
    }
    if(lim) s[i] = '\0';
    return i;
}
  •  Tags:  
  • c
  • Related