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