Search code examples
carraysfunctionpointerspointer-to-pointer

Double pointer with array in another function


I have to create a program that has an array of costumers (structs that contain name, code and documentation) and functions to insert, remove and list all of them in order of code. I'm not understanding what I should do. Please note that the parameters for insertCostumer, removeCostumer and listCostumer cannot be changed.

Piece of code 01:

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

#define MAX_REG 10

typedef struct _costumer {
    int code;
    char name[50];
    char documentation[20];
} costumer;

Piece of code 02:

int main(int argc, char** argv) {
    costumer *costumers[MAX_REG];
    costumer **p_costumer;
    p_costumer = &costumers[0];
    int count = 0;

    memset(costumers, 0, sizeof(costumers));

    //Some code to check what to do using a switch
            case '1': insertCostumer(p_costumer, &count); getch(); break;
            case '2': removeCostumer(p_costumer, &count); getch(); break;
            case '3': listCostumers(p_costumer, &count); getch(); break;
    //Some code
    return (EXIT_SUCCESS);
}

Piece of code 03:

void insertCostumer(costumer **p_costumer, int *count){
    char aux[50];
    char aux2[20];

    if(*count < MAX_REG) {
      *p_costumer = (costumer *) malloc(sizeof(costumer));
      printf("\nInsert the code: ");
      gets(aux);
      (*p_costumer)->code = atoi(aux);

      printf("Insert the name: ");
      gets(aux);
      strcpy((*p_costumer)->name, aux);

      printf("Insert the documentation: ");
      gets(aux2);
      strcpy((*p_costumer)->documentation, aux2);

      (*count)++;
      p_costumer = &*p_costumer[*count];

    } else {
        printf("List full! Remove a costumer first!\n");
    }
}

void removeCostumer(costumer **p_costumer, int *count){
    char aux3[50];
    int cod;

    printf("\nInsert the code of the costumer to be removed: ");
    gets(aux3);
    cod = atoi(aux3);

    for(int i = 0; i < *count; i++) {
        if(p_costumer[i]->code == cod) {
            strcpy(p_costumer[i]->name, NULL);
            p_costumer[i]->code = 0;
            strcpy(p_costumer[i]->documentation, NULL);
        }
      }
}

void listCostumers(costumer **p_costumer, int *count){
    for(int i = 0; i < *count; i++) {
        printf("Code: %d | Name: %s | Documentation: %s\n", p_costumer[i]->code, p_costumer[i]->name, p_costumer[i]->documentation);
    }
}

I don't know what I'm doing wrong; nothing is working, honestly. I was trying to first insert, list and remove to try and make the sorting part later, but I can't even get this part done. When I list, only the last costumer added is listed, for example.

Can someone help me?


Solution

  • Okay, I had to refactor a considerable amount of your code, so I don't have a blow by blow description of the changes.

    You'll just have to study it a bit.

    Note that even if you're passed a double pointer as an argument, doesn't mean you have to use it as a double in the body of the functions. Note, in particular, what I did for the count (e.g. int count = *p_count; and *p_count = count;)

    But, it should be noted that the list is one of pointers to structs and not merely a pointer to an array of structs (i.e. there is an extra level of indirection). This makes things a bit faster.

    Note that, bug fixes aside, the key is the "slide" operation in the remove function.

    Because we're "sliding" pointers, this is faster/more efficient with the pointer array. Study this [concept] well.

    Never use gets--always use fgets

    I've deliberately left off comments. This will allow you to add them as you analyze the code. I've found that this can be a powerful technique for understanding a [foreign] code base.

    Anyway, here's the code. I've done some rudimentary testing and it seems to work:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    //#include <conio.h>
    
    #define MAX_REG 10
    char aux[1000];
    
    typedef struct _costumer {
        int code;
        char name[50];
        char documentation[20];
    } costumer;
    
    void
    lineget(char *buf,size_t buflen)
    {
        char *cp;
    
        cp = fgets(buf,buflen,stdin);
    
        if (cp != NULL) {
            cp = strrchr(buf,'\n');
            if (cp != NULL)
                *cp = 0;
        }
    }
    
    void
    insertCostumer(costumer **p_costumer, int *p_count)
    {
        costumer *add;
        int count = *p_count;
    
        char aux2[20];
    
        if (count < MAX_REG) {
            add = malloc(sizeof(costumer));
    
            printf("\nInsert the code: ");
            lineget(aux,sizeof(aux));
            add->code = atoi(aux);
    
            printf("Insert the name: ");
            lineget(add->name,sizeof(add->name));
    
            printf("Insert the documentation: ");
            lineget(add->documentation,sizeof(add->documentation));
    
            p_costumer[count] = add;
            ++count;
        }
        else {
            printf("List full! Remove a costumer first!\n");
        }
    
        *p_count = count;
    }
    
    void
    removeCostumer(costumer **p_costumer, int *p_count)
    {
        int count = *p_count;
        int cod;
        int i;
        costumer *cur;
    
        printf("\nInsert the code of the costumer to be removed: ");
        fgets(aux,sizeof(aux),stdin);
        cod = atoi(aux);
    
        int slide = 0;
        for (i = 0; i < count; i++) {
            cur = p_costumer[i];
            if (cur->code == cod) {
                slide = 1;
                break;
            }
        }
    
        if (slide) {
            free(cur);
            --count;
    
            for (;  i < count;  ++i)
                p_costumer[i] = p_costumer[i + 1];
    
            p_costumer[count] = NULL;
        }
    
        *p_count = count;
    }
    
    void
    listCostumers(costumer **p_costumer, int *p_count)
    {
        costumer *cur;
        int count = *p_count;
    
        for (int i = 0; i < count; ++i, ++cur) {
            cur = p_costumer[i];
            printf("Code: %d | Name: %s | Documentation: %s\n",
                cur->code, cur->name, cur->documentation);
        }
    }
    
    int
    main(int argc, char **argv)
    {
        costumer *costumers[MAX_REG];
        costumer **p_costumer;
        char buf[100];
    
        p_costumer = &costumers[0];
        int count = 0;
    
        memset(costumers, 0, sizeof(costumers));
        setbuf(stdout,NULL);
    
        //Some code to check what to do using a switch
        while (1) {
            printf("operation to perform (1=insert, 2=remove, 3=print): ");
            char *cp = fgets(buf,sizeof(buf),stdin);
            if (cp == NULL)
                break;
    
            switch (cp[0]) {
            case '1':
                insertCostumer(p_costumer, &count);
                break;
    
            case '2':
                removeCostumer(p_costumer, &count);
                break;
    
            case '3':
                listCostumers(p_costumer, &count);
                break;
            }
        }
    
        return (EXIT_SUCCESS);
    }