problem mit einer funktion



  • hallo,

    warum funktioniert das hier

    # include <stdio.h>
    # include <stdlib.h>
    
    struct DATEN
    {
    	int kdnr;
    	struct DATEN *prev;
    	struct DATEN *next;
    };
    
    int show_list(struct DATEN *start, struct DATEN *end, int direction);
    
    int main()
    {
    	struct DATEN
    		*start,
    		*end,
    		*act,
    		*newone;
    	int counter = 0;
    	int again;
    
    	start = NULL;
    	act = NULL;
    
    	do
    	{
    		printf("Neuer Satz? (j)a / (n)ein\n");
    		again = getchar();
    		while(getchar() != '\n')
    			;
    		if(again == 'j')
    		{
    			newone = (struct DATEN *) malloc(sizeof(struct DATEN));
    			newone->kdnr = ++counter;
    			newone->next = NULL;
    			newone->prev = act;
    			if(start != NULL)
    			{
    				end = newone;
    				act->next = newone;
    			}
    			else
    			{
    				start = end = newone;
    			}
    			act = newone;
    		}
    	}while(again == 'j');
    
    // Ausgabe
    	printf("\n");
    	printf("Vorwaerts:\n");
    	for(act = start; act != NULL; act = act->next)
    	{
    		printf("Kundennummer: %d\n", act->kdnr);
    	}
    
    	printf("\n\n");
    
    	printf("Rueckwaerts:\n");
    	for(act = end; act != NULL; act = act->prev)
    	{
    		printf("Kundennummer: %d\n", act->kdnr);
    	}
    
    	return 0;
    }
    

    und warum funktioniert es nicht wenn ich den ausgabeteil durch diese funktion ersetze:

    int show_list(struct DATEN *start, struct DATEN *end, int direction)
    {
    	struct DATEN *act;
    	int error;
    	switch(direction)
    	{
    		case 1:
    			printf("Vorwaerts:\n");
    			for(act = start; act != NULL; act = act->next)
    				printf("Kundennummer: %d\n", act->kdnr);
    			error = 1;
    			break;
    		case -1:
    			printf("Rueckwaerts:\n");
    			for(act = end; act != NULL; act = act->prev)
    				printf("Kundennummer: %d\n", act->kdnr);
    			error = 1;
    			break;
    		default:
    			error = 0;
    			break;
    	}
    	return error;
    }
    

    vorwaerts ausgeben klappt ohne problem, aber wenn ich rückwaerts ausgeben möchte bekomme ich einen speicherzugriffsfehler...

    wäre fuer jede hilfe sehr dankbar!!

    grüße,

    Sternenstaub



  • lass mal deine funktion so beginnen

    int show_list(struct DATEN *start, struct DATEN *end, int direction) 
    { 
    	if (!start)
    		return 0;
    ...
    ...
    ...
    


  • vorwaerts ausgeben klappt immer noch, und rueckwaerts immer noch nicht...

    hier mal die genaue fehlermeldung:

    "test.exe" - Fehler in Anwendung
    Die Anweisung in "0x00401265" verweist auf Speicher in "0xcccccccc". Der Vorgang "read" konnte nicht auf dem Speicher durchgeführt werden.

    Klicken Sie auf "OK", um das Programm zu beenden.
    Klicken Sie auf "Abbrechen", um das Programm zu debuggen.

    hier der komplette sourcecode wie ich ihn auf die verschiedenen dateien verteilt habe:

    test.exe:

    # include <stdio.h>
    # include <stdlib.h>
    # include "GlobaleVar.h"
    # include "functions.h"
    
    int main()
    {
    	int i;
    	int error;
    	struct DATEN *anfang;
    	struct DATEN *ende;
    
    	printf("Wie viele Elemente: ");
    	scanf("%d", &i);
    
    	anfang = make_list(ende, i);
    	error = show_list(anfang, ende, 1);
    	printf("\n\n");
    	error = show_list(anfang, ende, -1);
    
    	return 0;
    }
    

    listfunkt.c:

    # include <stdio.h>
    # include <stdlib.h>
    # include "GlobaleVar.h"
    # include "functions.h"
    
    struct DATEN *make_list(struct DATEN *end, signed int sizel)
    {
    	struct DATEN
    		*start,
    		*act,
    		*newone;
    	int counter;
    	start = NULL;
    	act = NULL;
    	for(counter = 1; counter <= sizel; ++counter)
    	{
    		newone = (struct DATEN *) malloc(sizeof(struct DATEN));
    		newone->kdnr = counter;
    		newone->next = NULL;
    		newone->prev = act;
    		if(start != NULL)
    		{
    			end = newone;
    			act->next = newone;
    		}
    		else
    		{
    			start = end = newone;
    		}
    		act = newone;
    	}
    	return start;
    }
    
    int show_list(struct DATEN *start, struct DATEN *end, int direction)
    {
    	struct DATEN *act;
    	int error;
    	if(!start)
    		return 0;
    	switch(direction)
    	{
    		case 1:
    			printf("Vorwaerts:\n");
    			for(act = start; act != NULL; act = act->next)
    				printf("Kundennummer: %d\n", act->kdnr);
    			error = 1;
    			break;
    		case -1:
    			printf("Rueckwaerts:\n");
    			for(act = end; act != NULL; act = act->prev)
    				printf("Kundennummer: %d\n", act->kdnr);
    			error = 1;
    			break;
    		default:
    			error = 0;
    			break;
    	}
    	return error;
    }
    

    functions.h:

    struct DATEN *make_list(struct DATEN *end, signed int sizel);
    int show_list(struct DATEN *start, struct DATEN *end, int direction);
    

    GlobaleVar.h:

    struct DATEN
    {
    	int kdnr;
    	struct DATEN *prev;
    	struct DATEN *next;
    };
    

    könnte der fehler darin liegen, daß ich bei der aufteilung was falsch gemacht habe??



  • Sternenstaub schrieb:

    ...
    	struct DATEN *anfang;
    	struct DATEN *ende;
    ...
    	anfang = make_list(ende, i);
    

    du initialisierst zwar 'anfang', aber nicht 'ende'.
    wenn du's so machst, muss 'make_list' keinen einfachen pointer, sondern einen pointer auf pointer (struct DATEN**) bekommen



  • Spinn ich, oder dürften die For-Schleifen der Ausgabe generell nicht funktionieren (also, mich wundert, daß nur die rückwärtslaufende nicht tut)?

    for(act = start; act != NULL; act = act->next)
    

    Die Endbedingung müßte doch act->next != NULL sein...



  • hallo,

    diese schleife habe ich schamlos von meinem c-dozenten geklaut und mehrfach, erfolgreich, angewandt. wenn ich den code, wie ganz oben, also ohne funktionen, laufen lasse klappt auch alles ganz prima...



  • net schrieb:

    Sternenstaub schrieb:

    ...
    	struct DATEN *anfang;
    	struct DATEN *ende;
    ...
    	anfang = make_list(ende, i);
    

    du initialisierst zwar 'anfang', aber nicht 'ende'.
    wenn du's so machst, muss 'make_list' keinen einfachen pointer, sondern einen pointer auf pointer (struct DATEN**) bekommen

    struct DATEN *make_list(struct DATEN *end, signed int sizel);
    .
    .
    .
    anfang = make_list(ende, i);
    

    ich dachte eigentlich, durch diese funktion würde sowohl der wert von anfang gesetzt werden und ebenfalls der wert von ende, da ich ja ein call by reference mache, oder es zumindest versuche...

    wenn ich die funktion so umschreibe, wie muß ich dann end in der funktion ansprechen, um das gewünschte ergebnis zu erzielen?
    ist das so korrekt, oder muß ich

    struct DATEN *make_list(struct DATEN **end, signed int sizel)
    {
    ...
    		if(start != NULL)
    		{
    			*end = newone;
    			act->next = newone;
    		}
    		else
    		{
    			start = *end = newone;
    		}
    		act = newone;
    	}
    	return start;
    }
    

    vielen dank im voraus,

    Sternenstaub



  • vielen dank net,

    habe es, dank dir, hinbekommen!!
    der funktionsaufruf sieht jetzt so aus und in der funktion ist ende ein pointer auf pointer von struct DATEN.

    anfang = make_list(&ende, i);
    

    aber ich verstehe es noch nicht so ganz! durch:

    struct DATEN *make_list(struct DATEN *end, signed int sizel)
    

    übergebe ich doch schon die adresse von end und wenn ich die adresse habe kann ich doch den inhalt verändern, dachte ich zumindest...

    würde mir bitte jemand mal eine kleine hilfestellung geben wo ich bei folgenden drei variablen lande:

    int *p;
    int **pp;
    int ***ppp;
    

    wenn keinen, einen, zwei oder drei sterne davor setze und etwas dahin schreiben möchte?

    vielen dank im voraus,

    Sternenstaub



  • Sternenstaub schrieb:

    aber ich verstehe es noch nicht so ganz! durch:

    struct DATEN *make_list(struct DATEN *end, signed int sizel)
    

    übergebe ich doch schon die adresse von end und wenn ich die adresse habe kann ich doch den inhalt verändern, dachte ich zumindest...

    du übergibst 'end' aber die funktion arbeitet intern mit einer kopie (call by value). mit der kopie kannst du zwar die daten adressieren auf die 'end' zeigt, aber nicht 'end' selber.


Anmelden zum Antworten