Reputation: 1267
I have to read from stdin some characters (i don't know how many of them, but no more than MAX) and I want to store them in an array. Is this code snippet correct?
char *c1 = (char*) malloc(MAX * sizeof(char)); //may be too much
fgets(c, MAX, stdin);
int size = strlen(c1);
char *c2 = (char*) realloc(c1, size * sizeof(char));
free(c1);
Or is there a more elegant way of determining the right amount of memory to allocate for an array when you don't know how many elements to store?
Upvotes: 1
Views: 3998
Reputation: 73366
In the fgets()
, you probably meant c1
, not c
.
You could do it like this (if you insist on using realloc()):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 50
int main() {
char *c1 = malloc(MAX * sizeof(char));
if(!c1) {
printf("malloc() failed\n");
return -1;
}
fgets(c1, MAX, stdin);
int size = strlen(c1);
char* c2;
if(c1[size - 1] == '\n') {
c1[size - 1] = '\0';
c2 = realloc(c1, (size) * sizeof(char));
} else {
c2 = realloc(c1, (size + 1) * sizeof(char));
}
if(!c2) {
printf("realloc() failed\n");
return -1;
}
c1 = NULL;
printf("Input was: %s\n", c2);
free(c2);
return 0;
}
Here are some comments:
You expect to read a string, thus you should use char*
, not
int*
.
Usually, you don't want the newline read by fgets()
to be kept,
thus I used c1[size - 1] = '\0';
, which overwrites it. However, if the user inputs the maximum allowed characters, then there will no room for it, thus we check if a newline was really stored in our buffer.
In the realloc()
, you should allocate space for the size of the
string, PLUS THE NULL TERMINATOR. That's why it's now size+1
. However, in the case we overwritten the newline, there is no need for that, since we have already decreased the size of the string by one, thus size
would suffice.
Never forget to de-allocate your memory.
However, if I were you, I would print a message warning the user to input MAX
characters and avoiding the reallocation.
You see, as the ref of fgets() states, the function will:
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
So, even if the user inputs more, the program will not crash.
As Paul correctly commented, it is a really good idea to use a second pointer, so that if realloc()
fails, we won't lose our data.
Also note that you should't free c1
, because this pointer is invalidated and should be set to NULL
. c1
will likely point where c2
points, thus if we free c1
, then c2
will be pointing to garbage. Or it could be that the whole block of memory is transferred somewhere else, thus c1
points to garbage, we are trying to free.
Upvotes: 1