logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Sortowanie bąbelkowe punktów 3D z etykietami - problem z przypisaniem etykiet

lOOpi 10 Gru 2006 12:11 5546 14
REKLAMA
  • #1 3315035
    lOOpi
    Poziom 10  
    Posty: 18
    witam,

    problem jest natepujacy:
    Mam strukture ktora definiuje zbior punktow. Jeden punkt ma zdefiniowane - 3 wspolrzedne x,y,z i etykiete o max 20 znakach. Jest 80 takich punktow. Uzytkownik sam przypisuje etykiety i wspolrzedne do punktow. Pozniej punkty sa sortowane wg rosnacej odleglosci od poczatku ukladow wspolrzednych (√x+y+z). Sortowanie babelkowe!
    Mam problem z sortowaniem tej tablicy a mianowicie z etykietami. Gdy definiuje nowa zmienna 'w' typu char i przypisuje do niej etykiete tablicy przy sortowaniu, otrzymje dziwne znaczki. Oto moj program, poprosze o wskazowki co do przerobki :)

    #include <stdio.h>
    #include <math.h>
    
    struct Zbior					// struktura definiujaca zbior punktow
    {
    	float x,y,z;
    	char etykieta[20];
    };
    
    int main(void)
    {
    	int licznik = 0;
    	int index;
    	struct Zbior punkty1[80];
    	printf("Podaj etykiete punktu.\n");
    	printf("Aby zakonczyc wcisnij [enter] na poczatku wiersza.\n");
    	while (licznik < 80 && gets(punkty1[licznik].etykieta) != NULL && punkty1[licznik].etykieta[0] != '\0' )
    	{
    		printf("Teraz podaj wartosci punktow x y z.\n");
    		scanf("%f %f %f", &punkty1[licznik++].x, &punkty1[licznik].y, &punkty1[licznik].z);
    		while (getchar() != '\n')
    			continue;
    		if (licznik < 80)
    		printf("podaj kolejna etykiete.\n");
    	}
            int i,j;
            float t;
    	for (i=0; i<80-1; i++)
    	{
    		for (j=0; j<80-1-i; j++)
    		{
    			if (punkty1[j+1].x + punkty1[j+1].y + punkty1[j+1].z < punkty1[j].x + punkty1[j].y + punkty1[j].z)
    				t=punkty1[j];
    				punkty1[j]=punkty1[j+1];
    				punkty1[j+1]=t;
    		}
    	printf("Oto lista Twoich punktow:\n");
    	for (index = 0; index < licznik; index++)
    	printf ("%s, wspolrzedne: %.2f %.2f %.2f\n", punkty1[index].etykieta, punkty1[index].x, punkty1[index].y, punkty1[index].z);
    	return 0;
    	}
    }	
  • REKLAMA
  • #2 3315432
    Samuraj
    Poziom 35  
    Posty: 2792
    Pomógł: 286
    Ocena: 619
    Nie analizowałem dokładnie algorytmu jakim to sortowałeś, ale proponuje przepisać całą tablice do wektora o ilości elementów (x*y*z) posortować, a następnie z powrotem w tablice.
    Może to trochę zabawy ale łatwiej wyłapać błędy.
  • #3 3315455
    lOOpi
    Poziom 10  
    Posty: 18
    hm problem jest taki ze nie moge uzyc zbyt skomplikowanych funkcji a o wektorach nie mam zielonego pojecia :|
  • REKLAMA
  • #4 3317916
    NewToN20
    Poziom 12  
    Posty: 31
    Pomógł: 1
    Witam,
    Samuraj mówiąc o wektorze miał CHYBA na myśli tablice jedno wymiarową np.,
     
    #define SIZE x*y*x; // to taka 'stała' w programie
    
    float tab[SIZE];
  • #5 3318062
    wiesniak
    Poziom 31  
    Posty: 1006
    Pomógł: 231
    Ocena: 52
    1. podwójna pętla for, zamiana elementów - weź to w klamry, bo teraz jeśli if się spełni, to wykonywana jest tylko linijka przypisania.
    2. zakres przebiegów pętli - nie ma sensu lecieć 80 razy jeśli wprowadzisz tylko 2 - uzależnij te pętle od zmiennej licznik.
    2. zmienna t nie ma prawa być float tylko Zbior.
    3. licznik++ w takim miejscu jak teraz to bezsens, bo kolejne liczby wpisywane są pod wyższy indeks.
    4. osobiście przebudowałbym całą pętlę while. jako warunek zostawiłbym licznik <80, a sprawdzenie etykiety zrobiłbym po jej wpisaniu (if zła etykieta then break). jej pobieranie zrobiłbym za pomocą fgets (i koniecznie po obu scanf czyszczenie bufora przez fflush(stdin); ). wtedy cały while(getchar... jest zbędny.
    popracuj nad tym, jak będziesz miał problemy to będę podpowiadał (już sobie przepisałem odpowiednio program, ale gotowca nie dam, a przynajmniej nie od razu:) ).
  • #6 3318261
    lOOpi
    Poziom 10  
    Posty: 18
    ok bede kombinowal ale glownie chodzi mi o to zeby zrobic te sortowanie tzn. zeby na koncu wyswietlic odleglosc punktow od ukladu wspolrzednych, wraz z ich etykietami. Problem chyba jest z tymi etykietami, poniewaz punkty sortuja sie dobrze (przynajmniej na to wyglada ;) ) a etykiety gdzies gina i wogole otrzymuje dziwne znaki zamiast liter.
  • #7 3318296
    wiesniak
    Poziom 31  
    Posty: 1006
    Pomógł: 231
    Ocena: 52
    odległość od układu współrzędnych? masz na myśli od środka układu? jeśli tak, to masz też zły warunek - nie wystarczy suma współrzędnych. można powiedzieć, że dostajesz sześcian o bokach wymiarach współrzędnych i musisz policzyć przekątną. choć dokładna znajomość jest Ci zbędna, więc wystarczy suma kwadratów.

    algorytm sortowania jest ok, pomijając ten brak klamer.
    problem sortowania polega na tym, że przelatujesz całą tablicę, a tylko część jest zapisana - w tym momencie niezapisane komórki tablicy przenoszą się na początek, bo w ich zmiennych jest śmiecie (przypadkowe wartości, które odpowiednio się zachowują przy sprawdzaniu która większa... choć w zasadzie problem pownien się rozwiązać jeśli podniesiesz zmienne do kwadratu bo wtedy wartości ujemne staną się dodatnie i zostaną na końcu tablicy - co nie zmienia faktu, że ciagle może pojawić się przekłamanie). syf w etykietach wynika właśnie z poprzedniego problemu (wyświetlanie komórek nie zapisanych wcześniej, tylko zawierających śmiecie).

    spróbuj zastosować to co wyżej napisałem, powinno pomóc.
  • #8 3318311
    lOOpi
    Poziom 10  
    Posty: 18
    ok dzieki wielkie, czyli przerobie wyrazenie pod pierwiastkiem na sume kwadratow i zobacze czy cos pomoze. Myslalem ze ten problem z etykietami to jakis glebszy bol i przy sortowaniu trzeba by oddzielnie zapisywac etykiety a oddzielnie wspolrzedne. Wybaczcie zamieszanie i kiepska znajomosc problemu ale w sumie to moj drugi program jaki kiedykolwiek napisalem ;)
  • REKLAMA
  • #9 3322658
    lOOpi
    Poziom 10  
    Posty: 18
    chyba juz jest lepiej ale caly czas cos nie tak. Znika mi jeden element a sortowanie wyglada na to ze chyba nie dziala...

    
    #include <stdio.h>
    #include <math.h>
    
    struct Zbior					// struktura definiujaca zbior punktow
    {
    	float x,y,z;
    	char etykieta[20];
    };
    
    int main(void)
    {
    	int licznik = 0;
    	int index;
    	struct Zbior punkty1[80];
    	printf("Podaj etykiete punktu.\n");
    	printf("Aby zakonczyc wcisnij [enter] na poczatku wiersza.\n");
    	while (licznik < 80 && gets(punkty1[licznik].etykieta) != NULL && punkty1[licznik].etykieta[0] != '\0' )
    	{
    		printf("Teraz podaj wartosci punktow x y z.\n");
    		scanf("%f %f %f", &punkty1[licznik].x, &punkty1[licznik].y, &punkty1[licznik].z);
    		while (getchar() != '\n')
    			continue;
    		if (licznik < 80)
    		printf("podaj kolejna etykiete.\n");
    		licznik++;
    	}
    	{
    	int i,j;
    	struct Zbior t;
    	for (i=0; i<licznik; i++)
    	{
    		for (j=0; j<licznik-i; j++)
    		{
    			if (punkty1[j+1].x * punkty1[j+1].x + punkty1[j+1].y * punkty1[j+1].y + punkty1[j+1].z *  punkty1[j+1].z < punkty1[j].x * punkty1[j].x + punkty1[j].y * punkty1[j].y + punkty1[j].z * punkty1[j].z)
    				t=punkty1[j];
    				punkty1[j]=punkty1[j+1];
    				punkty1[j+1]=t;
    		}
    	printf("Oto lista Twoich punktow:\n");
    	for (index = 0; index < licznik; index++)
    	printf ("%s, wspolrzedne: %.2f %.2f %.2f\n", punkty1[index].etykieta, punkty1[index].x, punkty1[index].y, punkty1[index].z);
    	return 0;
    	}
    	}
    }
    


    a oto wyniki...:
    Cytat:

    knoppix@1[Desktop]$ ./a.out
    Podaj etykiete punktu.
    Aby zakonczyc wcisnij [enter] na poczatku wiersza.
    a
    Teraz podaj wartosci punktow x y z.
    7 8 9
    podaj kolejna etykiete.
    b
    Teraz podaj wartosci punktow x y z.
    5 6 7
    podaj kolejna etykiete.
    c
    Teraz podaj wartosci punktow x y z.
    1 2 3
    podaj kolejna etykiete.
    d
    Teraz podaj wartosci punktow x y z.
    0 0 0
    podaj kolejna etykiete.

    Oto lista Twoich punktow:
    b, wspolrzedne: 5.00 6.00 7.00
    c, wspolrzedne: 1.00 2.00 3.00
    d, wspolrzedne: 0.00 0.00 0.00
    , wspolrzedne: 0.00 -0.00 0.00
    knoppix@1[Desktop]$


    bardzo prosze o pomoc!
  • REKLAMA
  • #10 3322837
    wiesniak
    Poziom 31  
    Posty: 1006
    Pomógł: 231
    Ocena: 52
    powrórzę się:
    1. podwójna pętla for, zamiana elementów - weź to w klamry (to co ma wykonać się jeśli warunek jest spełniony), bo teraz jeśli if się spełni, to wykonywana jest tylko linijka przypisania.
    poza tym:
    i<licznik oraz licznik-i musisz jeszcze odjąć 1 (bo jeśli wprowadziłeś jeden punkt, to porównań wykonujesz 0).
  • #11 3322921
    lOOpi
    Poziom 10  
    Posty: 18
    achh chodzilo o klamry po if czyli powinno byc tak:

     if (punkty1[j+1].x * punkty1[j+1].x + punkty1[j+1].y * punkty1[j+1].y + punkty1[j+1].z *  punkty1[j+1].z < punkty1[j].x * punkty1[j].x + punkty1[j].y * punkty1[j].y + punkty1[j].z * punkty1[j].z)
               {
                t=punkty1[j];
                punkty1[j]=punkty1[j+1];
                punkty1[j+1]=t; 
                }


    rozumiem ze o to chodzi?
    licznik juz poprawiam
  • Pomocny post
    #12 3322950
    wiesniak
    Poziom 31  
    Posty: 1006
    Pomógł: 231
    Ocena: 52
    tak, dokładnie o to mi chodziło.

    ps. osobiście wczytywanie punktów zrobiłbym tak:
       while (licznik < 80) 
       { 
       printf("Podaj etykiete punktu %d.\n",licznik);
       	fgets(punkty1[licznik].etykieta,20,stdin);
    	fflush(stdin); 
    	if(punkty1[licznik].etykieta[0] == '\n'  || punkty1[licznik].etykieta[0] == '\0' )
    		break;
          printf("Teraz podaj wartosci punktow x y z.\n"); 
          scanf("%f %f %f", &punkty1[licznik].x, &punkty1[licznik].y, &punkty1[licznik].z); 
    	  	fflush(stdin); 
    		licznik++;
       }

    jest mniej warunków i kod jest moim zdaniem lepiej rozplanowany (możnaby z tego zrobić funkcję po prostu wycinając ten kawałek), natomiast u Ciebie część wczytywania jest poza while i za każdym razem sprawdzasz czy jeszcze wypisywać prośbę o nową etykietę.
  • #13 3323009
    lOOpi
    Poziom 10  
    Posty: 18
    dziala! zastanawia mnie jedno - czy punkt 'd' nie powinien byc przed 'a'?:

    Cytat:


    Oto lista Twoich punktow:
    b, wspolrzedne: 0.00 0.00 0.00
    a, wspolrzedne: 1.00 2.00 3.00
    d, wspolrzedne: 1.00 1.00 1.00
    c, wspolrzedne: 9.00 9.00 9.00
    knoppix@1[Desktop]$


    dziekuje bardzo :D

    a zaraz przebuduje petle while, dzieki za podpowiedz.
  • #14 3323059
    wiesniak
    Poziom 31  
    Posty: 1006
    Pomógł: 231
    Ocena: 52
    zastanawia mnie jeszcze dlaczego pod koniec masz 3 klamry, czy nie powinny być 2, a jedna zamykać for przed printf("oto liczba twoich punktow"); ?
    skoro w zasadzie problem rozwiązany, to mój kod wygląda tak:
    #include <stdio.h> 
    #include <math.h> 
    
    struct Zbior               // struktura definiujaca zbior punktow 
    { 
       float x,y,z; 
       char etykieta[20]; 
    }; 
    
    int main(void) 
    { 
       int licznik = 0; 
       int index; 
       int i,j; 
       struct Zbior t;   
    	struct Zbior punkty1[80]; 
       printf("Aby zakonczyc wcisnij [enter] na poczatku wiersza.\n"); 
       while (licznik < 80) 
       { 
       printf("Podaj etykiete punktu %d.\n",licznik);
       	fgets(punkty1[licznik].etykieta,20,stdin);
    	fflush(stdin); 
    	if(punkty1[licznik].etykieta[0] == '\n'  || punkty1[licznik].etykieta[0] == '\0' )
    		break;
          printf("Teraz podaj wartosci punktow x y z.\n"); 
          scanf("%f %f %f", &punkty1[licznik].x, &punkty1[licznik].y, &punkty1[licznik].z); 
    	  	fflush(stdin); 
    		licznik++;
       }
       for (i=0; i<licznik-1; i++) 
       { 
          for (j=0; j<licznik-i-1; j++) 
          { 
             if (punkty1[j+1].x + punkty1[j+1].y + punkty1[j+1].z < punkty1[j].x + punkty1[j].y + punkty1[j].z) 
    		 {
                t=punkty1[j]; 
                punkty1[j]=punkty1[j+1]; 
                punkty1[j+1]=t; 
    		 }
          } 
       }
       printf("Oto lista Twoich punktow:\n"); 
       for (index = 0; index < licznik; index++) 
       printf ("%s, wspolrzedne: %.2f %.2f %.2f\n", punkty1[index].etykieta, punkty1[index].x, punkty1[index].y, punkty1[index].z); 
       return 0; 
    }

    sprawdziłem go na takich samych danych jak Twoje i działa poprawnie.
  • #15 3582198
    lOOpi
    Poziom 10  
    Posty: 18
    problem rozwiazany pomyslnie, mozna go jedynie troche polepszyc przypisujac mnozenie liczb x, y, z jakiejs zmiennej tak zeby linijka
    
    if (sqrt(zbi.zbior1[j+1].x * zbi.zbior1[j+1].x + zbi.zbior1[j+1].y * zbi.zbior1[j+1].y + zbi.zbior1[j+1].z *  zbi.zbior1[j+1].z) < sqrt(zbi.zbior1[j].x * zbi.zbior1[j].x + zbi.zbior1[j].y * zbi.zbior1[j].y + zbi.zbior1[j].z * zbi.zbior1[j].z)) // sortowanie wg wzoru sqrt(x^2+y^2+z^2)


    nie byla taka dluga bo sie pogubic mozna ;) Dzieki za wszelkie wskazowki, temat zamykam!

Podsumowanie tematu

✨ Dyskusja dotyczy problemu z sortowaniem tablicy struktur definiujących punkty 3D z etykietami w języku C. Każdy punkt posiada współrzędne x, y, z oraz etykietę znakową o długości do 20 znaków. Autor stosuje sortowanie bąbelkowe według rosnącej odległości punktów od początku układu współrzędnych, obliczanej jako pierwiastek sumy kwadratów współrzędnych (√(x² + y² + z²)). Problem polegał na nieprawidłowym przypisywaniu i wyświetlaniu etykiet po sortowaniu, co wynikało z błędów w obsłudze tablic znaków oraz niepełnego zakresu sortowania (przetwarzanie niezainicjowanych elementów tablicy). Zalecano poprawę pętli sortującej poprzez dodanie klamer, ograniczenie zakresu pętli do faktycznej liczby wprowadzonych punktów oraz użycie struktury do tymczasowego przechowywania punktów podczas zamiany. Wczytywanie etykiet i współrzędnych poprawiono przez zastosowanie funkcji fgets i czyszczenie bufora wejściowego, co zapobiegało błędom w odczycie. Ostatecznie problem rozwiązano, a autor zasugerował optymalizację poprzez wprowadzenie zmiennej przechowującej wartość odległości zamiast powtarzania długiego wyrażenia w warunku sortowania. Dyskusja zawierała także wskazówki dotyczące poprawnej obsługi pętli i warunków zakończenia wczytywania danych.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA