C Stack mit Liste

T

thefy

Gast
Hallo Leute,

ich versuche einen Stack zu erzeugen. Dieser soll aber durch Nodes und eine einfach verkette Liste erstellt werden.

Eigentlich funktioniert es fast komplett. Nur die Print Funktion macht Probleme. Der Fehler müsste denke ich in der Zuordnung von head liegen.
Da ich jetzt ja immer weiter runter gehe aber head auf den obersten Node zeigt.
Deswegen funktioniert die while function nicht und er gibt nur aus:

--Top--
4
3
2
1
Segmentation fault

Das wird durch folgende Test main Funktion erzeigt:

Code:
int main(){
        
        struct Stack* my_stack = new_stack("mystack");
        
        printf("Add numbers from 1 to 4 in order to stack:\n");
        push_value(my_stack, 1);
        push_value(my_stack, 2);
        push_value(my_stack, 3);
        push_value(my_stack, 4);
        print_stack(my_stack);
    
    return 0;
}

Das source File sieht so aus:

Code:
struct Stack{
    struct Node* top;
    char stackname;
};

struct Node{
    int data;
    struct Node* next;
};

//Erzeuge einen neuen Stack mit dem gegebenen Namen (Name kann NULL sein)
struct Stack* new_stack(char* name) {
    struct Stack* neu = (struct Stack*) malloc(sizeof(struct Stack));
    neu->top = NULL;
    neu->stackname = *name;
    return neu;
}

//Lege den gegebenen Wert auf den stack. Diese Funktion erzeugt ein Node mit den gegeben Werten und legt es auf den stack.
void push_value(struct Stack* the_stack, int value) {
    struct Node* neu = (struct Node*) malloc(sizeof(struct Node));
    neu->data = value;
    neu->next = the_stack->top;
    the_stack->top = neu;
}

//Lege den gegebenen Node auf den stack. Diese Funktion ist für den Fall, dass ein Node schon vorhanden ist.
void push(struct Stack* the_stack, struct Node* new_node) {
    new_node->next = the_stack->top;
    the_stack->top = new_node;
}


//Gebe den Stack aus.
void print_stack(struct Stack* the_stack) {
    printf("--Top--\n");
    struct Node *head = the_stack->top;
	struct Node *current = the_stack->top;
	printf("%d\n", head->data);
	while (head != (current = current->next)){
		printf("%d\n", current->data);
	}
    printf("--Bottom--\n");
}


Was genau ist das Problem im Code? Könnt ihr mir eventuell sagen wie man das Lösen könnte. Gerne allgemein weil ich es ja auch verstehen möchte;)

Vielen Dank schon mal!
 
Schau dir mal die Schleife in der Ausgabe an und überlege worauf das unterste element im stack verweist.
 
Zuletzt bearbeitet:
1) ich würde zuerst prüfen, ob der Stack nicht leer ist, bevor überhaupt was ausgedruckt werden soll.
2) *censored*
 
Zuletzt bearbeitet: (spoiler entfernt ;))
Postet doch nocht immer gleich Lösungen. Gebt den Leuten ne Chance selbst drauf zu kommen mit nem Hinweis und gönntvihnen das Erfolgserlebniss.
Sorry für OT wollte ich schon lange mal loswerden
 
Naja. Üblicherweise erwartet man auf eine Frage eine Antwort und keine Rätsel.
Nur klappt das irgendwie in Mathe und Programmier Foren selten, vielleicht wegen einem mangelhaften Deutsch Verständnis? :)
 
Hm ich finde nicht das ich in Rätseln geschrieben habe. Meine Antwort war ein Hinweis auf die fehlerhafte Stelle.
 
Yessss danke für den Tipp, ich habe noch mal drüber nachgedacht! Das meinte ich mit allgemein;) Es muss != NULL sein! Danke für das "Erfolgserlebnis" :D

@black90: Ja hast recht, aber manchmal will man nicht gleich die Lösung sehen. Vor allem wenn man das Prinzip dahinter verstehen möchte.
 
black90 schrieb:
Naja. Üblicherweise erwartet man auf eine Frage eine Antwort und keine Rätsel.
Nur klappt das irgendwie in Mathe und Programmier Foren selten, vielleicht wegen einem mangelhaften Deutsch Verständnis? :)

Ich will hier ja keine Grundsatzdiskussion lostreten, aber wenn jemand dabei ist etwas zu lernen, dann nützt es ihm mehr, wenn man ihn darauf hinweist, wie man so ein Problem generell lösen kann. Beim Programmieren funktioniert das leider fast nur dadurch, dass man sich selber Gedanken macht und praktisch gar nicht, wenn man einfach die Lösung bekommt.

In der Mathematik kann einem ein Lösungsweg schon sehr weiterhelfen. Bei einem mathematischen Beweis wäre dann ein Hinweis schon wieder zielführender als die komplette Lösung; behaupte ich mal.
 
Ich habe mein Programm jetzt erweitert, um mit Stacks das Spiel Türme von Hanoi zu lösen.
Leider klappt die move Funktion in der das Spiel gelöst werden soll nicht richtig. Ich möchte das ganze mit recursion machen.
Die Inputs kommen direkt von der Kommandozeile, also 1. Argument: kleinste Scheibe, 2. Argument: größte Scheibe und dann die 3 Namen der Stacks.
Wenn nur eine Scheibe vorhanden ist funktioniert es und alles wird wie gewollt ausgegeben.
Bei mehreren Scheiben kommt aber "Segmentation fault":

./run_towers 1 2 A B C
***** BEFORE SOLVING *****


Tower A
--Top--
1
2
--Bottom--

Tower B
--Top--
--Bottom--

Tower C
--Top--
--Bottom--

2
***** SOLVING PUZZLE *****


Move ==> 1 from A to B
Segmentation fault


Der Fehler muss irgendwo in der move Funktion liegen denke ich, da es ja bei einer Scheibe klappt.



main-File mit der move Funktion:

Code:
#include "header.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

void move(int num_discs, struct Stack* source, struct Stack* destination, struct Stack* intermediate){
    
    if (num_discs == 1) {
        push(destination, source->top);
        pop(source);
        printf("Move ==> %d from %s to %s\n", num_discs, source->stackname, destination->stackname);
        return;
    }
    
    else {
    
    move(num_discs-1, source, intermediate, destination);
    
    push(destination, source->top);
    pop(source);
    printf("Move ==> %d from %s to %s\n", num_discs, source->stackname, destination->stackname);
    
    move(num_discs-1, intermediate, destination, source);
    
    }
    
}


int main(int argc, char **argv){
    
    int i;
    int b;
    char* input_string;
    
    if (argc<6) {
        printf("USAGE: run_towers range_start range_end tower1_name tower2_name tower3_name\n");
        return -1;
    }
    
    for (i=1; i<=2; i++) {

        input_string = argv[i];
        
        if (input_string[0] == 055 || isdigit(input_string[0]) != 0) {
            for (b=1; b<strlen(input_string); b++) {
                if (isdigit(input_string[b]) == 0) {
                    printf("USAGE: range_start and range_end must be integer values.\n");
                    return -2;
                }
            }
        }
        
        else {
            printf("USAGE: range_start and range_end must be integer values.\n");
            return -2;
        }
    }
    
    if (atoi(argv[1])>atoi(argv[2])) {
        printf("RANGE ERROR: A positive non-zero number of disks is required.\n");
        return -3;
    }
    
    char* NameA = argv[3];
    char* NameB = argv[4];
    char* NameC = argv[5];
    
    struct Stack* A = new_stack(NameA);
    struct Stack* B = new_stack(NameB);
    struct Stack* C = new_stack(NameC);
    
    for (i=atoi(argv[2]); i>=atoi(argv[1]); i--) {
        push_value(A, i);
    }
    
    printf("***** BEFORE SOLVING *****\n");
    printf("\n");
    printf("\n");
    printf("Tower %s\n", NameA);
    print_stack(A);
    printf("\n");
    printf("Tower %s\n", NameB);
    print_stack(B);
    printf("\n");
    printf("Tower %s\n", NameC);
    print_stack(C);
    printf("\n");
    
    int numdiscs;
    
    if (atoi(argv[1])==atoi(argv[2])) {
        numdiscs = 1;
    }
    
    if ((atoi(argv[1])<0) & (atoi(argv[2])>0)) {
        numdiscs = abs(atoi(argv[1]))+atoi(argv[2])+1;
    }
    
    if ((atoi(argv[1])<0) & (atoi(argv[2])<0)) {
        numdiscs = abs(atoi(argv[1]))-abs(atoi(argv[2]))+1;
    }
    
    else {
        numdiscs = atoi(argv[2])-atoi(argv[1])+1;
    }
    
    printf("%d\n", numdiscs);
    
    printf("***** SOLVING PUZZLE *****\n");
    printf("\n");
    printf("\n");
    
    move(numdiscs, A, C, B);
    
    printf("\n");
    
    printf("***** AFTER SOLVING *****\n");
    printf("\n");
    printf("\n");
    printf("Tower %s\n", NameA);
    print_stack(A);
    printf("\n");
    printf("Tower %s\n", NameB);
    print_stack(B);
    printf("\n");
    printf("Tower %s\n", NameC);
    print_stack(C);
    printf("\n");

    
    return 0;
}

Das Sourcefile von oben noch mal:

Code:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"


//Create a new, initialized stack with the name given in the argument. (Name can be NULL)
struct Stack* new_stack(char* name) {
    struct Stack* neu = (struct Stack*) malloc(sizeof(struct Stack));
    neu->top = NULL;
    neu->stackname = name;
    return neu;
}

//Push the given value onto the stack. This function will create a node with the given value and push it onto the stack.
void push_value(struct Stack* the_stack, int value) {
    struct Node* neu = (struct Node*) malloc(sizeof(struct Node));
    neu->data = value;
    neu->next = the_stack->top;
    the_stack->top = neu;
}

//Push the given node onto the stack. This function is for when you already have a created node in order to push it onto the stack.
void push(struct Stack* the_stack, struct Node* new_node) {
    new_node->next = the_stack->top;
    the_stack->top = new_node;
}

//Pop the top node from the stack, returning the node and updating the stack. Note: popping an empty stack returns NULL.
struct Node* pop(struct Stack* the_stack) {
    if ((the_stack->top) == NULL) {
        return 0;
    }
    
    else {
        struct Node* pop = the_stack->top;
        the_stack->top = the_stack->top->next;
        return pop;
    }
}

//Clear the entire stack, freeing all nodes (but not the stack itself).
void clear_stack(struct Stack* the_stack) {
    
	struct Node *current = the_stack->top;
    
    if ((the_stack->top) != NULL) {
        free(the_stack->top);
        the_stack->top = NULL;
       while ((current = current->next) != NULL){
		free(current);
       }
 
    }
   
}

void print_stack(struct Stack* the_stack) {
    printf("--Top--\n");
	struct Node *current = the_stack->top;
    
    if ((the_stack->top) != NULL) {
        printf("%d\n", current->data);
        while ((current = current->next) != NULL){
		printf("%d\n", current->data);
        }
    }
	
	
    printf("--Bottom--\n");
}
Ergänzung ()

Ok hat sich erledigt. Ich hab mein Hirn nochmal ordentlich in die Reserve gelockt und den Fehler gefunden:D

Das ist in der move-Function falsch:
push(destination, source->top);
pop(source);

da pop ja einen Wert zurück gibt der dem Ausdruck source->top entspricht muss ich einfach schreiben: push(destination, pop(source));
 
Warum popst du nicht erst und pushst das Ergebnis dann? Würde mögliche Fehler mit unerklärlicher Datenvermehrung vermeiden. In dem Fall ist es jetzt trivial, aber willst du dein Leben lang nur triviale Programme schreiben?
 
Zurück
Oben