更新嵌套C结构数组的正确方法是什么?

时间:2016-10-21 19:08:15

标签: c arrays struct parameter-passing pass-by-reference

我无法找到正确的方法来改变C99中嵌套结构数组的成员(在将数组传递给另一个函数之后)。数组在main()中声明 - 所以它在堆栈上,我猜? - 而且,我也可以只显示代码的相关部分。

typedef struct
{
    uint32_t x, y;
} point;

typedef struct
{
    uint32_t r, g, b, a;
} rgba;

typedef struct
{
    point a, b, c;
    rgba p;
} tri;

这些是结构;这是我如何创建一个随机三角形(我在程序的其他部分需要的能力):

tri triangle()
{
    tri t;

    t.a.x = rand() % xres;
    t.a.y = rand() % yres;
    t.b.x = rand() % xres;
    t.b.y = rand() % yres;
    t.c.x = rand() % xres;
    t.c.y = rand() % yres;
    t.p.r = rand() % 256;
    t.p.g = rand() % 256;
    t.p.b = rand() % 256;
    t.p.a = rand() % 256;

    return t;
}

这是我声明并填充数组的部分(你可以忽略的一些部分):

int main(int argc, char *argv[])
{
    init(argc, argv[1]);

    uint32_t img[xres][yres];

    copyInputImage(img);

    srand(time(NULL));

    tri trigons[NUM_TRIGONS];

    for (int i = 0; i < NUM_TRIGONS; i++)
    {
        trigons[i] = triangle();
    }

所有这一切都成功地为我提供了一组随机三角形。

现在这是我的问题:根据程序参数,有时我想立即用文本文件中的数据重新填充数组。文本格式很简单:每行都有一个unsigned char。以下是该文件中单个像素数据的示例:

0
40
0
5
37
31
134
64
167
100

这是三角形结构最终需要的10个基元的一个例子。所有数字字符串都是3位数或更少,但我的 fgets()循环涉及一个5字符缓冲区,以允许行终止符和空终止符。

这样做的功能如下:

void read_SVG(char* filename, tri* ts)
{
    FILE* fp = fopen(filename, "r");

    char str[5];

    for (int i = 0; i < NUM_TRIGONS; i++)
    {
        tri *t   = &(ts[i]);
        point *a = &(ts[i]).a;
        point *b = &(ts[i]).b;
        point *c = &(ts[i]).c;
        rgba  *p = &(ts[i]).p;

        while (fgets(str, 5, fp) != NULL)
        {
            a->x = (uint32_t) strtol(str, NULL, 10);
            a->y = (uint32_t) strtol(str, NULL, 10);
            b->x = (uint32_t) strtol(str, NULL, 10);
            b->y = (uint32_t) strtol(str, NULL, 10);
            c->x = (uint32_t) strtol(str, NULL, 10);
            c->y = (uint32_t) strtol(str, NULL, 10);
            p->r = (uint32_t) strtol(str, NULL, 10);
            p->g = (uint32_t) strtol(str, NULL, 10);
            p->b = (uint32_t) strtol(str, NULL, 10);
            p->a = (uint32_t) strtol(str, NULL, 10);
        }
        t->a = *a;
        t->b = *b;
        t->c = *c;
        t->p = *p;
    }
    fclose(fp);
}

最后,这是我调用 read_SVG()的方式,在 main()的上下文中显示。

if (argc > 2)
{
    read_SVG(argv[2], trigons);

    draw(screen, trigons);
    SDL_Flip(screen);
    SDL_SaveBMP(screen, "wtf.bmp");
    exit(0);
}

当我从 read_SVG()中输出数组时,它看起来像我期望的数据。但是当我在 main()中检查它时,它看起来像我最初填充的随机值。

所以看起来初始数组从未更新过。我做错了什么,谁能建议一个更好的方法来处理这种类型的嵌套结构传递和更新问题?

我确信有很多问题要问这个问题;我只能希望我的全面足以帮助其他一些C新手。在来这里寻求帮助之前,我尝试了各种各样的方法......

1 个答案:

答案 0 :(得分:2)

这部分是多余的,因为a,b,c和p已经指向t指向的相同内存:

    t->a = *a;
    t->b = *b;
    t->c = *c;
    t->p = *p;

但那只是一个挑剔。 ;)重要的注释可能是fgets()将读取第一个项目的所有文件内容,并且不读取其余项目的任何内容。也许s / while / if /?

编辑以澄清:这是read_SVG()函数的替代版本:

void read_SVG(char* filename, tri* ts)
{
    FILE* fp = fopen(filename, "r");
    char str[5];
    int i = 0;

    while (i < NUM_TRIGONS && fgets(str, 5, fp) != NULL) {
        uint32_t val = (uint32_t) strtol(str, NULL, 10);
        ts[i].a.x = ts[i].a.y = 
        ts[i].b.x = ts[i].b.y = 
        ts[i].c.x = ts[i].c.y = 
        ts[i].p.r = ts[i].p.g = ts[i].p.b = ts[i].p.a = val;

        i++;
    }
    fclose(fp);
}