nounoursnoir
nounoursnoir

Reputation: 703

C: dynamic allocation during a scanf

I would like to know if there is any way to dynamically allocate some memory when/before using a scanf. This would mean that there is no need to give a char * a size when initializing it. Instead of this, the quantity of memory needed would be allocated depending on the size of the input string (which means: after having the input).

Currently I find no other solution than to allocate a specific quantity of memory before having the input, so before knowing the size of the input:

char str[10];
scanf("%s", str);

And I know this is not safe: if the input is longer than 10 characters, the program will write on unallocated memory, which can cause segfaults or stuff like that.

Upvotes: 1

Views: 2627

Answers (3)

chux
chux

Reputation: 154280

User input from stdin is tricky.


OP's "if the input is longer than 10 characters, the program will write on unallocated memory" is an off-by 1 problem. If input is longer than 9, the program will attempt to write outside str[].

char str[10];
scanf("%s", str);  // Trouble with input more than 9

getline();, as suggested by this good answer is the typical solution.

I am rejecting the idea of "dynamic allocation during a scanf" as a good design goal. A program that allows for endless input is prone to abuse. It allows the user to overwhelm system resources. Good code validates input first. No more Heartbleed.

Instead I recommend that stdin input is assessed for a reasonable input length, be it 10, 1000, or 1,000,000 and a buffer of 2x or so is provided.

#define MAX_EXPECTED_SIZE 100
char buf[MAX_EXPECTED_SIZE * 2];
if (fgets(buf, sizeof buf, stdin)) {
  size_t len = strlen(buf);
  if (len + 1 == sizeof buf && buf[len] != '\n') {
    // Assume hostile input and act accordingly. Possibly exiting with message.
    // or consume rest of line
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF);

    return ERROR_LONG_LINE
  }

  // Use buf[]
}

Code can allocate the right-sized memory afterward if a copy of buf needs to be retained.

Upvotes: 1

Pras
Pras

Reputation: 4044

As pointed in comments, %m I believe solves your query

Another approach will be to limit the input to number byte you know you have allocated to your variable with eg %10s will input only 10 characters Then reallocating your input variable to make room for more character to be input in next call to scanf, you need to pass str like &str[10] in next call so that it does not overwrite earlier input

Upvotes: 1

Khaled.K
Khaled.K

Reputation: 5950

Use the getline function,

ssize_t getline(char **lineptr, size_t *n, FILE *stream);

Example Try Online

int main(void)
{
    char * line;
    size_t size;

    if(getline(&line, &size, stdin) != (-1))
    {
        printf("You entered: %s",line);
    }

    return 0;
}

Upvotes: 0

Related Questions