是否可以使用 C 在数组中连续添加



我是学生,我想问一下是否可以在数组中连续添加,

#include <stdio.h>
#include <string.h>
typedef struct
{
int dd;
int mm;
int yy;
}DATE;
typedef struct
{
char name[20];
int ID;
DATE DOB;
char course[20];
int yrlvl;
}Student;
int main()
{
Main_Actions();
return 0;
}
void Main_Actions()
{
char  *arr_Actions[] = {"default","Add Student","Edit Student Information","View all Records","Search Student","Exit",""};
int choice_Actions;
int loop_Actions;
printf("n ========= Actions =========n");
for(loop_Actions = 1; loop_Actions < 6; loop_Actions++)
{
printf("[%d]t",loop_Actions);
printf(arr_Actions[loop_Actions]);
printf("n");
}
printf("==============================");
printf("n Choice: ");
scanf("%d",&choice_Actions);
switch(choice_Actions)
{
case 1:
Add_Student();
break;
default:
printf("n Invalid input!");
break;
}
}
void Add_Student()
{
int intStudentMax;
printf("n Enter the number of students will be record ");
scanf("%d",&intStudentMax);  // Number of students will be added
system("cls");
Student students[intStudentMax]; // Set Student using an Array
for(int i=0; i<intStudentMax; i++) //Loop based on the User Input
{
printf("================================n");
printf("=========== STUDENT [%d]=========n",i+1);
printf("================================n");
printf("n Student[%d] Student ID Number: ",i+1);
scanf("%d", &students[i].ID);
printf("n Student[%d] Student Name: ",i+1);
scanf("%s",&students[i].name);
printf("n Student[%d] Student Course: ",i+1);
scanf("%s",&students[i].course);
printf("n Student[%d] Student Year Level: ",i+1);
scanf("%d",&students[i].yrlvl);

printf("n Student[%d] Student Birthday: ",i+1);
printf("n Month: ",i);
scanf("%d",&students[i].DOB.mm);
printf("n Day: ",i);
scanf("%d",&students[i].DOB.dd);
printf("n Year: ",i);
scanf("%d",&students[i].DOB.yy);
system("cls");
}
for(int j = 0; j < intStudentMax; j++ )
{
printf("%dt%st%st%dn",
students[j].ID, students[j].name, students[j].course,students[j].yrlvl);
}
Main_Actions();
}

这是我的场景,例如(添加学生)我想添加 5 名学生,然后输入所需的详细信息并将它们保存在 5 名学生循环后的数组中,它将返回菜单屏幕,然后一旦用户再次选择添加学生并再次输入另外 5 名学生,那么我的数组中的数据由 10 名学生组成,这可能吗?

"有可能吗...">

是的。答案是肯定的。诀窍是使用循环。一个简单的人会简单地问

是否要添加其他学生(是/否)?

在询问每个学生的信息后。

顺便说一下,您有几个问题:

  • 您的学生列表需要位于Add_Student()功能之外的某个位置。现在它是一个局部变量。对于这样的程序,可以将其设置为全局变量。

    同样,具有最大学生数和一个单独的变量来存储该数组中的当前学生数。

 

#define MAX_STUDENTS 100
Student students[MAX_STUDENTS];
int num_students = 0;
  • 输入是一种痛苦。我建议你使用一个函数来获取它,并返回一个enum来采取行动。

 

typedef enum { ADD_STUDENTS, EDIT_STUDENT, LIST_STUDENTS, ... } Main_Menu_Action;
Main_Menu_Action Main_Menu()
{
printf( "%s",
"Main Menu:n"
"  add  : Add studentsn"
"  edit : Edit studentn"
etc 
"? " );
while (1)
{
char s[100] = "";
fgets( s, sizeof(s), stdin );
if (strcmp( s, "addn" ) == 0) return ADD_STUDENTS;
...

printf( "%s", "Invalid response. Try again.n" );
}
}
  • 您的程序存在无限递归问题。main()调用Main_Actions()哪个调用Add_Student()哪个调用Main_Actions()哪个调用...等等,明白了吗?一个正确的菜单需要让它调用的函数返回

 

void Main_Actions()
{
while (1)
switch (Main_Menu())
{
case ADD_STUDENT: Add_Students(); break;
...
case QUIT: return;
}
}
int main(void)
{
Main_Actions();
return 0;
}
  • 最后,得到一个学生。把它放在一个循环中:

 

bool Ask_YN( const char * prompt )
{
printf( "%s (Y/N)? ", prompt );
char s[10] = "";
fgets( s, sizeof(s), stdin );
if ((s[0] == 'n') || (s[0] == 'N')) return false;
return true;
}
void Add_Students()
{
do Add_Student();
while (Ask_YN( "Would you like to add another student" ));
}

注意我们如何自由地使用实用程序函数来做事情(尤其是输入)吗?在这里,让你的生活尽可能简单。

顺便说一句,使用操作列表的想法很好。你仍然可以按照我的建议做到这一点。有一个成语可以做到这一点:

#define MAIN_ACTIONS(F) 
F( ADD_STUDENT,   "add",  "Add students" ) 
F( EDIT_STUDENT,  "edit", "Edit student" ) 
F( LIST_STUDENTS, "list", "List students" ) 
...
#define ENUM_F(e,n,d) e,
typedef enum { MAIN_ACTIONS(ENUM_F) NUM_ACTIONS } Main_Menu_Action;
#undef ENUM_F
void Print_Main_Menu()
{
printf( "n ========= Actions =========n" );
#define PRINT_F(e,n,d) printf( "%6s : %sn", n, d );
MAIN_ACTIONS(PRINT_F)
#undef PRINT_F
printf("==============================n Choice: ");
}
Main_Menu_Action Main_Menu()
{
Print_Main_Menu();
while (1)
{
...
}
}

当然,您不必使用此成语。它的好处是它将操作的所有确定部分放在一起,而不是在几个结构(枚举和数组)中,然后必须单独维护两者。您仍然可以使用该数组,只需正确定义和使用*_F宏即可。例如:

struct Main_Action_Info
{
Main_Menu_Action action;
const char * name;
const char * description;
};
#define ARRAY_F(e,n,d) { e, n, d },
struct Main_Action_Info Main_Action_Info_Array[] =
{
MAIN_ACTIONS(ARRAY_F)
{ NUM_ACTIONS, NULL, NULL }
};
#undef ARRAY_F

评论太长了——只是对杜托姆哈斯答案的补充:

如果你实现动态内存分配,你甚至可以允许无限数量的学生 - 嗯,实际上受到系统可以提供的内存数量的限制;你需要额外存储还剩下多少容量

Student* students;
size_t count = 0;
size_t capacity = 0;
int main(void)
{
capacity = 128;
students = malloc(sizeof(*students) * capacity);
if(students) // need to test, allocation might have failed
{
// run main loop...
free(students); // clean up properly!
}
else
{
// appropriate error handling, most likely just
// printing some user information...
}
return 0;
}

现在,如果内存不足,只需复制数据存储:

void add_student()
{
if(count == capacity)
{
size_t c = capacity * 2; // assume we won't overflow,
// especially with 64 bit size_t...
// to be totally safe you might want to add a check
Student* s = realloc(students, sizeof(*students) * c);
// need a temporary for the case re-allocation fails, we'd lose
// the sole pointer to original memory to clean up properly
// (-> memory leak)
if(s)
{
capacity = c;
students = s;
}
else
{
// appropriate error handling!
// you might exit (consider then installing an atexit handler
// freeing the memory) or whatever else appears meaningful to you
}
}
students[count] = ...;
++count;
}

请注意,您需要在修改后的容量检查中添加此类容量检查 无论如何add_student功能,即使您仅应用原始答案的更改;然后它可能看起来像

// note: still an array, not the pointer as in this answer:
if(num_students == sizeof(students)/sizeof(*students))
{
// error handling!
}
else
{
students[num_students] = ...;
++num_students;
}

最新更新