RedYoel
RedYoel

Reputation: 313

how to fill an array of pointers in c

I want to fill an array of char pointers in the following format:

[name, number of email addresses, all the email addresses]*number of people. The number of mail adresses for each person isn't known at first.

This is my main so far:

int main()
{
    char *contacts[N];
    int nextAvailable = 0;
    int * const nextAvailableP = &nextAvailable;
    add(contacts, nextAvailableP);
    //Printing this way will only print contacts[0]
    int i;
    for (i = 0; i < nextAvailable; i++) {
        printf("%s", contacts[i]);
    }
}

This is the add function:

int add(char *contacts[], int *nextAvailableP) {
    if (*nextAvailableP > 97) {
        printf("Not enough memory\n");
        return FALSE;
    }

    char tempName[50];
    char tempMail[50];
    int numberOfMails = 1;

    printf("Enter your name\n");
    fgets(tempName, 50, stdin);
    if ((strlen(tempName) > 0) && (tempName[strlen(tempName) - 1] == '\n'))
        tempName[strlen(tempName) - 1] = '\0';

    contacts[*nextAvailableP] = (char *)malloc((strlen(tempName) + 1));

    if (contacts[*nextAvailableP] == NULL) {
        printf("Not enough memory\n");
        return FALSE;
    } else {
        strcpy(contacts[*nextAvailableP], tempName);
    }

    (*nextAvailableP)++;
    int numberOfMailsIndex = *nextAvailableP;
    itoa(numberOfMails, contacts[numberOfMailsIndex], 10);
    (*nextAvailableP)++;
    

    printf("Enter your mail/s, use enter to enter a mail and '-1' to signal you finished\n");
    fgets(tempMail, 50, stdin);

    while (strcmp(tempMail, "-1") != 0) {
        if ((strlen(tempMail) > 0) && (tempMail[strlen(tempMail) - 1] == '\n')) {
            tempMail[strlen(tempMail) - 1] = '\0';
        }

        contacts[*nextAvailableP] = (char *)malloc((strlen(tempMail) + 1));
        
        if (contacts[*nextAvailableP] == NULL) {
            printf("Not enough memory");
            return FALSE;
        } else {
            strcpy(contacts[*nextAvailableP], tempMail);
        }
        (*nextAvailableP)++;
        numberOfMails++;
        itoa(numberOfMails, contacts[numberOfMailsIndex], 10);
        fgets(tempMail, 50, stdin);
    }
}

I thought I was initializing each cell in contacts to the requested size and then copying the word I scan from the user into it - but obviously I'm not. Should I iterate through each memory I've allocated char by char?

Btw, I know that the casting to *char isn't necessary

Upvotes: 1

Views: 821

Answers (2)

bd123456
bd123456

Reputation: 26

So this would be your corrected code

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

#define MAX_ENTRIES 50

int add(char *contacts[], int *nextAvailable);

int main(void){
    int i;
    char *contacts[MAX_ENTRIES];
    int nextAvailable = 0;
    add(contacts, &nextAvailable);
    add(contacts, &nextAvailable);

    for(i=0; i < nextAvailable ; i++){
        printf("%s\n", contacts[i]);
    }
}

char* intToString(int val, int base){
    //source: www.strudel.org.uk/itoa/
    static char buf[32] = {0};

    int i = 30;

    for(; val && i ; --i, val /= base)

        buf[i] = "0123456789abcdef"[val % base];

    return &buf[i+1];

}

int add(char *contacts[], int *nextAvailableP) {
    if (*nextAvailableP > 97) {
        printf("Not enough memory\n");
        return 0;
    }

    char tempName[50];
    char tempMail[50];
    int numberOfMails = 1;

    printf("Enter your name\n");
    fgets(tempName, 50, stdin);
    if ((strlen(tempName) > 0) && (tempName[strlen(tempName) - 1] == '\n'))
        tempName[strlen(tempName) - 1] = '\0';

    contacts[*nextAvailableP] = (char *)malloc((strlen(tempName) + 1));

    if (contacts[*nextAvailableP] == NULL) {
        printf("Not enough memory\n");
        return 0;
    } else {
        strcpy(contacts[*nextAvailableP], tempName);
    }

    (*nextAvailableP)++;
    int numberOfMailsIndex = (*nextAvailableP);
    contacts[numberOfMailsIndex] = malloc(5);
    (*nextAvailableP)++;

    printf("Enter your mail/s, use enter to enter a mail and '-1' to signal you finished\n");
    fgets(tempMail, 50, stdin);

    while (strcmp(tempMail, "-1\n") != 0) {
        if ((strlen(tempMail) > 0) && (tempMail[strlen(tempMail) - 1] == '\n')) {
            tempMail[strlen(tempMail) - 1] = '\0';
        }

        contacts[*nextAvailableP] = (char *)malloc((strlen(tempMail) + 1));

        if (contacts[*nextAvailableP] == NULL) {
            printf("Not enough memory");
            return 0;
        } else {
            strcpy(contacts[*nextAvailableP], tempMail);
        }
        (*nextAvailableP)++;
        numberOfMails++;
        fgets(tempMail, 50, stdin);
    }
    strcpy(contacts[numberOfMailsIndex], intToString(numberOfMails - 1,10));

}

Upvotes: 1

bd123456
bd123456

Reputation: 26

Your function add could be cut in a subfunction which gets a string from the user. This string will be stored in a allocated memory space which has the size of string.

Keep in mind : It's not a good practice to mix data of different nature in one array (names and email). It would be better to use structs (as @Barmar said).

I would do following steps:

  • Get name from user (char *)
  • Allocate memory and copy the name into it.
  • insert the pointer to this allocated memory into your array (contacts)
  • Get a email address put it in a dynamic allocated memory space
  • add its pointer to your array (Contacts
  • Increment emails counter
  • repeat
  • -1 detected
  • convert your email counter to string and the pointer into your array

Anyway here's a code that you can start play with:

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

#define MAX_ENTRIES 50
#define BUFFERSIZE 50

int add(char *contacts[], int *nextAvailable);
char *getString(char *queryText);
char* intToString(int val, int base);

int main(void){
    int i;
    char *contacts[MAX_ENTRIES];
    int nextAvailable = 0;
    add(contacts, &nextAvailable);
    add(contacts, &nextAvailable);

    for(i=0; i < nextAvailable ; i++){
        printf("%s", contacts[i]);
    }
}

int add(char *contacts[], int *nextAvailable){
    if(*nextAvailable > MAX_ENTRIES - 1){
        printf("Not enough memory\n");
        return 1;
    }

    contacts[*nextAvailable] = getString("Enter your name\n");
    if(contacts[*nextAvailable] == NULL){
        printf("Malloc Error\n");
        return 1;
    }
    ++(*nextAvailable);
    int counterfield = *nextAvailable;
    ++(*nextAvailable);
    int emailCounter = 0;
    while(1){

        if(*nextAvailable > MAX_ENTRIES - 1){
            printf("Not enough memory\n");
            return 1;
        }
        char *email = getString("Enter email\n");
        if(strcmp(email, "-1\n") == 0){

            contacts[counterfield] = malloc(5);
            contacts[counterfield] = intToString(emailCounter,  10);

            return 0;
        }
        emailCounter++;
        contacts[*nextAvailable] = email;
        ++(*nextAvailable);

    }


}


char *getString(char *queryText){
    char buffer[BUFFERSIZE];
    char *ret;
    printf("%s", queryText);

    fgets(buffer, BUFFERSIZE, stdin);
    ret = malloc(strlen(buffer));

    strcpy(ret, buffer);
    return ret;
}

char* intToString(int val, int base){
    //source: www.strudel.org.uk/itoa/
    static char buf[32] = {0};

    int i = 30;

    for(; val && i ; --i, val /= base)

        buf[i] = "0123456789abcdef"[val % base];

    return &buf[i+1];

}

Upvotes: 0

Related Questions