Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在用户需要时创建新的结构变量_C_Struct - Fatal编程技术网

C 在用户需要时创建新的结构变量

C 在用户需要时创建新的结构变量,c,struct,C,Struct,我刚刚开始使用C,在结构方面遇到了一些问题。例如,我有: struct student { int id; char name[25] }; 我希望用户根据需要添加尽可能多的学生: int count = 0; while (stop == 0){ struct student count scanf("%d", count.id); scanf("%s", count.name); scanf("%d", stop); } 看起来我必须创建

我刚刚开始使用C,在结构方面遇到了一些问题。例如,我有:

struct student {
    int id;
    char name[25]
};
我希望用户根据需要添加尽可能多的学生:

int count = 0;
while (stop == 0){
    struct student count
    scanf("%d", count.id); 
    scanf("%s", count.name);
    scanf("%d", stop);
}
看起来我必须创建
struct student count
(其中count是一个数字),并继续创建这些。因此,我想创建类似于
struct student 0
,然后创建
struct student 1
等等的内容,这样我就可以通过每个学生的计数或数字来引用它。
如何让这样的东西工作?

我想您应该在第一个代码示例中为在控制台中输入的每个用户创建结构的多个实例,由
while
-循环处理

实现这一点的最简单方法是使用数组。我建议您首先使用具有固定大小的数组,这意味着您要在代码中指定数组大小。此数组将允许您向其中添加与指定的数组大小相同数量的学生实例

一个简单的例子如下:

// Define the student struct
struct student {
    int id;
    char name[25];
};

// ...

// Create an array with a fixed size to put the students in, and define a counter
struct student students[128];
int count = 0;

while(stop == 0){
    // Create the struct to fill
    struct student newStudent;

    // Fill the struct with the user supplied data
    scanf("%d", newStudent.id);
    scanf("%s", newStudent.name);
    scanf("%d", stop);

    // Add the struct to the array, and increase the count afterwards
    students[count++] = newStudent;
}
在上面的示例中,我添加了一个固定大小为128的数组,您可以将其更改为任意大小。在
while
-循环中,创建了一个新结构的实例,这与之前的类似。该结构随后将由控制台提供的数据填充。在while循环的末尾,结构实例被添加到学生数组中。这将为您提供一个包含所有已输入学生的数组

然而,这种解决方案有一个缺点,那就是在大多数情况下,消耗的内存比实际使用的内存多得多。这是因为对于计算机来说,感觉好像128个完整实例(或任何其他数组大小,如果指定)存储在RAM中,如果只使用两个实例,这可能会非常昂贵。此外,正如我前面所说的,请务必记住,固定数组大小会限制条目数,这也会对代码产生负面影响。如果您不想产生这些后果,您可能想看看下面描述的解决方案

您可以使数组的大小成为动态的,这稍微高级一点。如果你想实现这样的目标,一定要看一看,就像在评论中指出的那样。您可能还想看看made


我希望这有助于解决您的问题。快乐编码

这将在用户请求时自动分配内存。它从1维开始,一直到几乎无限(实际上,一直到RAM中可用的空间)。 当然,如果您愿意,您可以更改
size
的初始大小以及阵列的增长率

// Example program
#include <stdio.h>      /* printf, scanf */
#include <stdlib.h>         /* for realloc, malloc */

// Supposing student is defined like this: 
struct student 
{ 
  int id; 
  char name[25];
};

int main()
{
  int stop = 0;
  int count = 0;
    int size = 0;

    // Using an array of students
    size = 1;
  struct student* students = malloc(size * sizeof(struct student));

  while (stop == 0)
  {
        if(count >= size)
        {
            size ++;
            students = realloc (students, size * sizeof(struct student));

            if (students == NULL)
            {
                printf ("Failed to allocate more memory.\n");
                return 0;
            }
        }   

    scanf("%d", &(students[count].id)); 
    scanf(" %24[0-9a-zA-Z ]", &(students[count].name));
    scanf("%d", &stop);
    count = count + 1;
  }

  int i = 0;
  for (i = 0; i < count; ++i)
    printf("%d => %d  %s\n", i, students[i].id, students[i].name);
}
//示例程序
#包括/*printf、scanf*/
#包括/*适用于realloc、malloc*/
//假设学生的定义如下:
结构学生
{ 
int-id;
字符名[25];
};
int main()
{
int stop=0;
整数计数=0;
int size=0;
//使用一组学生
尺寸=1;
struct student*students=malloc(size*sizeof(struct student));
while(stop==0)
{
如果(计数>=大小)
{
大小++;
学生=realloc(学生,大小*大小(结构学生));
如果(学生==NULL)
{
printf(“未能分配更多内存。\n”);
返回0;
}
}   
scanf(“%d”,&(学生[count].id));
scanf(“%24[0-9a-zA-Z]”,&(学生[count].name));
scanf(“%d”,停止(&S);
计数=计数+1;
}
int i=0;
对于(i=0;i%d%s\n”,i,学生[i].id,学生[i].name);
}

考虑一个指针并学习关于数组的学习。如果你搜索这个站点“StultStaveStudio”,你会发现这个问题已经回答了很多次。如果你知道你只需要一个固定数量的学生,使用一个数组。否则,请使用指针和动态内存分配。这些都是C的基本概念,如果您还不了解它们,这可能意味着您应该在尝试此练习之前阅读更多的课本。虽然编译器会对范围进行分类,但如果有两个名为
count
的完全不同的变量,可能会让读者感到困惑。在调用malloc()时,realloc(),1)在C中,不要强制转换这些函数返回的值。返回的类型是
void*
,可以分配给任何指针。强制转换只会使代码变得混乱,使其更难理解、调试和维护。2) 始终检查(!=NULL)返回值以确保操作成功。对于realloc(),这意味着使用临时变量,因此如果realloc()失败,分配的内存指针不会丢失。丢失分配的内存指针会导致内存泄漏。关于对
scanf()
的调用,请始终检查返回值(而不是参数值),以确保操作成功。(在当前场景中,除1之外的任何返回值都表示发生了错误。关于此行:
scanf(“%s”&(students[count].name));
“%s”格式说明符将不会跨过
空格(通常是空格、制表符、换行符),因此相关的scanf()将失败。建议将格式字符串替换为:
%s”
(请注意前导空格,它将消耗任何剩余的空白)使用“%s”格式说明符调用
scanf()
时,始终将输入的字符数限制为小于输入缓冲区长度的1。1)这允许scanf()始终附加NUL char 2)这会阻止用户输入足够的字符以溢出输入缓冲区,从而导致未定义的行为,并可能导致seg错误事件。若要允许学生姓名多于一个单词,建议使用格式字符串
“24%[\n]:
因此,在输入换行符之前,所有字符都将被输入,并且前导空格将被跳过,并且没有缓冲区溢出