C - указание членов массива структуры в другой массив (никакие дублирующие данные структуры просто не указывают на него) - PullRequest
0 голосов
/ 27 июня 2019

У меня есть два идентичных массива struct, один в обратном порядке.Проблема в том, что я не хочу дублировать одни и те же данные в два массива, я бы перевернул массив с элементами, указывающими на элементы первого массива, таким образом, чтобы я мог редактировать элементы структуры первого массива или из обращенного массива.вступая в силу в обоих.

вы можете просмотреть источник и запустить его онлайн здесь https://onlinegdb.com/SJbepdWxS

#include <stdio.h>

typedef struct point{
    int id;
    float x,y,z;
} point;

void printPoints(point *pts,int len){
    int i = 0;
    while (pts !=NULL && i < len){
        printf("id %d x %f y%f z %f\n",pts->id,pts->x,pts->y,pts->z);
        pts++;
        i++;
    }
}
void translatePoints(point *pts,int len,float t){
    int i = 0;
    while (pts !=NULL && i < len){

        pts->x = pts->x + t;
        pts->y = pts->y + t;
        pts->z = pts->z + t;

        pts++;
        i++;
    }
}

void reversePoints(point *pts, int len, point *rev){
    int i = 0;
    int j = len;
    while (i < len){
        j=len-i-1;
        rev[j]=pts[i];
        i++;
    }
}

int main()
{

    int i;

    int t1=200;
    int t2=300;

    int len=3;
    point points[len];
    point rev_points[len];


    for(i=0; i<len ; i++){
        points[i].id=i;
        points[i].x=10+i;
        points[i].y=20+i;
        points[i].z=30+i;
    }


    //point * pts = points;
    printf("\nprint points \n\n");
    printPoints(points,len);
    printf("\ntranslate points %d...\n\n",t1);
    translatePoints(points,len,t1);
    printf("\nprint points\n\n");

    printf("\nreverse points to rev_points\n");
    reversePoints(points,len,rev_points);

    printf("\nprint rev_points \n\n");
    printPoints(rev_points,len);

    printf("\ntranslate rev_points %d...\n\n",t2);
    translatePoints(rev_points,len,t2);

    printf("\nprint rev_points\n\n");
    printPoints(rev_points,len);

    printf("\nprint points\n\n");
    printPoints(points,len);

    return 0;

}

Я ожидаю, что значения структур обоих массивов изменятся, когда я изменю значение в одном из двух массивов.

Но изменяя значения struct в первом массиве, второй массив не изменяется и наоборот.

Ответы [ 2 ]

0 голосов
/ 27 июня 2019

Один из способов посмотреть на это - набор точек и две перестановки на множестве. Это устанавливает массив points, который используется как набор, и forward_points и reverse_points как массивы указателей на массив point, который мы будем использовать в качестве перестановок.

#include <stdio.h>

struct Point {
    int id;
    float x,y,z;
};

/* Print a point. */
static void printPoint(struct Point *point) {
    printf("id %d x %f y%f z %f\n",point->id,point->x,point->y,point->z);
}

/* These print out an array of pointers to point. */
static void printPointsRef(struct Point **ref, int len) {
    struct Point **end = ref + len;
    while(ref < end) printPoint(*(ref++));
}

/* This translates all the `pts` up to `len` by `(1,1,1)*t`. */
static void translatePoints(struct Point *pts, int len, float t) {
    struct Point *end = pts + len;
    while(pts < end) {

        pts->x = pts->x + t;
        pts->y = pts->y + t;
        pts->z = pts->z + t;

        pts++;
    }
}

/* Helper function to `main`. */
static void printPoints(struct Point **forward_points,
    struct Point **reverse_points, int len) {
    printf("print points\nprint points forward:\n");
    printPointsRef(forward_points,len);
    printf("print points reverse:\n");
    printPointsRef(reverse_points,len);
    printf("\n");
}

int main(void)
{
    const int len = 3;

    /* This is the actual points structure. */
    struct Point points[len];

    /* These are arrays of pointers to points; they are
     permutations of `points`. */
    struct Point *forward_points[len], *reverse_points[len];

    int i;

    const int t1=200;

    for(i=0; i<len; i++) {

        /* Initialise element `i` of `points`. */
        points[i].id=i;
        points[i].x=10+i;
        points[i].y=20+i;
        points[i].z=30+i;

        /* Initialise element `i` of `forward_points`
         to point to `points[i]`, and `backward_points`
         to point the other way (it doesn't matter that
         the backwards points are uninitialised, they
         will be.) */
        forward_points[i] = &points[i];
        reverse_points[i] = &points[len - 1 - i];
    }

    printPoints(forward_points, reverse_points, len);

    /* Translation is a vector space operation and doesn't
     care about order; we just do it on the original points. */
    printf("translate points %d...\n\n",t1);
    translatePoints(points,len,t1);

    printPoints(forward_points, reverse_points, len);

    return 0;

}

Schematic of the code.

Конечно, нет никаких ограничений целостности указателей; ничто не мешает указывать на что-либо, ноль, те же элементы или что-либо еще.

0 голосов
/ 27 июня 2019

Я добавил другую структуру с одним элементом, который является указателем

typedef struct ptr_point{
    point * p;
} ptr_point;

Я отредактировал функцию reversePoints

void reversePoints(point *pts, int len, ptr_point *rev){

    // This function is used only to test pointers 

    int i = 0;
    int j = len;

    while (i < len){
        j=len-i-1;
        rev[j].p = &pts[i];
        i++;
    }
}

и добавил еще одну функцию для печати ptr_points

void printPtrPoints(ptr_point *pts,int len){
    int i = 0;
    while (i < len){
        printf("id %d x %f y%f z %f\n",pts->p->id,pts->p->x,pts->p->y,pts->p->z);
        pts++;
        i++;
    }
}

и объявление второго массива как массива ptr_point

ptr_point rev_points[len];

В заключение: теперь данные во втором массиве не реплицируются, а указывают на элементную структуру первого массива.

Необходимость не реплицировать данные возникает в присутствии миллионов координатных точек, которые, если реплицируются более одного раза, сортируя их, например, по x, y, z и т. Д., Занимают много памяти с трудностями управления,

Однако это исправление заставляет меня использовать структура-> тип, чтобы изменить режим доступа для чтения или установки значений.

Я не знаю, является ли это лучшим решением, но оно решило проблему, не дублируя данные.

Вы можете запустить исходный код с исправлениями здесь: https://onlinegdb.com/SknP_i-eS

Спасибо всем за совет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...