我必须在 C 中创建一个带有指向数组的结构数组

Posted

技术标签:

【中文标题】我必须在 C 中创建一个带有指向数组的结构数组【英文标题】:i have to create an array of structs with a pointed array in C 【发布时间】:2021-07-28 00:39:19 【问题描述】:

为此,我从标准输入给定的维度创建了一个指向数组,我为数组中的每个结构分配了内存。 这有什么意义吗?我该如何解决这个问题? 编辑因为 riga[x] 是一个 int,我如何将结构与数组连接起来?编辑 2 我需要创建一个结构数组,并且该数组的维度在标准输入中给出。对不起,如果我不善言辞,我对此很陌生

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

typedef struct 
    char c;
    int ni;
    double nr;
dati;

int main () 

    int a,b,K;
    int *riga;

    printf("a b K\n");
    scanf ("%d %d %d",&a,&b,&K);
    printf("%d %d %d\n", a, b, K);

    riga= (int*) malloc(sizeof(int)*K);
    printf("insert %d valors",K);
    for (int k=0;k<K;k++)
            scanf("%d", &riga[k]);
    for(int p=0;p <K;p++)
            printf("%d\n", riga[p]);

    for (int x=0; x>K;x++)
            riga[x]=malloc(sizeof(dati));



    for (int i=0; i<K; i++)
            printf("insert data in line %d", i+1);
            scanf("%c %d %lf", riga[i].c, riga[i].ni, riga[i].nr);
    

    for (int j=0; j<K;j++)
            printf("%c %d %lf\n", riga[j].c,riga[j].ni,riga[j].nr);

    exit(EXIT_SUCCESS);
    

它在第 28 行给了我一个警告“警告:从‘void *’赋值给‘int’使得没有强制转换的指针变成整数 [-Wint-conversion] " 以及打印结构的错误“错误:在不是结构或联合的东西中请求成员‘c’”

【问题讨论】:

riga[x]=malloc(sizeof(dati)); - riga[x]int 并且您正在使用指针分配它 循环条件for (int x=0; x&gt;K;x++)也没有意义。 你有一个k 和一个K 变量吗?请不要。这就是你疏远你的同事的方式。这不值得混淆。 问题不够清楚。你的意图是什么?如果要创建数组,可以执行以下操作:dati *myArray; myArray = malloc(sizeof (*myArray) * K) 【参考方案1】:

您已经定义了int *riga。因此,您的前两个 for 循环将存储数据。也就是说,riga 是一个指向 int 的一维数组的指针。

所以,你的前两个 for 循环没问题。


但是,在您的第三个 for 循环中,您会这样做:

 riga[x] = malloc(sizeof(dati));

你_dereference riga,所以这是一个int,但你正在分配一个指针


riga [再次] 是指向 int 数组的指针,而 不是 指向 struct 数组的指针,因此您可以这样做(例如):

riga[i].c

不清楚你有什么数据或者你想如何存储它。有两种解释:

    您似乎想输入 两个 单独的数组。首先,一个简单的一维数组int,长度为K,你称之为riga。并且,您的 dati 结构的单独数组,长度也为 K 您只需要 一个 结构数组 dati,长度为 K

我已经重构了代码 [有一些猜测] 你需要什么。

我选择解释 (1) 是因为它最接近您的代码。当 riga 引用您的 dati 结构时,我将其重命名为 datarray

如果你想要(2),只需删除下面的riga 相关代码。

我使用cpp 条件来表示旧代码和新代码:

#if 0
// old code
#else
// new code
#endif

这里是调整后的代码[带有一些注释]:

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

typedef struct 
    char c;
    int ni;
    double nr;
 dati;

int
main(void)

    int a, b, K;

    printf("a b K\n");
    scanf("%d %d %d", &a, &b, &K);

    printf("%d %d %d\n", a, b, K);

    // this is interpretation (1) -- you want two separate arrays
#ifndef ONLY_ONE_ARRAY
#if 0
    int *riga = (int *) malloc(sizeof(int) * K);
#else
    int *riga = malloc(sizeof(*riga) * K);
#endif

    printf("insert %d valors", K);
    for (int i = 0; i < K; i++)
        scanf("%d", &riga[i]);

    for (int i = 0; i < K; i++)
        printf("%d\n", riga[i]);
#endif

// NOTE/BUG: riga is an int pointer so this is invalid
#if 0
    for (int x = 0; x > K; x++)
        riga[x] = malloc(sizeof(dati));
#else
    dati *datarray = malloc(sizeof(*datarray) * K);
#endif

    for (int i = 0; i < K; i++) 
        printf("insert data in line %d", i + 1);
#if 0
        scanf("%c %d %lf", riga[i].c, riga[i].ni, riga[i].nr);
#else
        scanf("%c %d %lf", datarray[i].c, datarray[i].ni, datarray[i].nr);
#endif
    

#if 0
    for (int i = 0; i < K; i++)
        printf("%c %d %lf\n", riga[j].c, riga[j].ni, riga[j].nr);
#else
    for (int i = 0; i < K; i++)
        printf("%c %d %lf\n", datarray[i].c, datarray[i].ni, datarray[i].nr);
#endif

    return EXIT_SUCCESS;

【讨论】:

我想做第 (2) 【参考方案2】:

您的变量riga 需要是一个dati 数组。您还需要检查对 scanf 的调用是否成功。要跳过前导空格,您需要在格式字符串中的 %c 之前添加一个空格。为了使内存分配更容易,我总是为此使用宏函数。这是一个解决方案:

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

#define NEW_ARRAY(pointer, length) \
     \
        (pointer) = malloc(((size_t) length) * sizeof (pointer)[0]); \
        if ((pointer) == NULL)  \
            fprintf(stderr, "Allocating memory failed: %s\n", strerror(errno)); \
            exit(EXIT_FAILURE); \
         \
    

typedef struct 
    char c;
    int ni;
    double nr;
 dati;

int main(void)

    dati *riga;
    int K, n;

    printf("Number of lines: ");
    n = scanf("%d", &K);
    if ((n == 1) && (K > 0)) 
        NEW_ARRAY(riga, K);
        for (int i = 0; i < K; i++) 
            printf("insert data in line %d: ", i + 1);
            n = scanf(" %c %d %lf", &riga[i].c, &riga[i].ni, &riga[i].nr);
            if (n != 3) 
                fprintf(stderr, "Character, integer and real number expected at line %d\n", i + 1);
                exit(EXIT_FAILURE);
            
        
        for (int i = 0; i < K; i++) 
            printf("%c %d %lf\n", riga[i].c, riga[i].ni, riga[i].nr);
        
        free(riga);
     else 
        fprintf(stderr, "Non-negative integer expected\n");
        exit(EXIT_FAILURE);
    
    return 0;

【讨论】:

使用像 NEW_ARRAY 这样的宏通常是一种反模式。我建议添加一个新函数,例如 'malloc_or_die()' @tstanisl 为什么它是反模式?我已经成功使用了几年。宏的好处是你不需要摆弄 sizeof;你只需要说出你想要多少元素。使用普通函数,如您建议的 malloc_or_die,您需要以字节为单位传递大小。 这里有几个问题:1)它看起来像一个函数,但它修改了riga参数,因此它应该将&amp;riga作为参数2)它评估riga两次,在指针 VLA 的情况下,即使使用大写字母 3 次也有助于警告它是一个宏 3) 需要 do ... while (0) 技巧来修复 if (...) NEW_ARRAY(...); else ... 中的吃 else 4) 在初始化或内部表达式期间使用它很麻烦,因为必须使用两行:int *x; NEW_ARRAY(x, size); 而对于其他选项,它将是 int *x = malloc_or_die(size, sizeof *x); @tstanisl 该宏定义了一个块,因此您的示例中的 if-else 语句现在应该有问题。如果您避免使用具有副作用的表达式的反模式并尽可能晚地初始化变量(以最小化变量的生存时间),那么其他问题就不会出现。 如果我使用你的代码它工作正常,但如果我想把 NEW_ARRAY 的部分放在主里面它不起作用我用了 "riga=malloc(sizeof(riga)[0]* ((size_t)K));"如果 K=4,我在第 1 行插入数据,然后转到第 3 行,在那里我放置其他数据,然后在第 2 行返回第 1 行的数据,在第 4 行返回第 3 行的数据

以上是关于我必须在 C 中创建一个带有指向数组的结构数组的主要内容,如果未能解决你的问题,请参考以下文章

在层次结构中创建类的指针数组

C 语言结构体 ( 结构体 数组 作为函数参数 | 数组 在 堆内存创建 )

从巨大的二维结构数组中创建结构的子数组

试图在 C++ 中创建一个包含结构的数组?

C基础结构体

从嵌套结构(带有其他结构的数组)创建字典 Swift