realloc之后我无法读取字符串

时间:2018-01-09 08:21:09

标签: c string struct realloc

我有这个功能,我重新定位内存,但是当我想读取字符串时,它没有工作=>错误 学生是一个结构

void insertStudent(Student **myStudents, int *size)
{
    int newSize = *size + 1;
    *myStudents = (Student*)realloc(myStudents, newSize*sizeof(Student));
    printf("Enter your grade: ");
    scanf("%f", &(*myStudents)[*size - 1].nota);

    printf("Enter your first name: ");
    scanf("%s", &(*myStudents)[newSize-1].firstName);


    printf("Enter your second name: ");
    scanf("%s", &(*myStudents)[*size - 1].lastName);
    //Generate a new code
    /*int code = rand() % 1+1000;
    int ok = 0;
    while (ok == 0)
    {
        ok = 1;
        for (int i = 0; i < *size; i++)
            if ((*myStudents)[i].cod == code)
            {
                code = rand() % 1 + 1000;
                ok = 0;
            }
    }*/
    (*myStudents)[*size-1].cod = 7;
    printf("Your code is: %d. Do not forget it! ", 7);
}

3 个答案:

答案 0 :(得分:4)

void insertStudent(Student **myStudents, int *size)
{
    *myStudents = (Student*)realloc(myStudents, newSize*sizeof(Student));
                               //   ^ <- look here

这是指向学生的指针的指针。 realloc()期望指向最初分配的数据的指针,所以你肯定必须在这里传递*myStudents

还要更改代码以使用临时变量。 realloc()可能会因错误而返回NULL,在这种情况下,原始内存仍然已分配,您必须free()

为了计算大小,最好使用sizeofnewSize * sizeof **myStudents)的表达式语法,因为这可以防止以后更改类型时出错。

对于尺码,您应该始终使用size_t,因为这可以保证保持任何可能的尺寸(int不是......)

进一步的注意事项:转换为void *和从void insertStudent(Student **myStudents, size_t *size) { size_t newSize = *size + 1; Student *newStudents = realloc(*myStudents, newSize * sizeof *newStudents); if (!newStudents) { free(*myStudents); *myStudents = 0; return; // check for this error in calling code } *myStudents = newStudents; *size = newSize; // [...] } 转换为C中的隐式,并且它arguably better style不会明确地编写此转换。

总而言之,代码应该像这样编写

{{1}}

答案 1 :(得分:1)

您正在重新分配到myStudents。这不是你的意图,也是不可能的。

来自standard 7.22.3.5

  

void *realloc(void *ptr, size_t size);

     

否则,如果ptr与之前返回的指针不匹配   内存管理功能,或者如果空间已被释放   调用free或realloc函数,行为未定义。如果   无法分配新对象的内存,旧对象则不能   取消分配,其价值不变。

之前您有未定义的行为,您没有传递最初分配的内存地址。而是你传递了一个局部变量。您有未定义的行为

Student* t = realloc(*myStudents, newSize*sizeof(Student))
if(t){
  *myStudents = t;
  (*size)++;
}
else {
   perror("realloc failed");
   free(*myStudents);
   exit(EXIT_FAILURE);
}

此外,当您增加内存时,如果呼叫成功,您应该增加内存。然后在整个代码中始终访问*size-1,它更容易处理和完成。

上面显示的正确方法。如果realloc返回NULL,您将不会丢失对已分配内存的引用。另外,建议检查realloc的返回值。在这种情况下,投射是多余的 - 不要这样做。

scanf中你可以简单地写

scanf("%s",(*myStudents)[newSize-1].firstName);

否则你传递char (*)[]它预期char*

答案 2 :(得分:1)

realloc()需要指向要重新分配的内存的指针,*myStudents而非myStudents

更改

 *myStudents = (Student*)realloc(myStudents, newSize*sizeof(Student));

 *myStudents = (Student*)realloc(*myStudents, newSize*sizeof(Student));