如何在C中正确地malloc结构

时间:2017-11-14 15:46:17

标签: c pointers struct malloc realloc

这是我的完整代码,看起来很有效,但效果不好。 我会接受任何代码,就像这样。

首先,代码有效,但是当我想在结构中添加第三个名称时,它会崩溃。

还有其他办法吗?

我需要结构,因为在将来,我想添加一些其他参数,如年龄,平均值,性别等。

请帮帮我。

//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。

感谢您的帮助!

4 个答案:

答案 0 :(得分:4)

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

Otehrwise你有内存泄漏。您没有使用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+1 realloc?{/ h3>

重新分配总体思路时,增加学生人数。为此,您需要为学生分配额外的内存。这就是代码中scount+1的原因。(realloc)。

其他一些观点:

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)
  

fgets函数最多读取的数量少于1   由n指向stream的流中s指定的字符   \0指向的数组。 a后没有读取其他字符   换行符(保留)或文件结束后。 空   在读入最后一个字符后立即写入字符   数组。

string字符已存在于输入的\0中。您可以获得它的长度,但是您知道\n之前的那个是您通过按<输入的\0字符 1 kbd>输入键。我们用n-1覆盖它。

1。这是通常的情况,但不是唯一的。有两种情况可能不适合查看该事物。

  • 输入行在'\n'之前有\0个或更多字符。 \n之前的那个不是'\n',而是用户输入的某个字符。

  • 最后一行是一个可能没有\n的流。 (stdin关闭)。在这种情况下,输入也不包含\n

因此,在这些情况下,删除s[scount].name[strcspn(s[scount].name, "\n")] = '\0'; 的想法会失败。在评论中讨论。 (chux)

比以这种方式覆盖更好更安全的解决方案:

\0

link 的解释是,如果给出s[scount].name[SIZE_MAX]作为输入,那么我们基本上会写入size_t strcspn(const char *s1, const char *s2) ,这是不合需要的。

来自标准§7.24.5.3

strcspn
  

s1函数计算最大初始值的长度   s2指向的字符串段,完全由。{1}组成   字符不是来自}指向的字符串

答案 1 :(得分:4)

  

如何在C中正确地malloc结构?

p = malloc(sizeof *p);
if (p == NULL) Handle_OutOfMemory();
  

如何在C中正确地重新分配结构?

void *t = realloc(p, sizeof *p * number_of_elements);
if (t == NULL && number_of_elements > 0) {
  Handle_OutOfMemory();
} else {
  p = t;
}

p指向某些struct。请注意上面的没有该类型的编码

OP'主要问题是没有使用realloc()的返回值并且分配1-too-small

// realloc(s, sizeof(students) * scount);
s = realloc(s, sizeof *s * (scount+1));  // or use above code with check for out-of-memory.

答案 2 :(得分:2)

realloc返回一个你需要保留的新指针:

  students* snew = realloc(s, sizeof(students) * (scount + 1));
  if (!snew) {
     free(s); // If there is not enough memory, the old memory block is not freed
     // handle out of memory
  } else { 
     s = snew;
  }

答案 3 :(得分:1)

你没有回来分配它!看看<custom-ion-item>的工作原理。在进行重新分配之后,需要将指针分配回来。

realloc

根据定义,realloc返回一个void指针,但你没有收集它。

if (scount == 0)
{
    s = (students*)malloc(sizeof(students));
}
else
{
    students *temp = realloc(s, sizeof(students) * (scount+1));
    if(temp == NULL){
        free(s);
    }
    else{
        s = temp;
    }
}
如果空间不足,

realloc会返回void *realloc(void *ptr, size_t size); 。因此,当您确定它不是NULL

时,您可以重新分配它

只需在上面做一个小改动,你的代码就像一个魅力!

干杯!