0

I have structs:

    typedef struct accont
{
    char **tel;//list of tel
    char **email;//list of emails
}acc;

and

typedef struct _strcol
{
    int count;      //total of accounts
    acc **list;
} strcol ;

I access the structure with a pointer:

strcol index;
contato *p;
p = (index.list + index.count);

the question, how i use malloc() in this function?

i try:

(*p)->tel = (char **) malloc(i * sizeof (char*))

p.tel = (char **) malloc(i * sizeof (char*))

&(*p)->tel = (char **) malloc(i * sizeof (char*))

and then as I do the second malloc to save data email or tel

my first post, excuse anything

rafa00706
  • 3
  • 1
  • 2
  • 1
    [Do not cast the return value of `malloc()`](http://stackoverflow.com/a/605858/1983495) – Iharob Al Asimi May 15 '15 at 00:38
  • This `&(*p)` does absolutely nothing, it's the same as just `p`. – Iharob Al Asimi May 15 '15 at 00:45
  • What is the exact problem? Compile error? Segfault? – Khaldor May 15 '15 at 00:48
  • Sorry, are you trying to malloc the elements in the last link of your "list"? Or trying to dynamically grow your "list"? I'm quite confused with your exact objective and exact problem. Could we get a bit more info? \n :-) – Khaldor May 15 '15 at 00:57
  • @JohnBollinger A typo? Supposed to be an `acc`? He's using it as a pointer to `acc` so FTM i'm considering it as such. But this question lacks a tad of detail as to the objective. – Khaldor May 15 '15 at 01:04
  • 1
    @JohnBollinger: The opposite to a `protato`? – caf May 15 '15 at 01:38

4 Answers4

2

So this:

(*p)->tel = (char **) malloc(i * sizeof (char*))

allocates space to store i pointers to char - so you can have i telephone number strings. But you don't actually have any space allocated to store those telephone number strings themselves yet. To do that, you need (for the first telephone number):

(*p)->tel[0] = malloc(j);

If this call to malloc() succeeds, you can now store nul-terminated string of length j-1 in the space pointed to by (*p)->tel[0]. You can then do the same for the other pointers in (*p)->tel up to (*p)->tel[i-1].

caf
  • 233,326
  • 40
  • 323
  • 462
  • Um... Unless he already has the strings containing phone numbers and all (Which i guess are allocated already when parsed or are hard-coded strings.) So realistically, unless he plans on filling his `(*p)->tel[X]` character by character, he can just do `(*p)->tel[X] = str;` – Khaldor May 15 '15 at 01:00
  • @Khaldor: That could be the case, but my guess was that the strings are going to be copied from some ephemeral location. There's just not enough information in the question to tell. – caf May 15 '15 at 01:41
1

Using malloc() is simple if code follows:

some_type *p;
p = malloc(number_of_elements * sizeof *p);
if (p == NULL) Handle_OutOfMemory();

So with p.tel,

// p.tel = (char **) malloc(i * sizeof (char*));
p.tel = malloc(i * sizeof *(p.tel));
if (p.tel == NULL) exit(EXIT_FAILURE);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

If I've understood the case correct, a stack implementation will be best suited in this case. You can use the standard stack library header (of gcc) or create your own stack implementation suited for your own need.

An example may be something like the code below but you'd better follow the Jerry Cain's videos about the stack procedures (you'll find these videos on youtube: Stanford - Programming Paradigms videos. Stack session should be between video number 6 to 8). link from here

note: be careful! Killing stack elements (via StackPop) will not kill the char strings created by strdup. You'll need to free them individually. These are explained in the videos but I don't exactly remember how (again, you'd find some valuable info in those videos for your case).

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

typedef struct {
    char *tel;
    char *email;
} account;

typedef struct {
    int *ptrElement; // starting address of the stack
    int sizeAllocat; // total size allocated
    int sizeCurrent; // current size
    int sizeElement; // byte length of the stack element
} Stack;

// create a new stack pointer
void StackNew (Stack *s, int sizeElement) {
    assert (s->ptrElement > 0);
    s->sizeElement = sizeElement;
    s->sizeCurrent = 0;
    s->sizeAllocat = 4;
    s->ptrElement = malloc (4 * sizeElement);
    assert (s->ptrElement != NULL);
}

// kills a stack pointer
void StackDispose (Stack *s) {
    free (s->ptrElement);
}

// expands stack space
static void StackGrow (Stack *s) {
    s->sizeAllocat *= 2;
    s->ptrElement = realloc (s->ptrElement, s->sizeAllocat * s->sizeElement);
}

// insert new stack pointer (of type account for example)
void StackPush (Stack *s, void *ptrElement) {
    if (s->sizeCurrent == s->sizeAllocat) {
        StackGrow (s);
    }
    void *target = (char *) s->ptrElement + s->sizeCurrent * s->sizeElement;
    memcpy (target, ptrElement, s->sizeElement);
    s->sizeCurrent++;
}

// pops (deletes) an element from stack
void StackPop (Stack *s, void *ptrElement) {
    void *source = (char *) s->ptrElement +
                   (s->sizeCurrent - 1) * s->sizeElement;
    memcpy (ptrElement, source, s->sizeElement);
    s->sizeCurrent--;
}

// relocate stack element
void StackRotate (void *first, void *middle, void *after) {
    int foreSize = (char *) middle - (char *) first;
    int backSize = (char *) after - (char *) middle;
    char tmp [foreSize];
    memcpy (tmp, first, foreSize);
    memmove (first, middle, backSize);
    memcpy ((char *) after - foreSize, tmp, foreSize);
}

int main () {
    Stack s;
    account *acc;
    StackNew (&s, sizeof (acc));

    // your code here
    // example
    // acc->tel = strdup("some number");
    // acc->email = strdup("some text");
    // StackPush(&s, &acc);
    ...
    // StackPop(&s, &acc);
    ...
    ...

    StackDispose (&s);
    return 0;
}
ssd
  • 2,340
  • 5
  • 19
  • 37
0

I'm going to assume 'p' is acc *p; (i have no idea what 'contato' is). Anyway ... the point is to show how memory can be allocated & tel/email data stored/accessed ... Also copied tel #/email id simply to demonstrate ... Regarding casting void pointer returns from malloc, I've seen arguments for/against ... i cast (malloc's about the only case where i cast).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct accont
{
        char **tel;    //list of tel
        char **email;  //list of emails
}acc;

typedef struct _strcol
{
        int count;      //total of accounts
        acc **list;
}strcol;

int main()
{
        int iNumAccounts = 5;   // Assume there are 5 Accounts.
        int iNumTels = 2;       // Each Account has 2 Tel #s.
        int iNumEmails = 3;     // Each Account has 3 Email ids.

        strcol index;
        acc *p = NULL;

        index.list = (acc **)malloc(5 * sizeof(acc *)); // Master list  
            // of 'acc' pointers i.e. pointer to a set of pointers.

        int i, j;
        for(i=0; i<iNumAccounts; i++) // Go through the 5 Accounts, one at 
            // a time ... and allocate & store tel #s/email ids.
        {
                index.list[i] = (acc *)malloc(sizeof(acc));

                p = index.list[i];

                p->tel = (char **)malloc(iNumTels * sizeof(char*));
                for(j=0; j<iNumTels; j++)
                {
                        p->tel[iNumTels] = (char *)malloc(11 * sizeof (char)); // 10 digit tel # + 1 byte for '\0' ...
                        strcpy(p->tel[iNumTels], "1234567890");
                }

                p->email = (char **)malloc(iNumEmails * sizeof(char*));
                for(j=0; j<iNumEmails; j++)
                {
                        p->email[iNumEmails] = (char *)malloc(51 * sizeof(char)); // 50 char long email id + 1 byte for '\0' ...
                        strcpy(p->email[iNumEmails], "kingkong@ihop.yum");
                }
        }

        for(i=0; i<iNumAccounts; i++) // Go through the 5 Accounts, one at a time ... and display.
        {
                p = index.list[i];

                for(j=0; j<iNumTels; j++)
                {
                        printf("Tel # is: %d\n", p->tel[iNumTels]);
                }

                for(j=0; j<iNumEmails; j++)
                {
                        printf("Email id is: %s\n", p->email[iNumEmails]);
                }

                printf("----------\n");
        }
}
iammowgli
  • 159
  • 4
  • 1
    Casting the return value of `malloc()` is unnecessary. Multiplying by .`sizeof (char)` is unnecessary as it is _always_ 1. Better to multiply by the size of the de-referenced pointer. – chux - Reinstate Monica May 15 '15 at 13:58
  • I use sizeof(char), instead of just '1', for consistency & it's clearer to me. Regarding not casting malloc's return, I've read about it ... here's my take: even if I cast & inadvertently introduce a bug by casting it incorrectly, the Compiler will give me a warning. Secondly, if I do not cast ... I can run into the following scenario: int * p; // instead of int ** p. p = malloc(10 * sizeof(int * )); // The compiler does not give a warning ... and the programmer will never know that s/he made a mistake/typo by declaring int * p instead of int ** p; ... Is this not a valid concern ? – iammowgli May 15 '15 at 18:25
  • Solve with `index.list = malloc(5 * sizeof *(index.list));`. – chux - Reinstate Monica May 18 '15 at 01:11