2
Readline from stdin
(lemmy.ml)
If one has POSIX extensions available, then it seems that defining _POSIX_C_SOURCE and just using getline or detdelim is the way to go. However, for source that is just C, here is a solution I've found from various sources, mainly here. I've also tried to make it more safe.
// Read line from stdin
#include <stdio.h>
#include <stdlib.h>
#define CHUNK_SIZE 16 // Allocate memory in chunks of this size
// Safe self-realloc
void *xrealloc(void *ptr, size_t size)
{
void *tmp = realloc(ptr, size);
if (!tmp) free(ptr);
return tmp;
}
// Dynamically allocate memory for char pointer from stdin
char *readline(void)
{
size_t len = 0, chunk = CHUNK_SIZE;
char *str = (char *)malloc(CHUNK_SIZE);
if (!str) return NULL;
int ch;
while((ch = getchar()) != EOF && ch != '\n' && ch != '\r') {
str[len++] = ch;
if (len == chunk) {
str = (char *)xrealloc(str, chunk+=CHUNK_SIZE);
if (!str) return NULL;
}
}
str[len++] = '\0'; // Ensure str is null-terminated
return (char *)xrealloc(str, len);
}
int main(void)
{
setbuf(stdout, NULL); // Ensure environment doesn't buffer stdout
printf("Enter name: ");
char *userName = readline();
if (!userName) return 1;
printf("Hello, %s!\n", userName);
free(userName);
return 0;
}
The idea is that we allocate in chunks of 16, or whichever size. xrealloc is handy when reallocating a block of memory to itself.
int *ptr = malloc(sizeof(int) * 4);
ptr = (int *)realloc(ptr, sizeof(int) * 8);
If realloc fails, ptr gets assigned NULL
, and we lose the address that we need to free, causing a memory leak. So, xrealloc allows for safe self re-allocation.