У меня возникли проблемы с поиском правильного способа мутации элементов массива вложенных структур в C99 (после передачи массива другой функции). Массив объявляется внутри main() - так ли это в стеке, я полагаю? - и я могу просто показать соответствующие части кода.Каков правильный способ обновления массива вложенных структур C?
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();
}
Все, что успешно доставит мне массив случайных треугольников.
Теперь вот моя проблема: в зависимости от параметров программы, иногда я хочу немедленно повторно заполнить массив данными из текстового файла. Формат текста прост: один символ без знака в каждой строке. Вот пример того, что данные для одного пикселя выглядит в этом файле:
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(), показанный в его контексте в основной().
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. Я попытался широкий спектр подходов, прежде чем прийти сюда за помощью ...
Одна из неправильных вещей в этом коде возвращается в локальную структуру от 'треугольника()'. Локальные вары создаются в стеке, и после возврата из функции его стоп-фрейм отбрасывается. Лучше передать указатель на структуру в качестве параметра. – hidefromkgb
Он возвращает структуру, которая будет выполнена через копию в вызывающем коде. он неэффективен, но фактически ничем не отличается от возврата локального int. – kdopen
Право; У меня есть -Wall, и я обычно получаю ошибку, когда возвращаю то, что будет потеряно после того, как кадр стека будет отброшен. Код, который я опубликовал в этом вопросе, не вызывает никаких предупреждений даже с -Wextra. – sacheie