Reputation: 99
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?
Upvotes: 1
Views: 102
Reputation: 46970
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.
Upvotes: 0
Reputation: 43298
(*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);
Upvotes: 2