Wie arbeite ich mit String-Feldern in einer C-Struktur?

Lesezeit: 6 Minuten

Benutzer-Avatar
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.

So sieht mein Struct-Code aus:

typedef struct 
{
  int number;
  string name;
  string address;
  string birthdate;
  char gender;
} patient;

typedef struct llist
{
  patient num;
  struct llist *next;
} list;

Ich habe darüber nachgedacht, eine Struktur für die Zeichenfolgen selbst zu erstellen, damit ich sie in der Struktur verwenden kann, wie folgt:

typedef struct string 
{ 
  char *text;
} *string;

Dann werde ich malloc() jeder von ihnen, wenn es erforderlich ist, neue Daten des String-Typs (Array of Char) zu erstellen.

typedef struct string
{
  char *text;
} *string;

int main()
{
    int length = 50;
    string s = (string) malloc(sizeof string);
    s->text = (char *) malloc(len * sizeof char);
    strcpy(s->text, patient.name->text);
}

Kann mir jemand helfen, das herauszufinden?
Vielen Dank.

Benutzer-Avatar
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:

typedef struct     {
  int number;
  char *name;
  char *address;
  char *birthdate;
  char gender;
} patient;

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.

Stattdessen, wenn Sie erklären

typedef struct llist
{
  patient *p;
  struct llist *next;
} list;

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

Benutzer-Avatar
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.

Definition der Struktur definieren:

typedef struct {
  int number;
  char *name;
  char *address;
  char *birthdate;
  char gender;
} Patient;

Variable mit dem Typ dieser Struktur initialisieren:

Patient patient;
patient.number = 12345;
patient.address = "123/123 some road Rd.";
patient.birthdate = "2020/12/12";
patient.gender="M";

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);

Benutzer-Avatar
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:

 patient.number = 3;     
 patient.name = "John";     
 patient.address = "Baker street";     
 patient.birthdate = "4/15/2012";     
 patient.gender="M";     

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


1365570cookie-checkWie arbeite ich mit String-Feldern in einer C-Struktur?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy