Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically allocate memory space for a string and get that string from user?

I want to read input from user using C program. I don't want to use array like,

char names[50];

because if the user gives string of length 10, then the remaining spaces are wasted.

If I use character pointer like,

char *names;

then I need to allocate memory for that in such a way of,

names = (char *)malloc(20 * sizeof(char));

In this case also, there is a possibility of memory wastage.

So, what I need is to dynamically allocate memory for a string which is of exactly same as the length of the string.

Lets assume,

If the user input is "stackoverflow", then the memory allocated should be of 14 (i.e. Length of the string = 13 and 1 additional space for '\0').

How could I achieve this?

like image 726
Dinesh Avatar asked Nov 17 '11 08:11

Dinesh


People also ask

How do I dynamically allocate memory for strings?

Allocating Strings DynamicallyEditint len = strlen(s); And then allocate the same amount of space plus one for the terminator and create a variable that points to that area in memory: char *s2 = malloc((len + 1) * sizeof(char));

Which function that it dynamically allocates a string to hold the output?

12.12. 8 Dynamically Allocating Formatted Output This function is similar to sprintf , except that it dynamically allocates a string (as with malloc ; see Unconstrained Allocation) to hold the output, instead of putting the output in a buffer you allocate in advance.

How do you dynamically allocate a string array?

T **a = malloc(N * sizeof *a); if (a) for (i = 0; i < N; i++) a[i] = malloc(M * sizeof *a[i]);


4 Answers

Read one character at a time (using getc(stdin)) and grow the string (realloc) as you go.

Here's a function I wrote some time ago. Note it's intended only for text input.

char *getln()
{
    char *line = NULL, *tmp = NULL;
    size_t size = 0, index = 0;
    int ch = EOF;

    while (ch) {
        ch = getc(stdin);

        /* Check if we need to stop. */
        if (ch == EOF || ch == '\n')
            ch = 0;

        /* Check if we need to expand. */
        if (size <= index) {
            size += CHUNK;
            tmp = realloc(line, size);
            if (!tmp) {
                free(line);
                line = NULL;
                break;
            }
            line = tmp;
        }

        /* Actually store the thing. */
        line[index++] = ch;
    }

    return line;
}
like image 140
cnicutar Avatar answered Oct 07 '22 07:10

cnicutar


You could have an array that starts out with 10 elements. Read input character by character. If it goes over, realloc another 5 more. Not the best, but then you can free the other space later.

like image 22
tekknolagi Avatar answered Oct 07 '22 06:10

tekknolagi


If you ought to spare memory, read char by char and realloc each time. Performance will die, but you'll spare this 10 bytes.

Another good tradeoff is to read in a function (using a local variable) then copying. So the big buffer will be function scoped.

like image 7
BigMike Avatar answered Oct 07 '22 07:10

BigMike


You can also use a regular expression, for instance the following piece of code:

char *names
scanf("%m[^\n]", &names)

will get the whole line from stdin, allocating dynamically the amount of space that it takes. After that, of course, you have to free names.

like image 7
Jytug Avatar answered Oct 07 '22 05:10

Jytug