2

I get very unexpected output from quite simple code

char ch = getchar(), word[100], *p = word;

while (ch != '\n') {
    *(p++) = ch;
    ch = getchar();
}
puts(word);

output of any 17 character input is appended by "time" like

12345678901234567time

if exceeds "time" is overwritten like

1234567890123456789me

Am I doing something wrong?

chqrlie
  • 131,814
  • 10
  • 121
  • 189

2 Answers2

2

puts expects a pointer to string. And a string needs to have a terminating null character - \0 - to signify where the string ends.

But in your case, you did not write the \0 at the end to signify that the string ends there.

You need to do:

char ch = getchar(), word[100], *p = word;

/* Also check that you are not writing more than 100 chars */
int i = 1;
while(ch != '\n' && i++ < 100){  
    *(p++) = ch; 
    ch = getchar();
}
*p = '\0'; /* write the terminaring null character */
puts(word);

Before, when you were not writing the terminating null character you could not expect anything determinate to print. It could also have been 12345678901234567AnyOtherWord or something.

sps
  • 2,720
  • 2
  • 19
  • 38
2

There are multiple issues in your code:

  • You do not null terminate the string you pass to puts(), invoking undefined behavior... in your case, whatever characters happen to be present in word after the last one read from stdin are printed after these and until (hopefully) a '\0' byte is finally found in memory.
  • You read a byte from stdin into a char variable: this does not allow you to check for EOF, and indeed you do not.
  • If you read a long line, you will write bytes beyond the end if the word array, invoking undefined behavior. If the end of file is encountered before a '\n' is read from stdin, you will definitely write beyond the end of the buffer... Try for example giving an empty file as input for your program.

Here is a corrected version:

char word[100];
char *p = word;
int ch;

while ((ch = getchar()) != EOF && ch != '\n') {
    /* check for long line: in this case, we truncate the line */
    if (p < word + sizeof(word) - 1) {
        *p++ = ch;
    }
}
*p = '\0';
puts(word);
chqrlie
  • 131,814
  • 10
  • 121
  • 189