结构体嵌套成员引用及动态数组扩容等C语言问题求助
员工注册表程序问题求助
结构体定义
typedef struct DOB { int month; int day; int year; } Birthdate; typedef struct EmployeeInfo { int empID; char *firstName; char *lastName; Birthdate date; double salary; } Employee;
主函数代码
int main() { //create the array of Items Employee * employeeRecord = (Employee * ) malloc(N * sizeof(Employee)); Birthdate * birthRecord = (Birthdate * ) malloc(N * sizeof(Birthdate)); int empID; double salary; Employee Employee; Birthdate Birthdate; char opt; while (1) { dispayMenu(); printf("Enter your Choice: "); scanf(" %c",&opt); switch(opt) { case 'i': printf("\nEnter empID: "); scanf("%d", & Employee.empID); printf("Enter firstName: "); scanf("%s", Employee.firstName); printf("Enter lastName: "); scanf("%s", & Employee.lastName); printf("Enter Date of Birth (month/day/year format): "); scanf("%d-%d-%d", &Employee.date.month,&Employee.date.day,&Employee.date.year); printf("Enter Employee salary: "); scanf("%lf", & Employee.salary); insertItem(employeeRecord, Employee); break; case 'u': printf("\nEnter empID to update: "); scanf("%d", & empID); updateItem(employeeRecord, empID); break; case 's': printf("\nEnter empID to search: "); scanf("%d", &empID); searchItem(employeeRecord, empID); break; case 'd': printData(employeeRecord); break; case 'q': quit(employeeRecord); break; default: printf("%c is not a valid choice", opt); } } }
核心问题
- 如何动态更新员工数组的大小?当前出现段错误,不想使用全局变量,不知如何在main中维护插入计数;
- 在updateItem函数中,如何正确访问嵌套的Birthdate成员修改出生日期?当前出现类型不匹配错误,updateItem函数代码如下:
void updateItem(Employee * employeeRecord, int empID) { int i; char chng; for (i = 0; i < current_size; i++) { if (employeeRecord[i].empID == empID) { printf("What data do you wish to update?: "); scanf(" %c", &chng); switch (chng) { case '1': printf("\nEnter new First Name: "); scanf("%s", &Employee.firstName); break; case '2': printf("\nEnter new Last Name: "); scanf("%s", &Employee.lastName); break; case '3': printf("\nEnter new Date of Birth: "); // scanf("%d", &empID); // searchItem(employeeRecord, empID); break; case '4': printf("\nEnter new salary: ") break; case '5': printf("\nReturning to main menu."); break; default: printf("%c is not valid, try it again.", opt); } } break; } else{ printf("Employee Not Found"); } }
此外还存在函数隐式声明与类型不匹配的问题。
解决方案
1. 动态维护员工数组大小与插入计数
不用全局变量,在main中直接维护两个变量:current_count(已插入员工数)和current_capacity(当前数组容量),插入时通过realloc动态扩容:
修改main函数变量定义
int main() { int current_count = 0; int current_capacity = N; Employee *employeeRecord = malloc(current_capacity * sizeof(Employee)); // 无需单独分配birthRecord,Employee结构体已包含Birthdate成员,删除该行 int empID; double salary; Employee newEmployee; // 变量名避免与类型重名,防止混淆 char opt; // ... 后续菜单逻辑 }
重写insertItem函数
传入current_count和current_capacity的指针,方便内部修改,同时注意为字符串成员分配内存:
void insertItem(Employee **employeeRecord, Employee newEmp, int *current_count, int *current_capacity) { // 检查是否需要扩容 if (*current_count >= *current_capacity) { *current_capacity *= 2; // 通常扩容为原容量的2倍 *employeeRecord = realloc(*employeeRecord, *current_capacity * sizeof(Employee)); if (*employeeRecord == NULL) { perror("realloc failed"); exit(EXIT_FAILURE); } } // 复制员工数据,注意为字符串分配内存 (*employeeRecord)[*current_count].empID = newEmp.empID; (*employeeRecord)[*current_count].firstName = malloc(strlen(newEmp.firstName) + 1); strcpy((*employeeRecord)[*current_count].firstName, newEmp.firstName); (*employeeRecord)[*current_count].lastName = malloc(strlen(newEmp.lastName) + 1); strcpy((*employeeRecord)[*current_count].lastName, newEmp.lastName); (*employeeRecord)[*current_count].date = newEmp.date; (*employeeRecord)[*current_count].salary = newEmp.salary; (*current_count)++; }
修改main中的插入调用
// 先临时存储输入的字符串,避免未分配内存导致段错误 char tempFirstName[50], tempLastName[50]; printf("Enter firstName: "); scanf("%49s", tempFirstName); newEmployee.firstName = malloc(strlen(tempFirstName) + 1); strcpy(newEmployee.firstName, tempFirstName); printf("Enter lastName: "); scanf("%49s", tempLastName); newEmployee.lastName = malloc(strlen(tempLastName) + 1); strcpy(newEmployee.lastName, tempLastName); // 调用insertItem insertItem(&employeeRecord, newEmployee, ¤t_count, ¤t_capacity);
2. 正确访问嵌套Birthdate成员修改出生日期
修正updateItem中的语法错误、变量未定义问题,正确访问结构体成员:
void updateItem(Employee *employeeRecord, int empID, int current_count) { int i; char chng; for (i = 0; i < current_count; i++) { if (employeeRecord[i].empID == empID) { printf("What data do you wish to update?: \n"); printf("1. First Name\n2. Last Name\n3. Date of Birth\n4. Salary\n5. Return to menu\n"); scanf(" %c", &chng); switch (chng) { case '1': { char temp[50]; printf("\nEnter new First Name: "); scanf("%49s", temp); free(employeeRecord[i].firstName); // 释放旧内存 employeeRecord[i].firstName = malloc(strlen(temp) + 1); strcpy(employeeRecord[i].firstName, temp); break; } case '2': { char temp[50]; printf("\nEnter new Last Name: "); scanf("%49s", temp); free(employeeRecord[i].lastName); employeeRecord[i].lastName = malloc(strlen(temp) + 1); strcpy(employeeRecord[i].lastName, temp); break; } case '3': printf("\nEnter new Date of Birth (month/day/year): "); scanf("%d-%d-%d", &employeeRecord[i].date.month, &employeeRecord[i].date.day, &employeeRecord[i].date.year); break; case '4': printf("\nEnter new salary: "); scanf("%lf", &employeeRecord[i].salary); break; case '5': printf("\nReturning to main menu."); break; default: printf("%c is not valid, try it again.\n", chng); break; } return; // 找到目标员工后直接返回 } } printf("Employee Not Found\n"); }
修改main中的更新调用
updateItem(employeeRecord, empID, current_count);
3. 解决函数隐式声明与类型不匹配问题
- 在main函数上方添加所有自定义函数的原型,确保调用前声明:
#include <stdio.h> #include <stdlib.h> #include <string.h> // 结构体定义 typedef struct DOB { int month; int day; int year; } Birthdate; typedef struct EmployeeInfo { int empID; char *firstName; char *lastName; Birthdate date; double salary; } Employee; // 函数原型 void dispayMenu(void); void insertItem(Employee **, Employee, int *, int *); void updateItem(Employee *, int, int); void searchItem(Employee *, int, int); void printData(Employee *, int); void quit(Employee *, int);
- 确保所有函数参数类型与调用一致,比如
searchItem、printData都需要传入current_count来控制遍历范围; - 完善
quit函数,释放所有动态分配的内存:
void quit(Employee *employeeRecord, int current_count) { for (int i = 0; i < current_count; i++) { free(employeeRecord[i].firstName); free(employeeRecord[i].lastName); } free(employeeRecord); exit(EXIT_SUCCESS); }
内容的提问来源于stack exchange,提问作者CortadoLover
相关产品推荐
相关产品推荐

