Zeigerhilfen ( C )

Hallo Freunde.

Ich habe eine kleines Zeigerproblem:

In Nachfolgendem Beispielquelltext bekomme ich immer einen SIGSEV bei Ausführung und ich bekomme schon bei der Kompilierung Fehler weil angeblich ein falscher Typ zurückgegeben wird.

Wenn ich eine explizite Typkonvertierung mache bekomme ich Warnungen und bei Ausführung den beschriebenen SIGSEV (Segmentation Fault).

Ich habe von Zeigern leider noch nicht so die Kenne, da ich mihc mit C bisher seltener befasst habe. Bitte helft mir, da ich diese Sachen für die Arbeit lernen muss.

Ich wäre auch für jeden Hinweis auf andere grobe Patzer dankbar.

Apropos: Ich habe noch keine Funktionen eingebaut, welche den Speicher aufräumen, da bin ich bisher noch nicht zu gekommen, allerdings ist es nicht schlimm, da ich ohnehin nur mit einer verketteten Liste arbeite(n möchte):wink:

Erstmal vielen Dank für jede Hilfe…

… und hier der Quelltext:

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 \* Copyright (C) 2004 by Alexander Fischer \*
 \* [email protected] \*
 \* \*
 \* This program is free software; you can redistribute it and/or modify \*
 \* it under the terms of the GNU General Public License as published by \*
 \* the Free Software Foundation; either version 2 of the License, or \*
 \* (at your option) any later version. \*
 \* \*
 \* This program is distributed in the hope that it will be useful, \*
 \* but WITHOUT ANY WARRANTY; without even the implied warranty of \*
 \* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \*
 \* GNU General Public License for more details. \*
 \* \*
 \* You should have received a copy of the GNU General Public License \*
 \* along with this program; if not, write to the \*
 \* Free Software Foundation, Inc., \*
 \* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \*
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

#include 
#include 
#include 
#include 
#include 

/\*
ToDo Liste:
--\> Speicherfreigabe noch in cleanup() einbauen (Speicher der verketteten Liste)
--\> Datensatzedit fertmachen:
 \-\> Datensätze richtig anzeigen lassen
 \-\> Die Fenster ausgabe in edit\_record ist erstmal wichtig
 \-\> edit\_specified\_record() noch bauen
 \-\> Datensatz löschen noch einbauen
--\> Übersicht einbauen
 \-\> Kilometer/ Verbrauch insgesamt etc.

\*/

struct record
{
 int datum;
 float getankt;
 float kosten;
 float tachostand;
 struct record \*next; //Pointer auf nächstes Struct wegen verketteter Liste
};



void malloc\_fail( void );
void fail( int error, int line);
/\*
Mögliche Fehlercodes:
1= Datei E/A
2= Memory Allocation Error (Nicht für Fenster, dort dann malloc\_fail())
\*/
void cleanup ( void ); //Aufräumarbeiten zum Programmende
void splash\_screen( void );
void addtolist( struct record \*newr );

int load\_data( void );
int save\_data( void );
int menu( void );
int overview( void );
int new\_record( void );
int edit\_record( void );
int is\_numeric( char input );
int edit\_specified\_record( struct record \*editr );



 
 struct record \*firstrecord;
 struct record \*header;

 //List Header

WINDOW \*p\_Win;



int main(int argc, char \*argv[])
{

 int value\_menu = 1;

 initscr();

 /\* Ein Curses Window öffnen; bei Fehler die Funktion malloc\_fail aufrufen und das Programm killen \*/
 if((p\_Win = newwin(LINES,COLS,0,0)) == ((WINDOW \*) NULL)) malloc\_fail(); 

 /\* Mein Splash Screen \*/
 splash\_screen();

 /\*So, hier wirds interessant: Gespeicherte daten schon mal spontan in den Arbeitsspeicher laden, werden 
 keine Daten gelesen, dann gibt load\_data eine 1 (TRUE) raus und der Header wird auf NULL gesetzt\*/
 if(load\_data())
 {
 firstrecord = NULL;
 header = NULL;
 }


 //Die Schleife für das Menü
 while(value\_menu)
 {
 value\_menu = menu();
 }

 //Programmende...
 cleanup(); //Programmcurses beenden
 printf( "Das Programm wurde normal beendet!\n" );
 return 0;
}


void malloc\_fail( void )
{
/\* Programm KILL Funktionen, wenn bei curses etwas schief geht!\*/

 clear();
 mvcur(0, 4, 0, 0);
 refresh();
 endwin();

 printf( "Achtung! Nicht genügend Arbeitsspeicher, oder Fehler bei der Zuweisung von Arbeitsspeicher.\n\nDas Programm wird unnormal beendet! Eventuell sind Ihnen Daten verloren gegangen." );

}

void fail( int error, int line )
{
 cleanup(); //Curses beenden
 switch(error)
 {
 case 1:
 printf( "Datei E/A Fehler!" );
 exit(error);
 break;

 case 2:
 printf( "Es konnte kein Speicher reserviert werden. Fehler beim reservieren des Arbeitsspeichers." );
 exit(error);
 break;

 default:
 printf( "Unbekannter Fehler!: %d", error );
 exit(error);
 break;
 }
}

void cleanup( void )
{
 /\*hier rufen wir die Funktionen auf um curses zu beenden nachdem das Bild ggeklärt und der 
 Cursor zurückgestzt worden ist\*/
 clear();
 mvcur(0,0,0,0);
 refresh();
 endwin();
 save\_data(); // daten speichern

}

void splash\_screen( void )
{
 WINDOW \*p\_Subwin;
 p\_Subwin = NULL;
 if((p\_Subwin = subwin(p\_Win, 9, 23, (int)LINES/2-9, (int)COLS/3-11)) == (WINDOW \*) NULL) malloc\_fail();

 box(p\_Subwin, '|', '-');
 wmove(p\_Subwin, 3, 1);
 waddstr(p\_Subwin, " Spritrechner");
 wmove(p\_Subwin, 5, 1);
 waddstr(p\_Subwin, "(c)2004 A. Fischer" );
 wrefresh(p\_Subwin);
 sleep(1);
 delwin(p\_Subwin);
 refresh(); 

}

int menu()
{
 WINDOW \*p\_Menuwin;
 p\_Menuwin = NULL;

 int line = 2;
 int col = 2;
 char sel;

 if((p\_Menuwin = newwin(8, 40, 5, 5)) == ((WINDOW \*) NULL)) malloc\_fail();

 box(p\_Menuwin, '|', '-'); 

 wmove(p\_Menuwin, line, col);
 waddstr(p\_Menuwin, "1. Uebersicht");
 line++;

 wmove(p\_Menuwin, line, col);
 waddstr(p\_Menuwin, "2. Neuen Datensatz");
 line++;

 wmove(p\_Menuwin, line, col);
 waddstr(p\_Menuwin, "3. Datensatz bearbeiten (N/A)");
 line++;

 wmove(p\_Menuwin, line, col);
 waddstr(p\_Menuwin, "q Programm beenden");

 wrefresh(p\_Menuwin);

 noecho(); crmode();

 sel = getch();
 switch(sel)
 {
 case 'q':
 delwin(p\_Menuwin);
 refresh();
 return 0;
 break;

 case '1':
 delwin(p\_Menuwin);
 refresh();
 overview();
 return 1;
 break;

 case '2':
 delwin(p\_Menuwin);
 clear();
 refresh();
 new\_record();
 return 1;
 break;

 case '3':
 delwin(p\_Menuwin);
 refresh();
 edit\_record();
 return 1;
 break;

 default:
 delwin(p\_Menuwin);
 refresh();
 return 1;

 }
 echo(); nocrmode();
 return 0;
}

int overview()
{

 return 0;
}

int new\_record()
{
 struct record \*new; new = NULL;
 WINDOW \*p\_First;

 char input;
 input = 0;

 new = (struct record \*)malloc(sizeof(struct record));
 if(!(new)) fail(2, \_\_LINE\_\_);
 new-\>next = NULL;

 p\_First = newwin(10, 50, 5, 10);

 box(p\_First, ':', (char)163);

 int line = 2; int col = 2;

 mvwaddstr(p\_First, line, col, "Getankte Liter:");
 mvwaddstr(p\_First, line+2, col, "Preis:");
 mvwaddstr(p\_First, line+4, col, "Tachostand:");
 mvwaddstr(p\_First, line+6, col, "Datum(JJJJ-MM-TT):");

 mvwaddstr(p\_First, line, col+20, "\_\_\_\_\_\_\_\_\_\_");
 mvwaddstr(p\_First, line+2, col+20, "\_\_\_\_\_\_\_\_\_\_");
 mvwaddstr(p\_First, line+4, col+20, "\_\_\_\_\_\_\_\_\_\_");
 mvwaddstr(p\_First, line+6, col+20, "\_\_\_\_-\_\_-\_\_");

 wrefresh(p\_First);


 //Erstes Feld füllen
 wmove(p\_First, line, col+20);
 wrefresh(p\_First);
 char eingabe[11];
 int i = 0;
 while((input = getch()) != 10)
 {
 if(i == 10) break;

 input = is\_numeric(input);

 if(input)
 {
 eingabe[i] = input;
 waddch(p\_First, input);
 wrefresh(p\_First);
 i++;
 }

 }
 eingabe[i] = '\0';
 new-\>getankt = \*eingabe;
 i=0;

 //Nächstes Feld füllen
 wmove(p\_First, line+2, col+20);
 wrefresh(p\_First);
 fflush(stdin);
 while((input = getch()) != 10)
 {
 if(i == 10) break;

 input = is\_numeric(input);

 if(input)
 {
 eingabe[i] = input;
 waddch(p\_First, input);
 wrefresh(p\_First);
 i++;
 }
 }
 eingabe[i] = '\0';
 new-\>kosten = \*eingabe;
 i = 0;

 //Nächstes Feld füllen
 wmove(p\_First, line+4, col+20);
 wrefresh(p\_First);
 fflush(stdin);
 while((input = getch()) != 10)
 {
 if(i == 10) break;

 input = is\_numeric(input);

 if(input)
 {
 eingabe[i] = input;
 waddch(p\_First, input);
 wrefresh(p\_First);
 i++;
 }
 }
 eingabe[i] = '\0';
 new-\>tachostand = \*eingabe;
 i = 0;


 //Nächstes Feld füllen
 wmove(p\_First, line+6, col+20);
 wrefresh(p\_First);
 fflush(stdin);
 while((input = getch()) != 10)
 {
 if(i == 8) break;

 input = is\_numeric(input);

 if(input)
 {
 eingabe[i] = input;
 waddch(p\_First, input);
 if(i == 3) waddch(p\_First, '-'); //Trennstriche für das Datum verwenden
 if(i == 5) waddch(p\_First, '-');
 wrefresh(p\_First);
 i++;
 }
 }
 eingabe[i] = '\0';
 new-\>datum = \*eingabe;
 i = 0;

 addtolist(new); //Funktion um die Struktur, die gerade initialisiert wurde, an die verkettete Liste anzuhängen

 clear();
 delwin(p\_First);
 refresh();
 return 0;
}

int edit\_record()
{
 struct record \*temp; temp = header;
 WINDOW \*p\_First; p\_First = NULL;

 char input; input = (char)0;
 char output[11];
 int line = 2; int col = 2;

 p\_First = newwin(10, 50, 5, 10);
 if(!(p\_First)) malloc\_fail();

 box(p\_First, '+', '+');

 while((input = getch()) != 'q')
 {
 if(!(temp)) break;
 if(input == 'e') edit\_specified\_record( temp );
 temp = temp-\>next;

 int line = 2; int col = 2;

 mvwaddstr(p\_First, line, col, "Getankte Liter:");
 mvwaddstr(p\_First, line+2, col, "Preis:");
 mvwaddstr(p\_First, line+4, col, "Tachostand:");
 mvwaddstr(p\_First, line+6, col, "Datum(JJJJ-MM-TT):");


 //So Hier ist der Knackpunkt. Die in der Verketteten Liste gespeicherten Daten möchte ich hier ausgeben und ggfl
 //editieren können. Allerdings bekomme ich immer Pointer fehler. Gezielte Typkonvertierungen führen zu einem
 // Speicherzugriffsfehler.
 mvwaddstr(p\_First, line, col+20, temp-\>getankt);
 mvwaddstr(p\_First, line+2, col+20, temp-\>kosten);
 mvwaddstr(p\_First, line+4, col+20, temp-\>tachostand);
 datum = temp-\>datum;
 wmove(p\_First, line+6, col+20);

 int b;
 for(b = 0; bnext) //Wenn der Zeiger auf das nächste Element ungleich NULL gespeichert wurde, dann muss noch ein weiteres Element existieren. Der Zeiger muss unbedingt aktualisiert werden, da er sonst auf die falsche Speicherstelle zeigt. 
 {
 do
 {
 temp = (struct record \*)malloc(sizeof(struct record));
 if(!(temp)) fail(2, \_\_LINE\_\_);

 if(!(fread(temp, sizeof(struct record), 1, myfile))) fail(2, \_\_LINE\_\_);
 actual-\>next = temp; // UNd hier wird der Zeiger aktualisiert. Den Allerletzten Zeiger muss icj nicht aktualisieren da ohnehin NULL
 actual = temp;
 }
 while(temp-\>next);
 }

 return 0;
}

int is\_numeric( char input )
//Prüft, ob eingabe numerisch (float)
{
 switch(input)
 {
 case ',':
 input = '.';
 case '0':
 case '1':
 case '2':
 case '3':
 case '4':
 case '5':
 case '6':
 case '7':
 case '8':
 case '9':
 case '.':
 return input;
 break;
 default:
 return 0;
 }
}

void addtolist( struct record \*newr )
{
 struct record \*temp; temp = NULL;

 if(header == NULL)
 {
 header = newr;
 header-\>next = NULL;
 }
 else
 {
 temp = header;
 while(temp-\>next != NULL)
 {
 temp = temp-\>next;
 }

 temp-\>next = newr;
 newr-\>next = NULL;
 }

}

int save\_data( void )
{
 struct record \*temp; temp = NULL;
 FILE \*myfile; myfile = NULL;
 myfile = fopen("./data", "wb");

 temp = header;

 if(temp)
 {
 do
 {
 fwrite(temp, sizeof(struct record), 1, myfile);
 temp = temp-\>next;
 } while(temp);
 }
 fclose(myfile);
 return 0;
}

int edit\_specified\_record( struct record \*editr )

//Noch nicht fertig, soll halt einen bestimmten Datensatz ändern
{
 WINDOW \*p\_First;

 char input;
 input = 0;

 new = (struct record \*)malloc(sizeof(struct record));
 if(!(new)) fail(2, \_\_LINE\_\_);
 new-\>next = NULL;

 p\_First = newwin(10, 50, 5, 10);

 box(p\_First, ':', (char)163);

 int line = 2; int col = 2;

 mvwaddstr(p\_First, line, col, "Getankte Liter:");
 mvwaddstr(p\_First, line+2, col, "Preis:");
 mvwaddstr(p\_First, line+4, col, "Tachostand:");
 mvwaddstr(p\_First, line+6, col, "Datum(JJJJ-MM-TT):");

 mvwaddstr(p\_First, line, col+20, "\_\_\_\_\_\_\_\_\_\_");
 mvwaddstr(p\_First, line+2, col+20, "\_\_\_\_\_\_\_\_\_\_");
 mvwaddstr(p\_First, line+4, col+20, "\_\_\_\_\_\_\_\_\_\_");
 mvwaddstr(p\_First, line+6, col+20, "\_\_\_\_-\_\_-\_\_");

 wrefresh(p\_First);

 //Erstes Feld füllen
 wmove(p\_First, line, col+20);
 wrefresh(p\_First);
 char eingabe[11];
 int i = 0;
 while((input = getch()) != 10)
 {
 if(i == 10) break;

 input = is\_numeric(input);

 if(input)
 {
 eingabe[i] = input;
 waddch(p\_First, input);
 wrefresh(p\_First);
 i++;
 }

 }
 eingabe[i] = '\0';
 editr-\>getankt = \*eingabe;
 i=0;

 //Nächstes Feld füllen
 wmove(p\_First, line+2, col+20);
 wrefresh(p\_First);
 fflush(stdin);
 while((input = getch()) != 10)
 {
 if(i == 10) break;

 input = is\_numeric(input);

 if(input)
 {
 eingabe[i] = input;
 waddch(p\_First, input);
 wrefresh(p\_First);
 i++;
 }
 }
 eingabe[i] = '\0';
 editr\>kosten = \*eingabe;
 i = 0;

 //Nächstes Feld füllen
 wmove(p\_First, line+4, col+20);
 wrefresh(p\_First);
 fflush(stdin);
 while((input = getch()) != 10)
 {
 if(i == 10) break;

 input = is\_numeric(input);

 if(input)
 {
 eingabe[i] = input;
 waddch(p\_First, input);
 wrefresh(p\_First);
 i++;
 }
 }
 eingabe[i] = '\0';
 editr\>tachostand = \*eingabe;
 i = 0;


 //Nächstes Feld füllen
 wmove(p\_First, line+6, col+20);
 wrefresh(p\_First);
 fflush(stdin);
 while((input = getch()) != 10)
 {
 if(i == 8) break;

 input = is\_numeric(input);

 if(input)
 {
 eingabe[i] = input;
 waddch(p\_First, input);
 if(i == 3) waddch(p\_First, '-'); //Trennstriche für das Datum verwenden
 if(i == 5) waddch(p\_First, '-');
 wrefresh(p\_First);
 i++;
 }
 }
 eingabe[i] = '\0';
 editr-\>datum = \*eingabe;
 i = 0;

 return 0;
}

Hallo Alexander !

Mir den ganzen Code anzusehen um irgendwo einen Fehler zu finden ist mir ehrlich gesagt etwas zu mühsam !
Versuch doch mal, genauer einzugrenzen, wo denn der Fehler genau passiert.
Wenn du eine IDE hast, versuchs mal mit dem Debugger.
Ansonsten taste dich eben daran heran, z.B. indem du an verschiedenen Stellen Informationen in eine Datei schreibst (und diese Datei sofort nach jedem schreiben schliesst, damit sie beim Programmabsturz nicht verlorengeht).
Wenn du dann etwas genauer weisst, wo du suchen sollst, gehts einfach leichter :wink:

mfg
Christof