tags:

views:

297

answers:

8

Actually, I'm new at C-programming, so there is the sample from Kernighan & Ritchie's "The C Programming Language":

int getline(char s[], int lim)
{
   int c, i;
   i=0;
   while (--lim > 0; && (c=getchar()) !=EOF && c !='\n')
      s[i++] = c;
   if (c =='\n') 
      s[i++] = c;
   s[i] = '\0';
   return i;
}

Why do we should check if c != '\n', despite we use s[i++] = c after that?

A: 

You do that just to exit the while loop on new line. Else you would have to check it in while body and use break.

oh, becouse c can catch next line...it's really simple, thank you.
willson
+1  A: 

The comparison is to ensure readline terminates when it encounters a newline character (the '\n'). On the iteration where it does, it terminates without adding the newline to the string, so the statement after that ensures that the string is always newline terminated, even if one of the other termination conditions was reached.

Nick Johnson
A: 

That ensures that you stop at the end of the line even if it's not the end of the input. Then if there is a newline the \n is added to the end of the line and i incremented one more time to avoid overwriting it with the \0.

HitScan
A: 
int getline(char s[], int lim)
{
   int c, i;
   i=0;
   /* While staying withing limit and there is a char in stdin and it's not new line sign */
   while (--lim > 0; && (c=getchar()) !=EOF && c !='\n')
   /* Store char at the current position in array, advance current pos by one */
      s[i++] = c;
   /* If While loop stopped on new-line, store it in array, advance current pos by one */
   if (c =='\n') 
      s[i++] = c;
   /* finally terminate string with \0 */
   s[i] = '\0';
   return i;
}
aku
+3  A: 

The functions reads characters from the standard input until either EOF or a newline characters is found.

The second check ensures that the only newline character is put into the char array. EOF shouldn't occur in a proper c-string. Also, if the character isn't newline that means that we might have filled up our c-string, in which case we shouldn't put any more characters into it.

Notice we still append the '\0'. We've ensured that theres still room for one more character in our c-string, as we use the pre-fix decrementor, which evaluates before the comparison.

aggergren
Don't you mean prefix decrementor? I assume you are talking about --lim as that is the only decrementor in the code.
Corin
A: 

I'm not sure whether I understand the question. c !='\n' is used to stop reading the line when the end of line (linefeed) occurs. Otherwise we would always read it until the limit even if it ends before. The first s[i++] = c; in the while-loop doesn't occur if a linefeed has been reached. That's why there is the special test afterwards and the other s[i++] = c; in case it was a linefeed which broke the loop.

auramo
A: 

Not answering your question, but I'll write some comments anyway:

I don't remember all K&R rules, but the function you've listed will fail if lim is equal to one. Then you won't run the loop which leaves c unintialised, but you'll still use the variable in the if (c == '\n') check.

Also the while (--lm > 0; ...) thing will not go through the compiler. Remove the ';' and it does.

+1  A: 

There is a bug in the code.

If the size of s is N bytes and the user types a newline as the (N-1)th character, the Nth character will become a '\n' and the (N+1)th character (which is not allocated) will become a '\0'.