这是我的全部代码,看起来很有用,但效果不太好。
我会接受任何代码,就是这样工作的。
首先,代码可以工作,但是当我想向结构添加第三个名称时,它会崩溃。
还有别的办法吗?
我需要struct,因为在将来,我想添加一些其他参数,如年龄、平均值、性别等。
求你了,帮帮我。

//The student table
typedef struct students {
    char name[50];
} students;

//Global params
int scount = 0;
students *s;

//Basic functions
void addNewStudent();

int main()
{
    int loop = 1;
    char in;
    int ch;
    printf("Willkommen.\n Wahlen Sie bitte von die folgenden Optionen:\n");
    while (loop)
    {
        printf("\t[1] Neue Student eingeben\n");
        printf("\t[9] Programm beenden\n");

        scanf(" %c", &in);
        while ((ch = getchar()) != '\n');
        switch (in)
        {
        case '1':
            addNewStudent();
            break;
        case '9':
            loop = 0;
            break;
        default: printf("------\nOption nicht gefunden.\n------\n");
            break;
        }
    }
    free(s);
    return 0;
}

void addNewStudent()
{
    int index = 0;
    if (scount == 0)
    {
        s = (students*)malloc(sizeof(students));
    }
    else
    {
        realloc(s, sizeof(students) * scount);
    }

    printf("Geben Sie Bitte die Name:\n");
    fgets(s[scount].name, sizeof(s[scount].name), stdin);

    while (s[scount].name[index] != '\n')
    {
        index++;
    }
    s[scount].name[index] = '\0';
    scount++;
}

我在用Visual Studio。
谢谢你的帮助!

最佳答案

students *mynew= realloc(s, sizeof(students)* (scount+1));
if( mynew != NULL )
    s=mynew;

另外你的记忆有漏洞。您没有使用返回值realloc
不要强制转换malloc的返回类型。
根据标准7.22.2.35
void *realloc(void *ptr, size_t size)

realloc函数释放ptr指向的旧对象,并
返回指向具有size指定大小的新对象的指针。
最好不要使用调用malloc的同一指针变量,因为如果失败,也会丢失对旧指针变量的引用(除非它是通过其他方式存储的)。
另外,您没有检查malloc的返回值。
s = malloc(sizeof(students));
if( s == NULL ){
   frpntf(stderr,"%s","Memory allocation failed");
   exit(1);
}

您还应该检查fgets()的返回值。
if( fgets(s[scount].name, sizeof(s[scount].name), stdin) == NULL){
     fprintf(stderr,"%s","Error in input");
     exit(1);
}

也试图编译你的代码它显示了
warning: ignoring return value of ‘realloc’, declared with attribute warn_unused_result [-Wunused-result]
         realloc(s, sizeof(students) * scount);
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

编译时,请不要忽略任何警告消息。它表明了你的问题。
要点:(为什么在scount+1realloc?)
当重新分配时,总的想法是增加学生人数。为此,你需要为学生分配额外的内存。这就是代码中scount+1的原因。
其他要点:
while (s[scount].name[index] != '\n')
{
    index++;
}
s[scount].name[index] = '\0';

你也可以这样做
size_t len = strlen(s[scount].name);
if(len){
   s[scount].name[len-1]='\0';
}

理解标准7.21.7.2中的原因
char *fgets(char * restrict s, int n,FILE * restrict stream)

realloc函数最多读取一个小于
fgets指定的字符从由n指向的流
stream指向的数组。在
新行字符(保留)或文件结束后。空的
字符在最后一个字符读入后立即写入
阵列。
s字符已经存在于输入的\0中。您可以得到它的长度,但是您知道string之前的那个字符是通过按Enter键输入的\0字符1。我们正在用\n覆盖它。
一。这是常见的情况,但不是唯一的。有两种情况下,这可能不是正确的看待事物的方式。
输入行在\0之前有n-1或更多字符。'\n'之前的不是\0而是用户输入的字符。
最后一行是可能没有\n的流。(stdin关闭)。在这种情况下,输入也不包含'\n'
因此,在这些情况下,删除\n的想法将失败。(楚克斯)
一个比用这种方式覆盖更好、更安全的解决方案:
s[scount].name[strcspn(s[scount].name, "\n")] = '\0';

来自link的解释是,如果a\n作为输入,那么我们将基本上写入不需要的\0
根据标准7.24.5.3
size_t strcspn(const char *s1, const char *s2)

s[scount].name[SIZE_MAX]函数计算最大初始值的长度
strcspn指向的字符串段,它完全由
不是由s1指向的字符串中的字符。

关于c - 如何在C中正确分配结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47289845/

10-13 06:40