• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Język c- struktury, alokacja pamięci, wskaźniki, jak wypisać te współrzędne?

VPS Starter Arubacloud
0 głosów
1,274 wizyt
pytanie zadane 1 czerwca 2018 w C i C++ przez julita998 Początkujący (250 p.)

Otrzymałam zadanie, którego polega na posortowaniu funkcją qsort struktury, która składa się z współrzędnych. U mnie n to ilość punktów. Zrobiłam już dosyć dużo, ale nie wiem jak wypisać te współrzędne. Zrobiłam tablicę (tab) która liczy długość pomiędzy punktami i mam ją posortowaną funkcją qsort. Proszę bardzo o pomoc, będę bardzo wdzięczna :))

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

typedef struct punkt{
int x,y;
} **wsp;

 int porownaj( const void* a, const void* b ) { 
     int* arg1 = (int*) a;
     int* arg2 = (int*) b;
     if( *arg1 < *arg2 ) return -1;
     else if( *arg1 == *arg2 ) return 0;
     else return 1;
   }
int main()
{
    int n,i;

    printf("Ile jest wspolrzednych: ");
    scanf("%d",&n);
    int tab[n];

    struct punkt **wsp=(struct punkt**)malloc(sizeof(struct punkt)*n);

    for(i=0;i<n;i++)
    wsp[i]=(struct punkt*)malloc(sizeof(struct punkt));

    for(i=0;i<n;i++){
         printf("%d wspolrzedna: ",i+1 );
         scanf("%d %d",&wsp[i]->x, &wsp[i]->y);
    }
     for(i=0;i<n;i++){
         printf("%d wspolrzedna: (%d,%d)",i+1, wsp[i]->x, wsp[i]->y );
            printf("\n");
    }

    for(i=0;i<n;i++){
        tab[i]=sqrt(pow(abs(wsp[i]->x),2)+pow(abs(wsp[i]->y),2));
    }


    printf("nieposortowana tablica: \n");
    for(i=0;i<n;i++)
    {
        printf("%d ", tab[i]);
    }
    printf("\n");

     qsort(tab, n, sizeof(int), porownaj );

     printf("posortowana tablica: \n");
       for(i=0;i<n;i++)
    {
        printf("%d ", tab[i]);
    }

    for(i=0;i<n;i++)
        free(wsp[i]);
    free(wsp);

    return 0;
}

 

3 odpowiedzi

+1 głos
odpowiedź 1 czerwca 2018 przez criss Mędrzec (172,590 p.)

Sortujesz odległości od środka układu współrzędnych a nie same punkty.

Kilka uwag:

struct punkt **wsp=(struct punkt**)malloc(sizeof(struct punkt)*n);

Dlaczego sizeof(struct punkt)? Wystarczy ci sizeof wskaźnika - sizeof(struct punkt*). W ogóle jakoś dziwnie to robisz. Alokujesz dynamicznie tablice wskaźników które wskazują na dynamicznie zaalokowane struktury. Nie prościej tak ? :

struct punkt wsp[n];

C na to pozwala.

I dlaczego odległości przedstawiasz za pomocą intów? Przecież to nie koniecznie liczba całkowita. Zauważ też, że nie musisz liczyć pierwiastka - nie potzrebujesz znać dokładnej odległości - wystarczy sama znajomość stosunku jednej do drugiej czego pierwiastek nie zmieni. I wtedy możesz zostawić int, bo masz pewność że suma kwadratów dwóch liczb całkowitych to też liczba całkowita.

Skoro chcesz posortować punkty (współrzędne), to, masz dwie opcje:

  • liczyć odległość za każdym porównaniem
  • policzyć odległość dla każdego punktu przed sortowaniem (tutaj przyda się dodatkowe pole w strukturze)

Druga opcja jest zdecydowanie bardziej optymalna, więc wybiorę tą. Funkcja porownaj mogłaby wyglądać tak:

struct punkt {
   int x, y;
   int distance;
};

int porownaj(const void* a, const void* b)
{
   int da = ((struct punkt*)a)->distance;
   int db = ((struct punkt*)b)->distance;

   if (da < db) return -1;
   if (da == db) return 0;
   return 1;
}

Zakładając, że tablica punktów wygląda tak jak pokazałem wyżej (struct punkt wsp[n];). Tylko pamiętaj, że musisz policzyć wartości dla pola distance przed sortowaniem oczywiście.

+1 głos
odpowiedź 1 czerwca 2018 przez RafalS VIP (122,820 p.)
typedef struct punkt {
	int x, y;
} **wsp;

To co zrobiłaś tutaj to zrobiłaś typedef struct punkt** wsp. Czyli wsp jest aliasem do podwójnego wskaźnika na struct punkt. Jeśli nie miałaś tego na myśli to popraw :P

Po drugie typedefy przy deklaracji struktury wykorzystuje się po to, żeby nie musieć pisać zawsze tego struct, czyli pisać samo punkt zamiast struct punkt. Ty zrobiłaś typedef (akurat nie do końca dobry :P ) a potem używasz pełnej nazwy struct punkt. Chcesz zrobić coś takiego:

typedef struct punkt {
	int x, y;
} punkt;

jest to równoważne z:

struct punkt {
	int x, y;
};
typedef struct punkt punkt;

Ale szybciej jest napisać typedefa odrazu przy deklaracji struktury, wiec wszyscy posługują się skróconą wersją. 

W obydwu przypadkach możesz potem używać samego punkt zamiast struct punkt w kodzie.

	struct punkt **wsp = (struct punkt**)malloc(sizeof(struct punkt)*n);

	for (i = 0; i<n; i++)
		wsp[i] = (struct punkt*)malloc(sizeof(struct punkt));

Tego kawałka wcale nie rozumiem. Wygląda to tak jakbyś chciała zrobić dwuwymiarową tablicę struktur, ale najpierw alokujesz n struktur, czyli normalną tablice struktur, ale przypisujesz ją do podwójnego wskaźnika, nie rozumiem. Później alokujesz pojedycze struktury i przypisujesz je do elementów tablicy. 

Generalnie to stworzyłaś tablicę dwuwymiarową gdzie te bardziej wewnętrzne tablice (wiersze) mają jeden element. A wielkość tablicy zewnętrznej (całości) jest większa niż n, bo zaalokowałaś n* wielkość struktury a nie wskaźnika na strukture. Wielkość struktury to 8 B(lub 16B, ale stawiałbym na 8), a wskaźnika 4B (lub 8B, ale stawiałbym na 4B). Więc masz tablicę dwuwymiarową, która prawdopodobnie jest odpowiednikiem takiej tablicy: struct point tab[n*2][1]. A takie odwołania:

wsp[i]->x

są równoważne z wsp[i][0].x.

Obstawiam, że nie taki był zamiar, jeśli chcesz normalną tablice to zrób tak:

struct punkt tab[n];

;P, a jeśli koniecznie musi być alokowana dynamicznie, co tutaj jest totalnie niepotrzebne to zrób tak:

struct punkt* tab = (struct punkt*) malloc(sizeof(struct punkt) * n);

W ten sposób tworzysz jednowymiarową tablice n struktur na stercie, będąca odpowiednikiem struct punkt tab[n] alokowanej na stosie.

Co do pytania - jeśli dobrze rozumiem to masz problem z wypisaniem wspołrzędnych punktów po sortowaniu. Dlatego, że zrobiłaś sobie ułatwienie wbrew treści zadania :P, które mówi, że masz sortować struktury, a Ty posortowałaś inty. Generalnie na jedno wychodzi, ale wtedy tracisz połączenie między tablicą struktur a intów.

Zrób tak jak mówi zadanie - posortuj tablicę struktur. Ja bym to widział w ten sposób:

int porownaj_struktury(const void* a, const void* b) {
	punkt* arg1 = (punkt*)a;
	punkt* arg2 = (punkt*)b;

	double dlugosc1 = sqrt(pow(arg1->x, 2) + pow(arg1->y, 2));
	double dlugosc2 = sqrt(pow(arg2->x, 2) + pow(arg2->y, 2));

	if (dlugosc1 < dlugosc2) return -1;
	else if (dlugosc1 == dlugosc2) return 0;
	else return 1;
}

Zauważ, że wywaliłem wartości bezwzlędne. Przecież wszystko podniesione do kwadratu jest dodatnie :P.

Zamiast liczyć te odległości za każdym razem można też zrobić pole dlugosc w struturze punkt i tam trzymać długość punktu.

+1 głos
odpowiedź 1 czerwca 2018 przez mokrowski Mędrzec (155,460 p.)

W ramach podpowiedzi bo już jest w tym wątku wiele rad:

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

typedef struct {
    int x;
    int y;
    int pow2_distance;
} point_type;

int compare_points(const void * point1_ptr, const void * point2_ptr);
int calc_pow2_distance(point_type * point_ptr);
void for_each_points(point_type * table, size_t size, int (*calc)(point_type *));
void fill_points_table(point_type * table, size_t size);
void show_points(point_type * table, size_t size);
size_t read_table_size(void);
point_type * allocate_table(size_t n);

int main(void) {
    /* .... */
    return EXIT_SUCCESS;
}

Po podziale na funkcje, ten kod będzie o wiele bardziej czytelny. 

Podobne pytania

0 głosów
1 odpowiedź 212 wizyt
0 głosów
1 odpowiedź 261 wizyt
pytanie zadane 7 kwietnia 2023 w C i C++ przez Zuzan Początkujący (390 p.)
0 głosów
1 odpowiedź 562 wizyt
pytanie zadane 19 listopada 2018 w C i C++ przez Roman1212 Początkujący (460 p.)

92,452 zapytań

141,262 odpowiedzi

319,079 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...