【问题标题】:Malloc and Realloc doesn't work (C11 - CLion)Malloc 和 Realloc 不起作用 (C11 - CLion)
【发布时间】:2018-10-17 00:19:26
【问题描述】:
#include <stdio.h>
#include <stdlib.h>

typedef struct Ogrenciler {
    int no;
    char adi[50];
    char soyadi[50];
    double vize;
    double final;
    double notu;
} Ogr;

int ogrenciSayisi = 0;

void KayitEkle(Ogr *ogrenci) {
    int simdikiOgr = ogrenciSayisi;
    if (ogrenciSayisi == 0) {
        ogrenciSayisi++;
        ogrenci = (Ogr *) malloc(ogrenciSayisi*sizeof(Ogr));
    } else {
        ogrenciSayisi++;
        ogrenci = (Ogr *) realloc(ogrenci, ogrenciSayisi * sizeof(Ogr));
    }
    printf("No:");
    scanf("%d", &ogrenci[simdikiOgr].no);
    printf("Adi:");
    scanf("%s", ogrenci[simdikiOgr].adi);
    printf("Soyadi:");
    scanf("%s", ogrenci[simdikiOgr].soyadi);
    printf("Vize:");
    scanf("%lf", &ogrenci[simdikiOgr].vize);
    printf("Final:");
    scanf("%lf", &ogrenci[simdikiOgr].final);
    ogrenci[simdikiOgr].notu = (ogrenci[simdikiOgr].vize * 0.4) + (ogrenci[simdikiOgr].final * 0.6);
    printf("Notu: %lf", ogrenci[simdikiOgr].notu);
    printf("\n\n");
    printf("Adi: %s\nNo: %d\nVize: %lf\nFinal: %lfNotu: %lf\n",
           ogrenci[simdikiOgr].adi, ogrenci[simdikiOgr].no, ogrenci[simdikiOgr].vize, ogrenci[simdikiOgr].final,
           ogrenci[simdikiOgr].notu);
}

int main() {
    int c;
    while (c != 5) {
        printf("\n1-\tYeni Kayit Ekle\n2-\tKayit Sil\n3-\tKayitlari Listele\n4-\tOrtalama Hesapla\n5-\tCikis\n");
        scanf(" %d", &c);
        Ogr *ogrenci;
        switch (c) {
            case 1:
                KayitEkle(ogrenci);
                break;
            case 2:
                KayitSil(ogrenci);
                break;
            case 3:
                KayitListele(ogrenci);
                break;
            case 4:
                OrtHesapla(ogrenci);
                break;
            case 5:
                printf("Cikiliyor");
                break;
            default:
                printf("Gecerli bir girdi yapiniz\n");
                break;
        }
    }

    return 0;
}

如您所见,我将 malloc() 和 realloc() 用于我的 typedef 结构,并且我只能输入一个条目。当我尝试添加一个新条目(切换案例:1)时,它不起作用并在本节之后崩溃:

printf("No:");
scanf("%d", &ogrenci[simdikiOgr].no);

起初,我尝试使用 calloc(ogrenciSayisi*10*sizeof(Ogr)) 但它只创建了一个空格。之后,在调试器(CLion)的 realloc 部分之后,ogrenci 指针变为空指针。

编辑: 我不是想返回一个值。据我所知 (int a) 等于 (int a[ ]) 所以 KayitEkle(ogrenci) 和 void KayitEkle (Ogr ogrenci) 对我来说似乎是合法的。而且我的 ogrenci 首先应该是空的,所以 (Ogr *ogrenci=NULL) 正如你所说的那样正确吗?

编辑2: 在 malloc 第 10 节中是一个错误。我修好了它。我正在尝试一些东西,但我忘了删除它。

【问题讨论】:

  • 与您的问题无关,但您使用c 没有初始化。这意味着它的值是 indeterminate 并且看起来几乎是随机的。不要那样做。
  • 至于你的问题,函数的参数是按值传递的。这意味着它们被复制,并且修改副本不会更改原始文件。做一些关于在 C 中模拟通过引用传递 的研究。哦,别忘了也初始化变量ogrenci
  • @Someprogrammerdude 说的是,当您重新分配时,您的 ogrenci 变量仅在本地更改。 main 有自己的副本,该副本未更改。这就是你有问题的原因。您需要了解变量和指针是如何工作的,否则您将多次遇到此问题。阅读stackoverflow.com/questions/5286453/…
  • 另外值得注意的是,您的realloc 实际上将重新分配到一个较小的 位置,这似乎不是您打算做的。出于某种原因,您在malloc 中有一个 10 倍的乘数。此外,您应该始终检查来自 mallocrealloc 的返回值,以确认它们确实已将内存返回给您。

标签: c struct malloc realloc dynamic-allocation


【解决方案1】:

您将ogrenci 指针按值传递给KayitEkle(),您在其中修改它的值,但不将其修改后的值返回给main()。您需要使用指针传递ogrenci 值(即KayitEkle(&amp;ogrenci))或将新值返回给被调用者(即ogrenci = KayitEkle(ogrenci))。下面的例子是后者。 ogrenci 指针在 while 循环内,因此每次循环运行时都会重新初始化,可能您打算将它放在循环之外,以便保留它的值。 局部变量在没有初始化的情况下具有 undefined(读取:any)值,因此如果需要,您需要将 ogrenci 显式初始化为 NULL。见Initialization。 当ogrenci == NULL 时,您不需要检查ogrenciSayisi == 0,因为realloc(NULL, ...) 等于malloc(...)。见realloc

#include <stdio.h>
#include <stdlib.h>

typedef struct Ogrenciler {
    int no;
    char adi[50];
    char soyadi[50];
    double vize;
    double final;
    double notu;
} Ogr;

int ogrenciSayisi = 0;

// or void KayitEkle(Ogr **ogrenci) and then use *ogrenci
Ogr *KayitEkle(Ogr *ogrenci) {
    int simdikiOgr = ogrenciSayisi;

    ogrenciSayisi++;
    ogrenci = realloc(ogrenci, ogrenciSayisi*sizeof(Ogr));

    printf("No:");
    scanf("%d", &ogrenci[simdikiOgr].no);
    printf("Adi:");
    scanf("%s", ogrenci[simdikiOgr].adi);
    printf("Soyadi:");
    scanf("%s", ogrenci[simdikiOgr].soyadi);
    printf("Vize:");
    scanf("%lf", &ogrenci[simdikiOgr].vize);
    printf("Final:");
    scanf("%lf", &ogrenci[simdikiOgr].final);
    ogrenci[simdikiOgr].notu = (ogrenci[simdikiOgr].vize * 0.4) + (ogrenci[simdikiOgr].final * 0.6);
    printf("Notu: %lf", ogrenci[simdikiOgr].notu);
    printf("\n\n");
    printf("Adi: %s\nNo: %d\nVize: %lf\nFinal: %lfNotu: %lf\n",
           ogrenci[simdikiOgr].adi, ogrenci[simdikiOgr].no, ogrenci[simdikiOgr].vize, ogrenci[simdikiOgr].final,
           ogrenci[simdikiOgr].notu);
    return ogrenci;
}

int main() {
    int c = 0;
    Ogr *ogrenci = NULL;
    while (c != 5) {
        printf("\n1-\tYeni Kayit Ekle\n2-\tKayit Sil\n3-\tKayitlari Listele\n4-\tOrtalama Hesapla\n5-\tCikis\n");
        scanf(" %d", &c);
        switch (c) {
            case 1:
                ogrenci = KayitEkle(ogrenci);
                break;
            case 2:
                ogrenci = KayitSil(ogrenci);
                break;
            case 3:
                ogrenci = KayitListele(ogrenci);
                break;
            case 4:
                ogrenci = OrtHesapla(ogrenci);
                break;
            case 5:
                printf("Cikiliyor");
                break;
            default:
                printf("Gecerli bir girdi yapiniz\n");
                break;
        }
    }

    // it's nice to free things
    free(ogrenci);

    return 0;
}

【讨论】:

    【解决方案2】:

    有很多错误。如果你想用你的函数动态分配内存。必须使用指针的指针,例如realloc 行上的指令也不正确,因为如果您的重新分配失败,您将覆盖旧的内存地址,并且指针采用与 NULL 相同的值。

    而且没有脱离主题。如果您输入的内容不是格式所期望的(例如字符而不是数字,反之亦然),您还应该对 scanf 函数采取预防措施,可以确定程序的行为是不确定的,所以您应该预测这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-29
      • 2021-01-15
      • 1970-01-01
      • 2017-02-22
      • 2018-07-06
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      相关资源
      最近更新 更多