Чистый C - Передача ссылки на указатель структуры - PullRequest
0 голосов
/ 24 февраля 2019

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

структура состоит из

typedef struct {
    long unsigned int aem;
    char name[64];
    short unsigned int lessonsToPass;
} Registration;

Я создал указатель на основную функцию

int i, sizeOfDatabase;
Registration *database
scanf("%d", &sizeOfDatabase);
database = (Registration*) malloc(sizeOfDatabase * sizeof(Registration));
for(i = 0; i < sizeOfDatabase; ++i){
    scanf("%lu%63s%hu", &(database+i)->aem, (database+i)->name, &(database+i)->lessonsToPass);
    for(tmp = (database+i)->name; (*tmp=toupper(*tmp)); ++tmp);
}

Итак, в основном я получаю базу данных с клавиатуры и делаю имя в верхнем регистре

после этого я вызываю функцию для добавления новой регистрации

void add(char *aem, char *name, char *lessonsToPass, int currentDatabaseSize, Registration **database){
    char *tmp;
    int newSize = currentDatabaseSize + 1;
    *database = (Registration*) realloc(*database, newSize * sizeof(Registration));
    for(tmp = name; (*tmp=toupper(*tmp)); ++tmp);
    (*database + newSize)->aem = atoi(aem);
    strcpy((*database + newSize)->name, name);
    (*database + newSize)->lessonsToPass = atoi(lessonsToPass);
}

имя char * никогда не превышает 64, и я все еще получаю ошибку компиляции malloc(): corrupted top size

Что яотсутствует

Ответы [ 2 ]

0 голосов
/ 24 февраля 2019

Вы выбрали несколько необычных идиом для представления того, что вы пытаетесь сделать.Вот код, который более понятен и устраняет проблему.Обратите внимание, я предполагаю, что у вас есть современный компилятор Си.Стиль вашего кода - C89.Это 1989 год. Если это вариант, вы должны использовать более новые функции языка C.

Сначала создайте строковый метод в верхнем регистре, чтобы избежать дублирования кода:

void strtoupper(char *s) {
  for (char *p = s; *p; ++p) *p = toupper(*p);
}

Теперь остальные:

int sizeOfDatabase;
Registration *database;

scanf("%d", &sizeOfDatabase);
database = malloc(sizeOfDatabase * sizeof *database); // NO CAST HERE!
for (int i = 0; i < sizeOfDatabase; ++i){
  Registration *r = database + i;
  scanf("%lu%63s%hu", &r->aem, r->name, &r->lessonsToPass);
  strtouper(r->name);
}

Вы должны передать указатель на размер базы данных, чтобы метод add мог его обновить.При правильном вызове realloc он неэффективен, поскольку для каждого вызова требуется время, пропорциональное размеру базы данных.Если это когда-нибудь станет большим, вы бы пожалели об этом.Но это прекрасный момент, который мы проигнорируем.

void add(char *aem, char *name, char *lessonsToPass,
  Registration **database, int *dbSize) {
  int i = (*dbSize)++; // Increase db size by 1 and get new element's index.
  Registration *db = *database = realloc(*database, *dbSize * sizeof **database);
  Registration *r = db + i;
  strcpy(r->name, name);  // DON'T MODIFY THE INPUT.
  strtoupper(r->name);
  r->aem = atoi(aem);
  r->lessonsToPass = atoi(lessonsToPass);
}

Надеюсь, это имеет смысл.

0 голосов
/ 24 февраля 2019
(*database + newSize)->aem = atoi(aem);

Просто списал выделенный блок, потому что newSize содержит количество выделенных записей, включая создаваемую сейчас.Правильный код:

(*database + newSize - 1)->aem = atoi(aem);
strcpy((*database + newSize - 1)->name, name);
(*database + newSize - 1)->lessonsToPass = atoi(lessonsToPass);
...