I was about to tell you that it was impossible because you need to have an allocate array to read into it when I realized that C++ extractor could do it (inside a std::string
). It is far from trivial and will require that you start with an arbitrary allocated array and realloc
it when you need more space.
Here could be a possible code that reads a word of arbitrary size until the first space character (or EOF):
static char* resize(char* buf, size_t* size) {
size_t new_size = *size * 2;
if (new_size <= *size) { // size_t overflow
free(buf);
return NULL;
}
char* newbuf = realloc(buf, *size);
if (!newbuf) {
free(buf);
return NULL;
}
return newbuf;
}
char* getWord(FILE* fd, size_t* size) {
size_t len = 8, cur = 0;
char* buf = malloc(len);
if (!buf) return NULL;
for (;;) {
int c = fgetc(fd);
if (c == EOF || isspace(c)) {
break;
}
if (cur >= len) {
if (!(buf = resize(buf, &len))) {
return NULL;
}
}
buf[cur++] = c;
}
if (cur >= len) {
if (!(buf = resize(buf, &len))) {
return NULL;
}
}
buf[cur] = '\0';
if (size) {
*size = len;
}
return buf;
}
It could be used that way:
int main() {
size_t sz;
char* buf = getWord(stdin, &sz);
printf("%s (%d)\n", buf, sz);
return 0;
}
and when passed exactly 8 characters (abcdefgh
), it correctly displays:
abcdefgh (16)
because it allocated one extra position for the terminating null.