Stos nie działa

Stos nie działa
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0

a dokładnie funkcja print bo robi się w nieskończoność

Kopiuj

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

typedef struct list {
    int data;
    struct list* next;
} list_element;

int push_front(list_element* head, int n)
{
    list_element* tmp = (list_element*)malloc(sizeof(list_element));
    if (tmp == NULL) {
        puts("no memory");
        return 0;
    }
    tmp->data = n;
    tmp->next = head;
    head = tmp;
    return 1;
}
void print(list_element* head)
{
    printf("%d", head->data);
    print(head->next);
    if (head == NULL)
        return;
}

int main()
{
    list_element* first = NULL;

    int choice;
    int end_program;

    while (end_program != 0) {

        scanf("%d", &choice);

        switch (choice) {
        case 1:
            puts("Give me a number to add:");
            scanf("%d", &choice);
            push_front(first, choice);
            break;
        case 2:
            print(first);
            break;
        default:
            puts("Blad!");
            break;
        }
        puts("you continue?:");
        scanf("%d", &end_program);
    }

    return 0;
}


Format! Style:

C++ online code formatter © 2014 by KrzaQ

Powered by vibe.d, the D language and clang-format
Pebal
  • Rejestracja:ponad 12 lat
  • Ostatnio:około rok
  • Postów:111
0
Kopiuj
void print(list_element* head)
{
    printf("%d", head->data);
    print(head->next);
    if (head == NULL)
        return;
}

Ta pętla nigdy się nie skończy, gdyż nigdy nie dochodzi do sprawdzenia warunku. Zanim dochodzi do sprawdzenia funkcja wywołuje samą siebie.
Umieść warunek na początku funkcji:

Kopiuj
void print(list_element* head)
{
    if (head == NULL)
        return;
    printf("%d", head->data);
    print(head->next);
}
bartek164
no nie moge bo 1 element stosu jest pusty
Patryk27
@Pebal: prędzej by wyrzuciło NPE, a tutaj to się nie dzieje.
Pebal
Nie możesz operować na wskazywanym obiekcie jeżeli wskaźnik jest nulem. Musisz najpierw dokonać sprawdzenia.
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
1
Kopiuj
    tmp->next = head;
    head = tmp;

Hmmmm


bartek164
o co ci chodzi? no dobrze jest, head teraz wskazuje na tmp czyli ma 2 elementy (oczywiscie po dodaniu 1 liczby, potem wiecej)
Patryk27
Zacznijmy w sumie od tego, że nigdzie nie zmieniasz wartości zmiennej head, którą masz w mainie. Poczytaj o referencjach w C.
bartek164
przekazuje first które jest adresem, i na nim póżniej działam, przkazuje go do zmiennej wskażnikowej, no to jak niemodyfikuje
Pebal
Przekazujesz kopię first.
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0

aha, aha, no nie wiem dlaczgeo moja lista jest pusta, po dodaniu do niej liczb

bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0

tera działa, first = tmp;
no ale, dlaczego przecież jest przekazane przez wskażnik, więc powinno oddziaływać na first i go zmieniać nie rozumiem

Pebal
  • Rejestracja:ponad 12 lat
  • Ostatnio:około rok
  • Postów:111
0

Przekazujesz do funkcji kopię wskaźnika i tę kopię modyfikujesz. Musisz przekazać wskaźnik do first:

Kopiuj
int push_front(list_element** head, int n)
{
    list_element* tmp = (list_element*)malloc(sizeof(list_element));
    if (tmp == NULL) {
        puts("no memory");
        return 0;
    }
    tmp->data = n;
    tmp->next = *head;
    *head = tmp;
    return 1;
}

push_front(&first, choice);
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0

ale przecież first jest już adresem nie? to mam przekazać adres adresu

Pebal
  • Rejestracja:ponad 12 lat
  • Ostatnio:około rok
  • Postów:111
0

Ta gwiazdka oznacza jedynie tyle, że zmienna przechowuje adres. Przypisanie wartości do zmiennej nie modyfikuje danej wskazywanej przez ten adres a jedynie ten adres. Musisz przekazać adres wskaźnika.

edytowany 1x, ostatnio: Pebal
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0

omg teraz to jest pomieszane

Pebal
  • Rejestracja:ponad 12 lat
  • Ostatnio:około rok
  • Postów:111
2
Kopiuj
int a;        // zmienna przechowuje liczbę
int* b;       // zmienna przechowuje adres
int* c = &a;  // zmienna c przechowuje adres zmiennej a
int** d = &b; // zmienna d przechowuje adres zmiennej b
*c = 5;       // zapisujemy wartość w zmiennej a
*d = NULL;    // zapisujemy adres w zmiennej b
edytowany 1x, ostatnio: Pebal
bartek164
no no dzięki, widze to jaśniej
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0
Kopiuj
void print(list_element** head)
{   if (*head == NULL)
        return;
    printf("\t%d", (*head)->data);
    print((*head)->next);

}

wywala mi bład podczas wypisywania wartośći

edytowany 1x, ostatnio: bartek164
Patryk27
jaaaaaaaaaaaki błąd
bartek164
jakbym wiedział to bym powiedział :)
Patryk27
My jesteśmy w jeszcze gorszej pozycji, bo nie czytamy w myślach, ani nie widzimy Twojego monitora.
Pebal
To się nie powinno kompilować. Powinno być print(&(*head)->next); Jednak ta funkcja nie wymaga przekazania wskaźnika na adres. Pozostaw ją taką jaką była, tylko ze sprawdzeniem na początku.
bartek164
no miałeś rację, o kurde, głowa mnie boli ale rozumiem
Pebal
  • Rejestracja:ponad 12 lat
  • Ostatnio:około rok
  • Postów:111
0

Błąd wynika z priorytetów operatorów. Operator -> ma większy priorytet od operatora *. *head musisz umieścić w nawiasie.

edytowany 4x, ostatnio: Pebal
bartek164
tak tak, ale jest jakiś bład paskundy i program przestał działać, musze pomyśleć zaraz
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0

push back nie działa (zadanie -dodaje element na koniec listy)
dodatkwoo wpadłem na szlony pomysł jak usunąć całą listę, jest w case 8, nie wiem czy działa,się pytam

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

typedef struct list {
    int data;
    struct list* next;
} list_element;

int push_front(list_element** head, int n)
{
    list_element* tmp = (list_element*)malloc(sizeof(list_element));
    if (tmp == NULL) {
        puts("no memory");
        return 0;
    }
    tmp->data = n;
    tmp->next = *head;
    *head = tmp;
    return 1;
}
void push_back(list_element** head, int n)
{

    if (*head == NULL) {
        list_element* tmp = (list_element*)malloc(sizeof(list_element));
        if (tmp == NULL) {
            puts("no memory");
            return;
        }
        tmp->data = n;
        tmp->next = (*head)->next;
        (*head)->next = tmp;
        return;
    }
    else
        push_back(&(*head)->next, n);
}

void print(list_element** head)
{
    if (*head == NULL)
        return;
    printf("\t%d", (*head)->data);
    print(&(*head)->next);
}

void size(list_element* head)
{
    int amount = 0;
    for (; head != NULL; head = head->next)
        ++amount;
    printf("%d", amount);
}
void pop_front(list_element** head)
{
    list_element* tmp;
    tmp = *head;
    *head = (*tmp).next;
    free(tmp);
}

/*void pop_back(list_element** head)
{for(; ; head=(*head)->next)
    if((head=(*head)->next) ==NULL)
        free((*head)->next);


}
*/

int main()
{
    list_element* first = NULL;

    int choice;
    int end_program;

    while (end_program != 0) {

        scanf("%d", &choice);

        switch (choice) {
        case 1:
            puts("Give me a number to add:");
            scanf("%d", &choice);
            push_front(&first, choice);
            break;
        case 2:
            print(&first);
            break;
        case 3:
            size(first);
            break;
        case 4:
            pop_front(&first);
            break;
        case 5:
            puts("Give me a number to add:");
            scanf("%d", &choice);
            push_back(&first, choice);
            break;
        case 6:
            //  pop_back(&first);
            break;
        case 8:
            free(first);
            first = NULL;
            break;
        default:
            puts("Blad!");
            break;
        }
        puts("\nyou continue?:");
        scanf("%d", &end_program);
    }

    return 0;
}

edytowany 1x, ostatnio: bartek164
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
0

Formatuj kod należycie - nie da się go zrozumieć.


Pebal
  • Rejestracja:ponad 12 lat
  • Ostatnio:około rok
  • Postów:111
1
Kopiuj
void push_back(list_element** head, int n)
{
    list_element* tmp = (list_element*)malloc(sizeof(list_element));
    if (tmp == NULL) 
    {
        puts("no memory");
        return ;
    }

    tmp->data = n;
    tmp->next = NULL;
 
    if(*head == NULL)
    {
        *head = tmp;
    }
    else 
    {
        list_element** last = &(*head)->next;
        while(*last != NULL)
            last = &(*last)->next;
        *last = tmp;
    }
 }

Powinieneś jednak dodać do kodu zmienną, która przechowywałaby adres ostatniego węzła, aby czas dodawania na końcu listy był rzędu O(1) a więc taki sam, jak czas dodawania elementu na początku listy.

edytowany 5x, ostatnio: Pebal
Pebal
Teraz powinno być ok.
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0

Dobra poradzilem sobie z tym, jeśli ktoś ma pomysł jak napisać funkcję insert_before, dodającą element przed określonym elementem to będzie fajnie(w kodzie jest funkcja którą zrobiłem dodającą element po określonym elemencie-insert_after)

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

typedef struct list {
    int data;
    struct list* next;
} list_element;

int push_front(list_element** head, int n)
{
    list_element* tmp = (list_element*)malloc(sizeof(list_element));
    if (tmp == NULL) {
        puts("no memory");
        return 0;
    }
    tmp->data = n;
    tmp->next = *head;
    *head = tmp;
    return 1;
}

void print(list_element** head)
{
    if (*head == NULL)
        return;
    printf("\t%d", (*head)->data);
    print(&(*head)->next);
}

void size(list_element* head)
{
    int amount = 0;
    for (; head != NULL; head = head->next)
        ++amount;
    printf("%d", amount);
}
void pop_front(list_element** head)
{
    list_element* tmp;
    tmp = *head;
    *head = (*tmp).next;
    free(tmp);
}
void push_back(list_element** head, int n)
{
    list_element* tmp = (list_element*)malloc(sizeof(list_element));
    if (tmp == NULL) {
        puts("no memory");
        return;
    }

    tmp->data = n;
    tmp->next = NULL;

    if (*head == NULL) {
        *head = tmp;
    }
    else {
        list_element** last = &(*head)->next;
        while (*last != NULL)
            last = &(*last)->next;
        *last = tmp;
    }
}

void pop_back(list_element** head)
{
    list_element* tmp = *head;
    list_element* preavious = NULL;
    while (tmp->next) {
        preavious = tmp;
        tmp = tmp->next;
    }
    if (preavious == NULL) {
        free(head);
        head = NULL;
    }
    else {
        preavious->next = NULL;
        free(tmp);
    }
}

void insert_after(list_element* head, int n)
{
    int choice, i;
    printf("\nafter element(1,2..):");
    scanf("%d", &choice);

    for (i = 1; i < choice; ++i) {
        head = head->next;
    }
    list_element* tmp = (list_element*)malloc(sizeof(list_element));
    tmp->data = n;
    tmp->next = head->next;
    head->next = tmp;
}

void options()
{
    puts("1:push_front");
    puts("2:print list");
    puts("3:size list");
    puts("4:pop_front");
    puts("5:push_back");
    puts("6:pop_back");
    puts("7:insert_after");
    puts("8:clear list");
    puts("0:end program");
}

int main()
{
    list_element* first = NULL;

    int choice;
    int end_program;

    while (end_program != 0) {
        options();
        scanf("%d", &choice);

        switch (choice) {
        case 1:
            printf("\nGive me a number to add:");
            scanf("%d", &choice);
            push_front(&first, choice);
            break;
        case 2:
            print(&first);
            break;
        case 3:
            size(first);
            break;
        case 4:
            pop_front(&first);
            break;
        case 5:
            printf("\nGive me a number to add:");
            scanf("%d", &choice);
            push_back(&first, choice);
            break;
        case 6:
            pop_back(&first);
            break;
        case 7:
            printf("\nGive me a number to add:");
            scanf("%d", &choice);
            insert_after(first, choice);
            break;
        case 8:
            free(first);
            first = NULL;
            break;
        default:
            puts("Blad!");
            break;
        }
        printf("\nyou continue?(0 - end program):");
        scanf("%d", &end_program);
    }

    return 0;
}

edytowany 1x, ostatnio: bartek164
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0
Kopiuj
void insert_after(list_element** head, int n)
{
    if(*head ==NULL) {
        puts("no element");
        return;
    }
    int choice, i;
    printf("\nafter element(1,2..):");
    scanf("%d", &choice);

    for (i = 1; i < choice; ++i) {
        *head = (*head)->next;
    }
    list_element* tmp = (list_element*)malloc(sizeof(list_element));
    tmp->data = n;
    tmp->next = (*head)->next;
    (*head)->next = tmp;
}

```dobra jest, NIECH MI KTOS powie dlaczego bez ** ta poprzednia wersja działała poprawnie
edytowany 1x, ostatnio: bartek164
Pebal
Dlatego, że sobie założyłeś, że gdy wykonujesz insert_after to lista nie jest pusta. W związku z tym nigdy nie modyfikujesz w tej funkcji zmiennej first. To jest jednak bardzo ryzykowne założenie i z zasady błędne.
bartek164
ej nie rozumiem na prawde, no to jakim cudem potem jak wyświetlam liczby to działa prawidłowo, i dlaczego to działa, omg
Pebal
Funkcja działała poprawnie, bo nie wywoływałeś tej funkcji dla pustej listy. Podwójne wskaźniki nie są potrzebne jeżeli nie wstawia się elementów na froncie listy.
bartek164
yyyyy ale skoro przekazuje head, to przekazuje adres jakies struktury, i tam jest ona modyfikowana tak, no chyba rozumiem
Pebal
Dobrze rozumiesz. Jednak przekazywany wskaźnik nie może być nulem, bo nie masz wtedy żadnej struktury, którą można edytować.
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0

Mam pytanie, co się dzieje gdy w casie 8 wykonuje instrukcje free(first) ?

Pebal
Zwalniana jest pamięć pierwszego elementu listy.
bartek164
a reszta zostaje
bartek164
a to żem wyczyścił
Pebal
Reszta zostaje. Musisz iterować po liście i zwalniać pamięć dla poszczególnych węzłów. Pamiętając przy tym, że nie wolno odwołać się do elementu listy po zwolnieniu pamięci. Tak więc musisz odczytać pole next węzła przed zwolnieniem jego pamięci.
bartek164
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad rok
  • Postów:534
0

popatrzalem do internetu i jest to zrobione tak

Kopiuj

void UsunWszystkie(Wezel *&poczatek) 
{ Wezel *tmp; 
 while (poczatek != NULL) 
 { tmp = poczatek; 
 poczatek = tmp->nastepny; 
 free(tmp); 
 }
} ale to wynika z tego że tmp przypisujemy początek, no troche to jakieś dziwne, bo usuwamy pamięc tmp, przechodziy dalej, i dlaczego niby miało się ususnać poczatek, przecież tmp przchowuje adres, poczatku, ale nie ma tam ** , nie wiem 
Pebal
Nie ma wskaźnika na wskaźnik, ale jest referencja na wskaźnik. Pozwala zrealizować to samo.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)