web-dev-qa-db-fra.com

Comment travailler avec des champs de chaîne dans une structure C?

J'ai du mal à créer une base de données basée sur une liste à liaison unique en C, non pas à cause du concept de liste liée, mais plutôt des champs de chaîne dans la structure eux-mêmes.

Il s'agit d'une affectation en C et pour autant que je sache (je suis un débutant), C ne reconnaît pas "chaîne" comme type de données.

Voici à quoi ressemble mon code struct:

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

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

Je pensais créer une structure pour les chaînes elles-mêmes afin de pouvoir les utiliser dans la structure, comme ceci:

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

Ensuite, je vais malloc() chacun d'eux quand il est nécessaire de faire de nouvelles données du type chaîne (tableau de caractères).

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

Quelqu'un peut m'aider à trouver la solution?
Je vous remercie.

15
fleuracia

Sur les chaînes et l'allocation de mémoire:

Une chaîne en C n'est qu'une séquence de chars, vous pouvez donc utiliser char * ou un tableau char partout où vous souhaitez utiliser un type de données chaîne:

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

Ensuite, vous devez allouer de la mémoire à la structure elle-même et à chacune des chaînes:

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

Si vous n'avez besoin que de quelques patients, vous pouvez éviter la gestion de la mémoire aux dépens d'allouer plus de mémoire que vous n'en avez vraiment besoin:

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;

Sur les listes chaînées:

En général, le but d'une liste chaînée est de prouver un accès rapide à une collection ordonnée d'éléments. Si votre llist contient un élément appelé num (qui contient vraisemblablement le numéro du patient), vous avez besoin d'une structure de données supplémentaire pour contenir les patients réels eux-mêmes, et vous aurez besoin pour rechercher le numéro du patient à chaque fois.

Au lieu de cela, si vous déclarez

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

alors chaque élément contient un pointeur direct vers une structure patient, et vous pouvez accéder aux données comme ceci:

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;
}
37
Adam Liss

Bien que Richard soit ce que vous voulez si vous voulez utiliser un typedef, je suggère que ce n'est probablement pas une bonne idée dans ce cas, car vous perdez de vue qu'il s'agit d'un pointeur, sans rien gagner.

Si vous la traitiez comme une chaîne comptée, ou quelque chose avec des fonctionnalités supplémentaires, cela pourrait être différent, mais je recommanderais vraiment que dans ce cas, vous vous familiarisiez simplement avec l'implémentation de chaîne C `` standard '' étant un `` char * ''. ..

1
Gwyn Evans

Cela ne fonctionne pas:

string s = (string)malloc(sizeof string); 

string fait référence à un pointeur, vous avez besoin de la taille de la structure elle-même:

string s = malloc(sizeof (*string)); 

Notez également le manque de cast (conversion de void* (le type de retour de malloc) est implicitement effectué).

De plus, dans votre main, vous avez un patient globalement supprimé, mais qui n'est pas initialisé. Essayer:

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

avant d'accéder en lecture à l'un de ses membres

En outre, strcpy est intrinsèquement dangereux car il n'a pas de vérification des limites (copiera jusqu'au premier '\0' est rencontré, écrivant au-delà de la mémoire allouée si la source est trop longue). Utilisez strncpy à la place, où vous pouvez au moins spécifier le nombre maximum de caractères copiés - lisez la documentation pour vous assurer de passer la valeur correcte, il est facile de faire une erreur de coup par coup.

0
Attila

Vous pouvez simplement utiliser un typedef encore plus simple:

typedef char *string;

Ensuite, votre malloc ressemblerait à un malloc habituel:

string s = malloc(maxStringLength);
0