Двойной указатель с массивом в другой функции - PullRequest
0 голосов
/ 08 апреля 2020

Мне нужно создать программу, которая имеет массив клиентов (структуры, которые содержат имя, код и документацию) и функции для вставки, удаления и перечисления всех из них в порядке кода. Я не понимаю, что я должен делать. Обратите внимание, что параметры для insertCostumer, removeCostumer и listCostumer нельзя изменить.

Кусок кода 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;

Кусок кода 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);
}

Кусок кода 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);
    }
}

Я не знаю, что я делаю неправильно; ничего не работает, честно. Я пытался сначала вставить, перечислить и удалить, чтобы попытаться выполнить сортировку позже, но я даже не могу выполнить эту часть. Когда я перечисляю, в списке указан только последний добавленный клиент, например.

Может ли кто-нибудь мне помочь?

1 Ответ

0 голосов
/ 08 апреля 2020

Хорошо, мне пришлось провести рефакторинг значительной части вашего кода, поэтому у меня нет подробного описания изменений.

Вам просто нужно немного изучить его.

Обратите внимание, что даже если вы передали двойной указатель в качестве аргумента, это не значит, что у вас есть , чтобы использовать его в качестве двойного в теле функций. Обратите внимание, в частности, что я сделал для подсчета (например, int count = *p_count; и *p_count = count;)

Но следует отметить, что список является одним из указателей на структуры и не просто указатель на массив структур (то есть является дополнительным уровнем косвенности). Это делает все немного быстрее.

Обратите внимание, что, исправляя ошибку, ключом является операция «сдвиг» в функции удаления.

Поскольку мы «скользим» указатели, это быстрее / эффективнее с массивом указателей. Хорошо изучите эту [концепцию].

Никогда используйте gets - всегда используйте fgets

Я намеренно оставил комментарии. Это позволит вам добавлять их при анализе кода. Я обнаружил, что это может быть мощным методом для понимания [чужой] кодовой базы.

В любом случае, вот код. Я провел некоторое элементарное тестирование, и оно работает:

#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);
}
...