Hazim
Hazim

Reputation: 381

Dynamically allocating lines from stdin?

I'm trying to read a file of 10 lines of varying lengths (which will not exceed 349 characters), and store them in a dynamically allocated array in order to be able to manipulate them later on. I have the below code which gives me a "warning: passing argument 1 of âstrcpyâ makes pointer from integer without a cast" message.

What did I do wrong here? My logic was that addresses should be a pointer to an array of pointers, where each pointer in the array points to a line in the string, which I would try to make happen by using strcpy of that line to that point.

    char buffer[350];
    char** addresses;
    int i = 0;

    *addresses = malloc(sizeof(char*)*10); /* Let's start off with 10 addresses  */

    while(fgets(buffer, sizeof(buffer), stdin) != NULL)
    {
            strcpy(*addresses[i],buffer);
            i++;
    }

Upvotes: 0

Views: 1780

Answers (4)

autistic
autistic

Reputation: 15642

To quickly address the errors I see here:

  • You're dereferencing addresses (eg. *addresses or addresses[0]) without ensuring that addresses points somewhere valid. You need to assign to addresses before you dereference.
  • The type of *addresses[i] in strcpy(*addresses[i],buffer) is char, where it is expected that it be char *. This is what your compiler is complaining about. I suspect that you meant strcpy(addresses[i], buffer).

Even if you're to run this code in an embedded environment, your requirements seem simple enough that you shouldn't need malloc. In fact, introducing malloc complicates things... I tend avoid it unless absolutely necessary. Use automatic storage duration, instead. It'll make life easier, because you won't have as many error situations to handle (though as it is you aren't handling them anyway)...

#define nelem(array) (sizeof array / sizeof *array) /* number of elements in array */

int main(void)
{
    char address[10][351] = { 0 };
    size_t size = 0;
    while (size < nelem(address) && fgets(address + size, sizeof *address, stdin))
    {
         address[size][strcspn(address[size], "\n")] = '\0';
         size++;
    }
}

Note that 10 and 351 only appear once here... Feel free to adjust them as you feel fit, within reason. If you can multiply them into the megabytes region, you might want to consider a different data structure depending on what you intend to do with this.

Upvotes: 1

Gopi
Gopi

Reputation: 19874

addresses is a pointer to pointer so you need to allocate memory for your pointers first and later allocate memory to each pointers individually as shown below.

In 2D space if addresses is a pointer to a pointer then addresses[i] is a pointer.So allocate memory for it before writing to this location.

    char** addresses;

    addresses = malloc(sizeof(char*)*10);// Now you 10 character pointers
    int i = 0;
    while(fgets(buffer, sizeof(buffer), stdin) != NULL)
    {
        size_t n = strlen(buffer);
        if(n>0 && buffer[n-1] == '\n')
        buffer[n-1] = '\0';
        if(i>=10)
        break;
        addresses[i] = malloc(strlen(buffer)+1);//Allocate memory to the pointer before writing to it
        strcpy(addresses[i],buffer);
        i++;
    }

PS: fgets() comes with a newline character so I have added a check to replace a newline character with a null.

Upvotes: 1

Karthikeyan.R.S
Karthikeyan.R.S

Reputation: 4041

You have to give like this,

strcpy(addresses[i],buffer);

If you give like this,

strcpy(*addresses[i],buffer);

First argument will consider as a single character.

And while allocating the memory you have do like this,

address=malloc(sizeof(char)*10);

You have to allocate the memory for each pointer.

address[i]=malloc(strlen(buffer)+1);

Or else, you can use strdup function which will allocate the memory for given string length.

address[i]=strdup(buffer);

The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3).

Upvotes: 1

R Sahu
R Sahu

Reputation: 206667

You've got couple of issues:

  1. Syntax:

    Use

    strcpy(addresses[i],buffer);
    

    instead of

    strcpy(*addresses[i],buffer);
    
  2. Memory:

    You need to allocate memory for addresses[i] before you can copy the contents of buffer to it.

    Add a line to allocate memory for addresses[i] before the call to strcpy.

    addresses[i] = malloc(sizeof(buffer));
    

Upvotes: 2

Related Questions