简体   繁体   中英

Pure C - Passing the reference of a pointer of a struct

I have created a program that is loading a database with student information from the keyboard, after that I am trying to create an option to add a new registration of a student to that database

the struct consists of

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

I have created a pointer of it on the main function

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

So basically I am getting the database from the keyboard and making the name to uppercase

after that I am calling a function to add a new registration

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

the char *name is never bigger than 64 and I am still getting compilation error malloc(): corrupted top size

What am I missing?

(*database + newSize)->aem = atoi(aem);

Just wrote off the allocated block because newSize contains the number of allocated records including the one being created now. Correct code:

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

You've chosen some unusual idioms to represent what you're trying to do. Here's code that's more understandable and fixes the problem. Note I'm assuming you have a modern C compiler. The style of your code is C89. That's 1989. If it's an option, you should be using newer C language features.

First make a string uppercase method to prevent duplicate code:

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

Now the rest:

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

You should pass a pointer to the database size so the add method can update it. While calling realloc the way you do is correct, it's inefficient because every call requires time proportional to the entire database size. If it ever got big, you'd regret this. But that's a fine point we'll ignore.

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

I hope this makes sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM