# Is there an off-by-one error in this example code?

• 06-14-2011
edw211
Is there an off-by-one error in this example code?
Right, so in a K&R exercise, I'm supposed to modify this code (which I haven't touched yet). It currently uses the getline() function to read in lines from input, find the longest one, and output it up to 1000 chars.

I am supposed to change the getline() function to calculate and display the true length of the longest line, but only save 1000 chars (including \n and \0) to an array
and display those. Anything beyond the 1000th character is not displayed.

Here is the code I am to be working with:

Code:

```/* Corresponding K&R Section: 1-9 */ /* Revise longest-line program to print length of         arbitrarily long lines and show as much as         possible of the longest line */ #include <stdio.h> #define MAXLINE 1000 /* maximum input line length */ int getline(char line[], int maxline); void copy(char to[], char from[]); /* print the longest input line */ int main(void) {         int len = 0;                                        /* current line length */         int max = 0;                                        /* maximum length seen so far */         char line[MAXLINE] = {0};                /* current input line */         char longest[MAXLINE] = {0};        /* longest line saved here */                 while ((len = getline(line, MAXLINE)) > 0)                 if (len > max)                 {                         max = len;                         copy(longest, line);                 }                if (max > 0) /* there was a line */                 printf("%s", longest);         return 0; } /* getline: read a line into s, return length */ int getline(char s[], int lim) {         int i = 0; c = 0;                 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; } /* copy: copy 'from' into 'to'; assume to is big enough */ void copy(char to[], char from[]) {         int i;         i = 0;         while ((to[i] = from[i]) != '\0')                 ++i; }```
My confusion stems primarily from this part in getline():

Code:

```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';```
The limit being passed to that function is 1000, the same as the size of the array being passed. The for loop is incrementing i from 0 to 999 (lim - 1). Let's assume that I have an input line 2000 chars in length, and I get to character 998. This is put into the array with "s[i] = c". Fine, now I'm going to break out of the loop because i = lim - 1 = 999.

But now that I've broken out, it seems like it could write '\n' at index 999 then write the null-terminator off the end of the array at index 1000, which is out of bounds. Am I wrong here? Does it work differently because the unary operator in the increment part of the for loop is prefixed?
• 06-14-2011
stahta01
With lim equal to 1000 the max valid value in for loop is 998 because 999 is not less that (1000-1).
Code:

`i < lim - 1`
Tim S.
• 06-14-2011
tabstop
Your for loop will not be able to die with both i equal to 999 and c equal to '\n' -- for if character 998 was '\n', the loop would stop early (while i was still 998) and if the loop stops with i equal to 999, no new character is read into c because of the short-circuit (so even if character 999 was '\n' c would not contain it).
• 06-14-2011
edw211
Quote:

Originally Posted by tabstop
Your for loop will not be able to die with both i equal to 999 and c equal to '\n' -- for if character 998 was '\n', the loop would stop early (while i was still 998) and if the loop stops with i equal to 999, no new character is read into c because of the short-circuit (so even if character 999 was '\n' c would not contain it).

Ohhhhh, it all makes sense now then. Okay, thanks. I had forgotten about short-circuiting. I was thinking as though everything in the loop condition was carried out with every test.