This is a classic thing to want to do since it's in C that one doesn't have the std::string
of C++ and input
of Python.
I believe that the best thing to do is to read the input stream character by character, since scanf
is unsafe and fgets
requires an expected size to be passed, things which I do not want to do.
I've read other answers in this site, but they seem to overcomplicate things too much, maybe the following code fails in borderline cases and I'm just ignorant, but as far as I've tried, this works fine. Even with piping on bash.
The reason i do realloc(str, buf - 1)
is to be able to store up to SIZE_MAX
since, when an overflow occurs, buf
will equal 0 and 0 - 1 in a size_t
will be equal to SIZE_MAX
.
So I tried the following approach:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *str = malloc(2);
if (!str) {
printf("Cannot allocate string.\n");
return 1;
}
int c;
char *reallocStr;
size_t len = 0;
size_t buf = 2;
printf("Enter some text: ");
while ((c = getchar()) != EOF && c != '\n') {
if (len + 1 == buf) {
buf *= 2;
reallocStr = realloc(str, buf - 1);
if (!reallocStr) {
printf("Cannot reallocate string.\n");
free(str);
return 1;
}
str = reallocStr;
}
str[len++] = c;
}
str[len] = '\0';
printf("You entered: %s\n", str);
free(str);
return 0;
}
INT_MAX
,SIZE_MAX
,UINTMAX_MAX
or what? Do you want no upper bound? Until memory runs out? \$\endgroup\$