You can read words with scanf
using the "%s"
format specifier and concatenate them into a line using a loop (adding spaces where needed). You can use a fixed size buffer if you have some reasonable maximum number of characters you anticipate, or you can allocate and reallocate using malloc
and realloc
-- that is up to you. In either case the logic is the same, you have to track the number of characters available and how many you have used to know whether the next word will fit. The only difference being when dynamically allocating memory you have the option to reallocate additional storage and keep going, while in the case of the fixed buffer you simply have to handle the error of the line being too long to fit.
In either case when using scanf
with the "%s"
conversion specifier, you must also use the field-width modifier to ensure you don't read more characters than will fit into the storage for the word. For example if your word buffer is 128
characters, you must use "%127s"
to limit the number of characters you can store to 127
plus 1
for the nul-terminating character. Otherwise your use of scanf
is no safer than using gets
, see Why gets() is so dangerous it should never be used!
A simple example addressing your input and output could be:
#include <stdio.h>
#include <string.h>
#define MAXC 1024 /* max chars per-word and line */
int main (void) {
char buf[MAXC + 1] = "", word[MAXC]; /* line and word buffers */
size_t remain = MAXC; /* available space that remains */
fputs ("input : ", stdout); /* prompt for input */
for (;;) { /* loop continually */
char c; /* char following word */
int rtn = scanf ("%1023s%c", word, &c); /* read word & c, save return */
if (rtn > 0) { /* if word read */
size_t len = strlen(word); /* get word length */
if ((remain - len) > 0) { /* if space remains */
if (remain < MAXC) { /* if not 1st word */
strcat (buf, " "); /* add space between words */
remain--; /* decrement remains */
}
strcat (buf, word); /* add word to buf */
remain -= len; /* reduce remain by len */
}
else { /* handle line too long */
fputs ("error: line too long.\n", stderr);
return 1;
}
}
if (rtn == EOF || c == '\n') { /* if EOF or end of line */
printf ("output: %s\n", buf); /* output line */
break; /* break */
}
}
}
Example Use/Output
$ ./bin/scanf_words_buf
input : hi my name is..
output: hi my name is..
The key is to put your accountants hat on and ensure you do not write beyond the storage available.