2012-04-15 16 views
13

Tengo problemas para crear una base de datos basada en una lista enlazada individualmente en C, no por el concepto de lista enlazada sino por los campos de cadena en la propia estructura.¿Cómo trabajar con campos de cadenas en una estructura C?

Esta es una tarea en C y hasta donde yo sé (soy novato), C no reconoce 'cadena' como un tipo de datos.

Esto es lo que se ve mi código struct como:

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

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

Estaba pensando en hacer una estructura para las cadenas de sí mismos para que pueda utilizarlos en la estructura, como esto:

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

Luego voy a malloc() cada uno de ellos cuando sea necesario para hacer nuevos datos del tipo de cadena (matriz de caracteres).

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

¿Alguien me puede ayudar a resolver esto?
Gracias.

Respuesta

0

Esto no funciona:

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

string hace referencia a un puntero, necesita el tamaño de la propia estructura:

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

nota la falta de fundición, así (conversión de void* (malloc tipo de devolución) se realiza implícitamente).

Además, en su main, tiene un contenedor global patient, pero no está inicializado. Proveedores:

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

antes de leer de acceso a cualquiera de sus miembros

Además, strcpy es inherentemente insegura, ya que no tiene comprobación de límites (copiará hasta la primera '\0' se encuentra, escribiendo pasado asignada memoria si la fuente es demasiado larga). Use strncpy en su lugar, donde puede al menos especificar la cantidad máxima de caracteres copiados: lea la documentación para asegurarse de que pasa el valor correcto, es fácil hacer un error de uno por uno.

+0

Usted [no debe escribir a máquina] (http://stackoverflow.com/questions/605845/doi-i-cast-the-result-of-malloc/605858#605858) mientras usa malloc. –

+0

No. 'patient' no está declarado globalmente, es un typdef. Pero incluso si fuera global, no lo inicializaría así. – kralyk

+0

@kralyk - correcto, me di cuenta y me corrigieron. – Attila

0

Se podía usar un aún más simple typedef:

typedef char *string; 

Entonces, su malloc se vería como un malloc habitual:

string s = malloc(maxStringLength); 
31

En cuerdas y la asignación de memoria:

Una cadena en C es solo una secuencia de char s, por lo que puede usar char * o una matriz char donde quiera que desee utilizar un tipo de datos de cadena:

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

Luego hay que asignar memoria para la estructura en sí, y para cada una de las cadenas:

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 usted sólo necesitará un par de patient s, se puede evitar la administración de memoria, a expensas de la asignación de más memoria de la que realmente necesita:

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; 

En las listas vinculadas:

En general, el propósito de una lista vinculada es comprobar el acceso rápido a una colección ordenada de elementos. Si su llist contiene un elemento llamado num (que presumiblemente contiene el número de paciente), necesita una estructura de datos adicional para contener los mismos patient s, y deberá buscar el número del paciente cada vez.

En cambio, si se declara

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

entonces cada elemento contiene un puntero directo a una estructura patient, y se puede acceder a los datos de la siguiente manera:

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

ah, así que básicamente no necesito literalmente usar el tipo de picadura y modificarlo en el puntero si quiero usarlo como un puntero de char. gracias, esto es realmente asombroso. pero tengo un par de preguntas aquí: (a) digo que quiero insertar un registro para un nuevo paciente, ¿tengo que hacer una nueva función como inserción vacía()? se confundió un poco con el paciente struct para la estructura typedef anterior (b) o tengo que insertar un nuevo (digamos un nodo) que contendrá la estructura del paciente en la estructura de la lista, insertando digamos, digamos, un nuevo nodo al ¿lista? es comprensible ... muchas gracias. – fleuracia

+0

Las listas vinculadas son una de las estructuras de datos fundamentales y de propósito general que te servirán bien una vez que las entiendas. Sería una inversión que vale la pena buscar una explicación más completa de la que obtendrás aquí en SO. Hay muchos buenos sitios web y libros disponibles. –

1

Mientras que Richard es lo que quiere si quieres ir con un typedef, te sugiero que probablemente no sea una buena idea en este caso, ya que lo pierdes de vista y no ganas nada.

Si estuviera tratando una cadena contada, o algo con funcionalidad adicional, eso podría ser diferente, pero realmente recomiendo que en este caso, se familiarice con la implementación 'estándar' de cadena C siendo un ' char * '...

Cuestiones relacionadas