简体   繁体   English

纯C-传递结构体指针的引用

[英]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 char *名称从不大于64,并且我仍然收到编译错误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. 刚刚注销了分配的块,因为newSize包含分配的记录数,包括现在正在创建的记录数。 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. 注意我假设您有一个现代的C编译器。 The style of your code is C89. 您的代码样式为C89。 That's 1989. If it's an option, you should be using newer C language features. 那是1989年。如果可以选择,则应该使用较新的C语言功能。

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. 您应该传递一个指向数据库大小的指针 ,以便add方法可以更新它。 While calling realloc the way you do is correct, it's inefficient because every call requires time proportional to the entire database size. 以正确的方式调用realloc ,效率很低,因为每次调用都需要与整个数据库大小成比例的时间。 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. 我希望这是有道理的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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