Wie arbeite ich mit String-Feldern in einer C-Struktur?
Lesezeit: 6 Minuten
Fleurazie
Ich habe Probleme, eine Datenbank basierend auf einer einfach verknüpften Liste in C zu erstellen, nicht wegen des Konzepts der verknüpften Liste, sondern wegen der Zeichenfolgenfelder in der Struktur selbst.
Dies ist eine Zuweisung in C und soweit ich weiß (ich bin ein Neuling), erkennt C ‘string’ nicht als Datentyp.
Kann mir jemand helfen, das herauszufinden?
Vielen Dank.
Adam Liss
Zu Strings und Speicherzuweisung:
Ein String in C ist nur eine Folge von chars, damit Sie verwenden können char * oder ein char array, wo immer Sie einen String-Datentyp verwenden möchten:
Dann müssen Sie Speicher für die Struktur selbst und für jede der Zeichenfolgen zuweisen:
patient *createPatient(int number, char *name,
char *addr, char *bd, char sex) {
// Allocate memory for the pointers themselves and other elements
// in the struct.
patient *p = malloc(sizeof(struct patient));
p->number = number; // Scalars (int, char, etc) can simply be copied
// Must allocate memory for contents of pointers. Here, strdup()
// creates a new copy of name. Another option:
// p->name = malloc(strlen(name)+1);
// strcpy(p->name, name);
p->name = strdup(name);
p->address = strdup(addr);
p->birthdate = strdup(bd);
p->gender = sex;
return p;
}
Wenn Sie nur ein paar brauchen patients können Sie die Speicherverwaltung auf Kosten der Zuweisung von mehr Speicher vermeiden, als Sie wirklich benötigen:
typedef struct {
int number;
char name[50]; // Declaring an array will allocate the specified
char address[200]; // amount of memory when the struct is created,
char birthdate[50]; // but pre-determines the max length and may
char gender; // allocate more than you need.
} patient;
Auf verknüpften Listen:
Im Allgemeinen besteht der Zweck einer verknüpften Liste darin, einen schnellen Zugriff auf eine geordnete Sammlung von Elementen zu beweisen. Wenn dein llist enthält ein Element namens num (die vermutlich die Patientennummer enthält), benötigen Sie eine zusätzliche Datenstruktur, um die eigentliche zu halten patients selbst, und Sie müssen jedes Mal die Patientennummer nachschlagen.
dann enthält jedes Element einen direkten Zeiger auf a patient Struktur, und Sie können wie folgt auf die Daten zugreifen:
patient *getPatient(list *patients, int num) {
list *l = patients;
while (l != NULL) {
if (l->p->num == num) {
return l->p;
}
l = l->next;
}
return NULL;
}
ah, im Grunde muss ich den Sting-Typ nicht buchstäblich verwenden und ihn in einen Zeiger ändern, wenn ich ihn als Zeiger von char verwenden möchte. danke das ist wirklich augenöffnend. Aber ich habe hier ein paar Fragen: (a) Sagen wir, ich möchte einen Datensatz für einen neuen Patienten einfügen, muss ich eine neue Funktion wie void insert() erstellen? bin etwas verwirrt mit dem struct patient für die typedef struct oben (b) oder muss ich einen neuen (z. B. einen Knoten) einfügen, der die Patientenstruktur in der Listenstruktur enthält, indem ich beispielsweise einen neuen Knoten in die einfüge aufführen? Ist das verständlich? Vielen Dank.
– Fleurazie
15. April 2012 um 15:45 Uhr
Verkettete Listen sind eine der grundlegenden, universellen Datenstrukturen, die Ihnen gute Dienste leisten werden, sobald Sie sie verstanden haben. Es wäre eine lohnende Investition, eine umfassendere Erklärung zu finden, als Sie hier auf SO erhalten. Viele gute Websites und Bücher sind verfügbar.
– Adam Liss
15. April 2012 um 20:04 Uhr
Pakpoom Tiwakornkit
Ich denke, diese Lösung benötigt weniger Code und ist auch für Neulinge leicht verständlich.
Für Zeichenfolgenfelder in struct können Sie Zeiger verwenden, und die Neuzuweisung der Zeichenfolge zu diesem Zeiger ist direkt und einfacher.
So einfach ist das. Ich hoffe, diese Antwort hilft vielen Entwicklern.
Das hat mir geholfen, die Probleme zu lösen. Ich habe Fehler beim Definieren von Zeichenfolgen wie: struct Student { char name[24]; } student;
– Benutzer8581607
31. Januar 2021 um 9:26 Uhr
patient.gender = ‘M’ wird dort anstelle von “M” stehen, da es char ist. Bitte korrigiere es. Es wird zwar kompiliert, aber das Ergebnis wird nicht wie erwartet sein.
– Kapil
28. April 2021 um 16:22 Uhr
Als Neuling ist diese Antwort sehr hilfreich für mich. Hat es irgendwelche Nachteile im Vergleich zu der (scheinbar komplizierteren) akzeptierten Antwort?
– David
14. Januar um 16:07 Uhr
@Dave Es gibt keine Nachteile bei der Verwendung dieser Methode AFAIK, aber wenn Sie den Codierungsstil der akzeptierten Antwort verstehen können, ist dies ein Plus, da viele Entwickler diesen Stil verwenden.
– Pakpoom Tiwakornkit
19. Januar um 15:44 Uhr
@Kapil Danke für den Hinweis. Die Antwort ist korrigiert.
– Pakpoom Tiwakornkit
19. Januar um 15:47 Uhr
Während Richard’s das ist, was Sie wollen, wenn Sie mit einer Typedef arbeiten möchten, würde ich vorschlagen, dass es in diesem Fall wahrscheinlich keine besonders gute Idee ist, da Sie aus den Augen verlieren, dass es sich um einen Zeiger handelt, während Sie nichts gewinnen.
Wenn Sie es als gezählten String oder etwas mit zusätzlicher Funktionalität behandeln, könnte das anders sein, aber ich würde wirklich empfehlen, dass Sie sich in diesem Fall einfach damit vertraut machen, dass die ‘Standard’-C-String-Implementierung ein ‘char *’ ist. ..
Sie könnten einfach eine noch einfachere verwenden typedef:
typedef char *string;
Dann würde Ihr Malloc wie ein gewöhnliches Malloc aussehen:
string s = malloc(maxStringLength);
Attila
Das funktioniert nicht:
string s = (string)malloc(sizeof string);
string bezieht sich auf einen Zeiger, benötigen Sie die Größe der Struktur selbst:
string s = malloc(sizeof (*string));
Beachten Sie auch das Fehlen von Besetzung (Konvertierung von void* (mallocder Rückgabetyp von ) wird implizit ausgeführt).
Auch in Ihrer mainSie haben eine global deklarierte patient, aber das ist nicht initialisiert. Versuchen:
bevor Sie auf eines seiner Mitglieder lesend zugreifen
Ebenfalls, strcpy ist grundsätzlich unsicher da es keine Grenzüberprüfung gibt (wird bis zum ersten kopiert '\0' gefunden wird, Schreiben über den zugewiesenen Speicher hinaus, wenn die Quelle zu lang ist). Verwenden strncpy Stattdessen, wo Sie zumindest die maximale Anzahl der kopierten Zeichen angeben können – lesen Sie die Dokumentation, um sicherzustellen, dass Sie den richtigen Wert übergeben. Es ist leicht, einen Off-by-One-Fehler zu machen.
Sie sollten nicht typisieren, während Sie malloc verwenden.
– Alok Speichern
15. April 2012 um 12:56 Uhr
Nein. patient ist nicht global deklariert, es ist ein typdef. Aber selbst wenn es global wäre, würden Sie es nicht so initialisieren.
– kralyk
15. April 2012 um 13:04 Uhr
Sie sollten nicht typisieren, während Sie malloc verwenden.
– Alok Speichern
15. April 2012 um 12:56 Uhr
Nein. patient ist nicht global deklariert, es ist ein typdef. Aber selbst wenn es global wäre, würden Sie es nicht so initialisieren.
– kralyk
15. April 2012 um 13:04 Uhr
13655700cookie-checkWie arbeite ich mit String-Feldern in einer C-Struktur?yes