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

Stos elementów w C

Object Storage Arubacloud
0 głosów
477 wizyt
pytanie zadane 31 maja 2018 w C i C++ przez Alan Kruszyński Obywatel (1,410 p.)
#include <stdio.h>
#include <stdlib.h>


/*ZMIENNE*/
int opcja, wartosc, i, nr_elem=0;
int *top;
struct element{
    int wartosc;
    int *poprzednik;
};

/*FUNKCJE*/
void push(){
 printf("\nWartosc nowego elementu: ");scanf("%d", &wartosc);

    if (nr_elem == 0){
                int *element;
                element=(int*)malloc(sizeof(struct element));
                struct element{
                    int wartosc;
                    int *poprzednik;
                }elem={*(&wartosc), NULL};
                elem.poprzednik=top;
                top = &elem;
                nr_elem++;

                printf("Utworzono pierwszy element stosu o wartosci %d", wartosc);
                printf("\nUstawiono szczyt stosu na ten element, brak poprzednika\n\n");
            }
    if (nr_elem != 0){

            int *element;
                element=(int*)malloc(sizeof(struct element));
                struct element{
                    int wartosc;
                    int *poprzednik;
                }elem={*(&wartosc), NULL};
                elem.poprzednik=top;
                top = &elem;
                nr_elem++;

                printf("Utworzono element stosu o wartosci %d", wartosc);
                printf("\nUstawiono szczyt stosu na ten element\n\n");
                }
}

void pop(){
    int tmp;
    tmp = *top;
    top=elem.poprzednik;
    elem.wartosc=tmp
}
void peek(){

    printf("Na wierzcholku stosu znajduje sie element o wartosci %d",*top );
}
//----------------------------------------------------------------//
main(){
for(;;){
    printf(" ----------------MENU------------------\n");
    printf("| 1. Dodaj element do stosu            |\n");
    printf("| 2. Zdejmij element ze stosu          |\n");
    printf("| 3. Sprawdz co lezy na wierzchu stosu |\n");
    printf("| 4. Zakoncz program                   |\n");
    printf(" --------------------------------------\n");
    printf("| \Wybierz numer opcji: ");scanf("%d", &opcja);

switch(opcja){
case 1:
    push();
    break;

case 2:
    //void pop;
    break;

case 3:
    peek();
    break;

case 4:
    break;
}
}
}

Mam za zadanie do szkoły napisać stos elementów który działa w sposób pokazany wg opcji Menu. Materiał realizowany jest dość szybko a ja nie miałem czasu wszystkiego dokładnie ogarnąć z uwagi na pracę. Naklepałem trochę kodu i w stanie takim jak tutaj widać utknąłem. Przejrzałem kod i naszło mnie kilka pytań bez odpowiedzi na które chyba nie pójdę dalej.

1. Czy dobrze  myślę że przy aktualnej wersji kodu tworzony element stosu ma cały czas taką samą nazwę, czyli element stosu jest nadpisywany i w efekcie mamy cały czas jeden element? Jak zwiększać numer elementu przy każdym utworzeniu? 

2. Jak w funkcji peek wypisać na ekranie wartość ze struktury element?

3. Jak usunąć element ze stosu? Tzn wymyśliłem że utworzę jakiś tmp i tam zapiszę wartość top, top przesunę na poprzednik, wartość na wartość poprzednika itd... Wiem co zrobić ale nie mam kompletnie pomysłu jak zrobić.

Wykładowca wymaga używania funkcji malloc i free oraz wskaźników, a ja się ze wskaźnikami do niedawna bardzo nie lubiłem. Wiem że podobne tematy już istnieją, ale mnie interesuje rozwiązanie sprecyzowane do mojego kodu, ponieważ właśnie taki  sposób w jaki próbowałem zaimplementować stos interesuje wykładowcę

komentarz 31 maja 2018 przez monika90 Pasjonat (22,940 p.)
W deklaracji funkcji należy podać typ zwracany, w przypadku main powinien to być int, nie można tego pominąć.

2 odpowiedzi

0 głosów
odpowiedź 31 maja 2018 przez Wunsz Użytkownik (680 p.)

To co zrobiłeś chyba nie jest stos. Stos to tablica i masz jedna zmienna określającą pozycje tej danej na wierzchu.To ma działać na zasadzie LIFOLast In, First Outostatni na wejściu, pierwszy na wyjściu. 

0 głosów
odpowiedź 31 maja 2018 przez RafalS VIP (122,820 p.)

Może zacznę od wypisania błędów w Twoim kodzie a potem odpowiem na pytania.

Używanie zmiennych globalnych to zła praktyka, nie jest to błąd, ale lepiej tak nie robić.

struct element nie jest poprawnym elementem stosu, w tej wersji to nie ma prawa działać. Stos w postaci listy (bo taki zacząłeś pisać) składa się z elementów, które mają jakąś wartość i wskaźnik na kolejny/poprzedni element w liście. Twój element ma wartość i wskaźnik na inta, a nie na kolejny/poprzedni element listy czyli struct element * poprzednik. Mam nadzieję, że Cię tym nie zaskoczę, ale typy mają znaczenie :P

struct element {
	int wartosc;
	int *poprzednik;
};

To nie jest deklaracja zmiennej. To jest definicja typu. Niżej w kodzie nie ma sensu coś takiego:

		struct element {
			int wartosc;
			int *poprzednik;
		}elem = { *(&wartosc), NULL };

wystarczy:

struct element elem = {wartosc,NULL};

Bo typ struct element jest już zdefiniowany. Po drugie: linijke niżej robisz tak:

elem.poprzednik = top;

po co wstawiłeś tam NULLa linijkę wyżej, jeśli zaraz go nadpisujesz. Zrób tak:

elem = { wartosc, top };

Jak już jesteśmy tutaj to:

*(&wartosc)

yyy? Czemu, dlaczego, po co? Pobierasz adres zmiennej wartość, a potem go dereferenciujesz tzn wyciągasz wartość tego co się w tej pamięci kryje, czyli: wartosc == *(&wartosc). * i & się tutaj znoszą.

top = &elem;

Typ elem to struct element a top to int*. Lepiej nie przypisywać niekompatybilnych wskaźników. Czasem działa, czasem nie, bo nigdzie w standardzie nie ma, że wszystkie wskaźniki będą miały tą samą wielkość. Nie mówiąc już o tym, że strasznie to zaciemnia kod i generuje ostrzeżenia :P

void pop(){
    int tmp;
    tmp = *top;
    top=elem.poprzednik;
    elem.wartosc=tmp
}

elem był lokalną zmienną w innej funkcji. Nie jest tu widoczny.

		int *element;
		element = (int*)malloc(sizeof(struct element));
		struct element {
			int wartosc;
			int *poprzednik;
		}elem = { *(&wartosc), NULL };

malloc w ten sposób jest bez sensu. Po pierwsze totalnie niekompatybilne typy. Wielkość struct element to 2x wielkość inta. Po drugie alokujesz dynamicznie składową elementu, a sam element jest niszczony po wyjściu z funkcji.

Wykładowca wymaga używania funkcji malloc i free oraz wskaźników

Bardzo dobrze, że wymaga bo inaczej się tego nie da napisać.

Może kilka zdań o dynamicznej alokacji. Zmienne lokalne są automatycznie zwalniane na końcu zakresu. Tzn, że tworzony przez Ciebie struct element elem. Znika po wyjściu z funkcji. Mówimy o takiej syutacji:

int* fun() {
	int x = 5;
	int * wsk = &x;
	return wsk;
}

int main() {
	int * result = fun();
	printf("%d", result);
}

Powinno wypisać jakieś śmieci. Bo int x na który wskazuje result został zniszczony po wyjściu z funkcji. Zapobiec temu można dynamiczną alokacją (malloc, free), która pozwala nam samym decydować kiedy pamięć jest zwlaniana:

int* fun() {
	int * x = malloc(sizeof(int));
	*x = 5;
	return x;
}

int main() {
	int * result = fun();
	printf("%d\n", *result);
	free(result);
	printf("%d\n", *result);
}

Teraz pierwszy printf wypisze nasza 5. A drugi śmieci bo zdecydowaliśmy się zwolnić pamięć i jest ten sam efekt co wcześniej po wyjściu z funkcji. Jednak w przeciwieństwie do 1. przykładu tutaj to my decydujemy kiedy pamięć jest zwalniana. W 1. przypadku kompilator sam automatycznie zwalniał pamięć po wyjściu z zakresu.

Szczerze odpowiedz na pytania nie ma sensu przed naprawieniem tych błędów, bo teraz ten program nie ma za bardzo sensu.

A tak na marginesie - Twój problem prawie wcale nie różni się tak bardzo od innych list na tym forum. Poczytaj jak oni to robili, bo nie chce mi się tego samego pisać setny raz.

Podobne pytania

0 głosów
2 odpowiedzi 291 wizyt
pytanie zadane 18 listopada 2022 w C i C++ przez Czarus Obywatel (1,310 p.)
0 głosów
1 odpowiedź 281 wizyt
pytanie zadane 17 czerwca 2019 w C i C++ przez Giero112 Nowicjusz (170 p.)
0 głosów
2 odpowiedzi 348 wizyt
pytanie zadane 24 maja 2019 w C i C++ przez Kaper99 Użytkownik (660 p.)

92,567 zapytań

141,420 odpowiedzi

319,615 komentarzy

61,952 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy 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!

...