3

I want to read a set of strings in an array. The size of the array is to be decided at run-time using malloc or alloc i.e. the number of strings are accepted as input. I tried the following code but it doesn't worked.

char *array;
array=(char*)malloc(sizeof(char)*t); //t is the size of array
for(int temp=0;temp<t;temp++)
{
    gets(a[temp]);
}

The same worked in case of array of integers.
Please help me in finding the solution.

3
  • BTW sizeof(char) is redundant; it is defined and required by the C standard to be 1. Commented May 8, 2012 at 12:06
  • @glglgl right, sizeof(char) is redundant. Instead I should use malloc(1*t). Commented May 8, 2012 at 12:38
  • why not just malloc(t)? :-) Commented May 8, 2012 at 19:07

4 Answers 4

5

C doesn't have any automatic built-in support for storing strings, there is no variable that is "a string", and can automatically grow to hold the proper number of characters. You need to allocate the memory yourself.

What you're doing now, is allocating place for the proper number of character pointers, but not for any characters. So the gets() call is writing into memory that is not allocated, which is undefined behavior. Since the integers fit completely in a single allocation each, that's why similar code worked for integers. Strings are more complex, so you need to do more work.

If there is any known upper bound on the length of these strings, you can use a temporary buffer of fixed length, and then copy from that into newly allocated dynamic memory once you know the required size. If there is no such bound, you need to repeat the same concept, by reading a fixed block, storing that, and if no end of line was found, read another block, grow the memory allocation for this string using realloc(), append the new characters, and repeat until the line ends.

As a side note, you should always avoid using gets(), since it doesn't support protecting your program against buffer overrun. It's much better to use fgets(), documented on the same page.

Sign up to request clarification or add additional context in comments.

Comments

1

What you allocate is space for exactly one string, stored in zero-terminated format.

If you want to store an array of several strings, you need to malloc() an array of char * PLUS the several strings.

Besides, gets() is unsafe, as there is no size limit. Instead, use fgets(). It has the following signature:

char *fgets(char *restrict s, int n, FILE *restrict stream);

As it wants a stream, you just should give stdin.

So the best way to read one line is

char * read_one_line(uint32_t maxbufsize)
{
    char * s = malloc(maxbufsize);
    if (!fgets(s, maxbufsize, stdin)) {
        free(s);
        return NULL;
    } else {
        char * s2 = realloc(s, strlen(s)+1); // +1 for the NUL at the end
        if (s2) {
            return s2;
        } else {
            return s; // should never happen as the memory block is shrinked
        }
    }
}

This function allocates the memory needed for one line, resizes it appropriately after reading and leaves it to the caller to free it again at the appropriate time.

1 Comment

what is the other efficient way to read array of strings in input?
1

You need to allocate space for an array of strings (char*) first:

char **array;
array = (char**)malloc(sizeof(char*)*t);

Then you need to allocate space for each of them (let's 50 to be maximum count of characters for these strings):

int i = 0, m = 50;
for (i = 0; i < t; ++i)
    array[i] = (char*)malloc(sizeof(char)*51); // 51 = 50 characters + '\0'

And then you can do what you wanted to do:

for(i = 0; i < t; ++i)
    scanf("%50s", array[i]);

Instead of gets, it's better to use scanf with specified width (%50s = 50 characters + '\0').

Comments

0

Just remember that at-last in character array there should be a NUL character.

so allocate t+1 bytes of memory with alloc or malloc.

t bytes for the characters and 1 byte for the terminating NUL character.

after your for loop, i.e. outside of the loop, just write

a[temp] = '\0';

then you can take it in work.

I hope it will work.

it will look like this

char *a = malloc(sizeof((char)*(t+1)));//t is number if characters
int temp;
for(temp=0; temp<t; temp++) {
    gets(a[temp]);
}
a[temp] = 0;

then print array and you'll get a string.

printf("%s",a);

5 Comments

what, you want to call malloc for every character?!
malloc only once for (t+1) times
What does 'times' mean in your context? Do you mean bytes?
Yes,i mean (t+1) bytes..., 't' bytes for storing string and 1 byte for store NULL.
1. Your code example only reads one string (one line). 2. It uses the inherently insecure gets(). Not good.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.