strukturen
-
guten Abend,
ich habe in c folgendes Problem und würde mich über eine Lösung freuen.
Bei der Ausführung meines test Programmes gibt es bei der Ausgabe folgenden Fehler
"Segmentation fault"
nun verstehe ich nicht warum.
schonmal vielen dank im voraus!lg mario
PS: sorry das sollte eigentlich zu ansi c gehören
#include <stdio.h>
#include <stdlib.h>struct daten
{
char *name;
int anzahl;
};void eingabe( struct daten *db );
void ausgabe( struct daten *db );int main()
{
struct daten db;eingabe( &db );
ausgabe( &db );return 0;
}void eingabe( struct daten *db )
{
int anzahl;printf( "Eingabe des Namens: \n" );
scanf( "%s", db->name );
printf( "Eingabe des alter: \n" );
scanf( "%i", &anzahl );db->anzahl = anzahl;
return;
}void ausgabe( struct daten *db )
{printf( "Name = %s\n", db->name );
printf( "Anzahl = %i\n", db->anzahl );return;
}
-
Benutze nächstes Mal bitte [cpp]-Tags (erste weisse Schaltfläche unter dem Textfeld).
Für die Membervariable
name
reservierst du keinen Speicher. Der Zeiger wird nicht initialisiert, und wennscanf()
versucht, in dessen Speicherbereich zu schreiben, kommt es zu undefiniertem Verhalten (in deinem Fall zu einem Segmentation Fault).Für den Anfang würde ich dir raten, ein Array mit fixer Grösse anzugeben, welche sicher kein Name übersteigt.
struct daten { char name[20]; int anzahl; };
Alternative: Du arbeitest mit
malloc()
undfree()
, um dynamisch Speicher zu beschaffen und wieder freizugeben.
-
Dieser Thread wurde von Moderator/in volkard aus dem Forum C++ in das Forum ANSI C verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
vielen dank für deine Antwort,
ich habe es geändert und würde gerne wissen, wie ich den folgenden Ausdruck
verbessern könntevoid eingabe( struct daten *db )
{
...
scanf( "%i", &anzahl );db->anzahl = anzahl;
...
}
scanf erwartet ja eine adresse auf dem Speicher meiner Variablen anzahl.
Da ich meiner Funktion bzw. Procedure (da keine rückgabe wert besteht)
die Adresse meiner Struktur übergebe, müsste ich doch einfach folgendes schreiben können:
...
scanf( "%i", db.anzahl );
...
dies funktioniert leider aber nicht.mein vollständiger code ist wie folgt:
lg mario
#include <stdio.h>
#include <stdlib.h>#define MAX 10
struct daten
{
char *name;
int anzahl;};
void eingabe( struct daten *db );
void ausgabe( struct daten *db );int main()
{
struct daten db;eingabe( &db );
ausgabe( &db );return 0;
}void eingabe( struct daten *db )
{
int anzahl;db->name = (char
malloc( sizeof( MAX ) );
printf( "Eingabe des Namens: \n" );
scanf( "%s", db->name );
printf( "Eingabe des alter: \n" );
scanf( "%i", &anzahl );db->anzahl = anzahl;
return;
}void ausgabe( struct daten *db )
{printf( "Name = %s\n", db->name );
printf( "Anzahl = %i\n", db->anzahl );return;
}
-
Hi,
mario876 schrieb:
vielen dank für deine Antwort,
ich habe es geändert und würde gerne wissen, wie ich den folgenden Ausdruck
verbessern könntevoid eingabe( struct daten *db )
{
...
scanf( "%i", &anzahl );db->anzahl = anzahl;
...
}Kannst du so schreiben:
scanf( "%i", &db->anzahl );
Gruß,
B.B.
-
vielen dank für deine Antwort!
mir sind einige Dinge unklar und ich habe meine Gedankengänge einfach mal als
Kommentar dazu geschrieben.
Mit diesem Programm versuche ich, Zugriffe auf Strukturen zu üben und zu verstehen.Ich würde mich um Hilfe sehr freuen und bin jedem Helfenden sehr dankbar!
Es wäre sehr nett wenn ihr euch mein Programm mal anschaut und die Kommentare auf Korrektheit prüft. Außerdem funktioniert es nicht, denn es kommt wieder mal ein "Segmentation fault".
Das Programm hat so noch kein Sinn daher bitte ich euch um Nachsicht.
Ich möchte es schritt für schritt verbessern und euch um Rat fragen bei Ungereimtheiten.
Schonmal vielen Dank im Vorfeld![cpp] #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXFELD 30 struct person { char *name; int alter; }; struct daten { struct person *mitarbeiter; struct person *next; struct person tmp; int anzahl; }; // eingabe von daten wie name alter void input( struct daten *db ) { int alter; if ( db->next == NULL ) { printf( "Eingabe des Namens: " ); // ich übergebe der funktion die Adresse meiner Struktur db // daher muss ich jetzt erstmal mit db->tmp auf den inhalt zeigen // da scanf eine adresse der zu speichernden variable benötigt // belasse ich es so denn in name ist eine adresse ( ist ein Zeiger ) scanf( "%s", db->tmp.name ); // jetzt versuche ich mit malloc genau so viel Speicher zu reservieren wie ich brauche // ich reserviere so viele bytes wie die länge meines eingegebenen wortes // + 1 da das \0 (null zeichen) einen string abschließt db->mitarbeiter->name = (char *) malloc( strlen( db->tmp.name) + 1 ); // strcpy brauch zwei Zeiger rechts von wo nach wo (links) // da ich ja die adresse von db übergebe muss ich ja zu erst dies auflösen und db->mitarbeiter schreiben // damit ich nicht die adresse der adresse habe also ein pointer auf pointer // da mitarbeiter auch ein Zeiger ist muss ich nun mitarbeiter->name schreiben damit ich nun den Zeiger von name habe // sonst wäre es ja wieder ein pointer auf pointer strcpy( db->mitarbeiter->name, db->tmp.name ); // jetzt übergebe ich meine adresse von name für die ausgabe printf("%s", db->mitarbeiter->name); // da ich nicht verstehe wie ich das alter direkt ohne umgehung einer extra variable in meine struktur schreibe // habe ich dies halt so geschrieben // wie mache ich das anders printf( "\nEingabe des alters: " ); scanf( "%i", &alter ); // &(*db).anzahl db->mitarbeiter->alter = alter; // nur damit ich weiß wie ich folgendes anspreche: // hier versuche ich für den mitarbeiter.name speicher zu resavieren // db->mitarbeiter->name = (char *) malloc( MAXFELD ); // und hier sage ich die adresse des mitarbeiters die ich zuvor angefordert habe übergebe ich an db.next //db->next = db->mitarbeiter; // hier möchte ich die derzeitige Adresse an db.next von db.tmp die ich zuvor in der main angefordert habe an next übergeben // &db->tmp : db->tmp damit habe ich wieder den Inhalt von tmp // die Adresse die ich übergeben habe (&db) wird dadurch aufgelöst // da ich aber die Adresse von tmp haben möchte sage ich &db->tmp db->next = &db->tmp; db->anzahl++; return; } printf("Test\n"); db->anzahl++; return; } // ausgabe von daten wie name alter void output( struct daten *db ) { printf( "Name: %s, anzahl: %i\n", db->mitarbeiter->name, db->anzahl ); return; } int main() { struct daten db; db.tmp.name = (char *) malloc( MAXFELD ); db.next = NULL; db.anzahl = 0; do { input( &db ); output( &db ); printf("außen\n"); } while ( db.anzahl < 5 ); return 0; } [/cpp]
-
Gewöhne dir an einen Debugger zu benutzen.
^Program received signal SIGSEGV, Segmentation fault.
0x00401322 in input (db=0x22ff30) at test.c:39
39 db->mitarbeiter->name = (charmalloc( strlen( db->tmp.name) + 1 );
(gdb) p db
$1 = (struct daten0x22ff30
(gdb) p db->mitarbeiter
$2 = (struct person0x77c04e42
(gdb) p db->tmp
$3 = {name = 0x3f2558 "test", alter = 4200470}
(gdb) p db->tmp.name
$4 = 0x3f2558 "test"
(gdb) p db->mitarbeiter->name
$5 = 0xc01bd8f7 " 2╝"^Immerhin sagt er dir welche Zeile falsch ist. Mit ein bisschen Überlegen kommst du dann darauf dass deine Struktur db->mitarbeiter ins Nirvana zeigt. Du musst sowas einbauen:
db->mitarbeiter = struct person *malloc(sizeof(struct person));
Edit: Vermeide Dinge wie MAXFELD, NAMELEN_MAX und generell alles nach dem Muster buffer[wirdschonreichen]. Es ist wie goto, total praktisch aber unkontrollierbar und zeugt von Faulheit des Programmierers. Und wenn du unbedingt sowas benutzen musst kommentiere wieso MAXFELD ausgerechnet 30 ist und nicht 29 und nicht 31 und unter welchen Voraussetzungen es funktioniert und wann man den Wert anpassen muss.
-
Willst du eine verkettete Liste programmieren? Pack doch den Zeiger, der die Strukturen verkettet,
vorzugsweise in die Struktur mit rein. Den Puffer für die Eingabe als Struktur einzubetten ist
unpraktisch, schreib die Puffer lieber als Variable in die Eingabefunktion und übernimm diese in die Struktur, nachdem sie geprüft sind. Der Aufbau sieht dann
so aus:#include <stdio.h> #define NAMELEN_MAX 30 struct Person { char* name; char* next; int alter; }; struct Daten { struct Person* first; // Speichert den Zeiger auf den Anfang der Liste. int anzahl; }; void input ( struct Daten* pd ) { char buf[NAMELEN_MAX+1]={0}; int alter=0; // ... return 0; } int main() { struct Daten daten ={0}; input ( &daten ); return 0; }