fleuracia
Tengo problemas para crear una base de datos basada en una lista de enlaces únicos en C, no por el concepto de lista enlazada sino por los campos de cadena en la estructura en sí.
Esta es una tarea en C y, que yo sepa (soy un novato), C no reconoce ‘cadena’ como un tipo de datos.
Así es como se ve mi código de estructura:
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 propias cadenas para poder usarlas en la estructura, así:
typedef struct string
{
char *text;
} *string;
Lo haré entonces malloc()
cada uno de ellos cuando se requiere realizar nuevos datos del tipo string (array of char).
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);
}
¿Puede alguien ayudarme a resolver esto?
Gracias.
adam liss
En cadenas y asignación de memoria:
Una cadena en C es solo una secuencia de char
s, para que puedas usar char *
o un char
matriz donde quiera usar un tipo de datos de cadena:
typedef struct {
int number;
char *name;
char *address;
char *birthdate;
char gender;
} patient;
Luego, debe 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 solo necesitas unos pocos patient
s, puede evitar la administración de memoria a expensas de asignar 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 listas enlazadas:
En general, el propósito de una lista enlazada es demostrar un acceso rápido a una colección ordenada de elementos. Si tu llist
contiene un elemento llamado num
(que presumiblemente contiene el número de paciente), necesita una estructura de datos adicional para contener el número real patient
s mismos, y tendrá que buscar el número de paciente cada vez.
En cambio, si declaras
typedef struct llist
{
patient *p;
struct llist *next;
} list;
entonces cada elemento contiene un puntero directo a un patient
estructura, y puede acceder a los datos de esta 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;
}
-
ah, básicamente, no necesito usar literalmente el tipo de picadura y modificarlo en un puntero si quiero usarlo como un puntero de char. gracias esto es realmente revelador. pero tengo un par de preguntas aquí: (a) digamos que quiero insertar un registro para un nuevo paciente, ¿tengo que hacer una nueva función como void insert()? me confundí un poco con la estructura del paciente para la estructura typedef anterior (b) o tengo que insertar una nueva (por ejemplo, un nodo) que contendrá la estructura del paciente en la estructura de la lista, insertando, digamos, un nuevo nodo en la ¿lista? es esto comprensible .. muchas gracias .
– fleuracia
15/04/2012 a las 15:45
-
Las listas vinculadas son una de las estructuras de datos fundamentales de propósito general que le serán de utilidad una vez que las comprenda. Sería una inversión valiosa encontrar una explicación más completa de la que obtendrá aquí en SO. Hay muchos buenos sitios web y libros disponibles.
– Adam Liss
15 de abril de 2012 a las 20:04
Kit Pakpoom Tiwakorn
Creo que esta solución usa menos código y es fácil de entender incluso para los novatos.
Para el campo de cadena en la estructura, puede usar el puntero y reasignar la cadena a ese puntero será directo y más simple.
Definir definición de estructura:
typedef struct {
int number;
char *name;
char *address;
char *birthdate;
char gender;
} Patient;
Inicialice la variable con el tipo de esa estructura:
Patient patient;
patient.number = 12345;
patient.address = "123/123 some road Rd.";
patient.birthdate = "2020/12/12";
patient.gender="M";
Es así de simple. Espero que esta respuesta ayude a muchos desarrolladores.
-
Esto me ayudó a resolver los problemas. Recibía errores al definir cadenas como:
struct Student { char name[24]; } student;
– usuario8581607
31 de enero de 2021 a las 9:26
-
paciente.género = ‘M’ estará allí en lugar de “M” como es char. Por favor, corríjalo. Aunque compilará, pero el resultado no será el esperado.
– Kapil
28 de abril de 2021 a las 16:22
-
Como novato, esta respuesta es muy útil para mí. ¿Tiene algún inconveniente en comparación con la respuesta aceptada (aparentemente más complicada)?
– Dave
14 de enero a las 16:07
-
@Dave No hay inconvenientes al usar este método AFAIK, pero si puede comprender el estilo de codificación de la respuesta aceptada, entonces es una ventaja, ya que hay muchos desarrolladores que usan ese estilo.
– Pakpoom Tiwakornkit
19 de enero a las 15:44
-
@Kapil Gracias por señalarlo. Se corrige la respuesta.
– Pakpoom Tiwakornkit
19 de enero a las 15:47
Mientras que Richard’s es lo que quieres si quieres ir con un typedef, sugeriría que probablemente no sea una idea particularmente buena en este caso, ya que pierdes de vista que es un puntero, sin ganar nada.
Si lo estuviera tratando como una cadena contada, o algo con funcionalidad adicional, eso podría ser diferente, pero realmente recomendaría que en este caso, simplemente se familiarice con la implementación de la cadena C ‘estándar’ que es un ‘char *’. ..
Podrías usar una aún más simple typedef
:
typedef char *string;
Entonces, su malloc se vería como un malloc habitual:
string s = malloc(maxStringLength);
atila
Esto no funciona:
string s = (string)malloc(sizeof string);
string
se refiere a un puntero, necesita el tamaño de la estructura en sí:
string s = malloc(sizeof (*string));
Tenga en cuenta la falta de reparto también (conversión de void*
(malloc
tipo de retorno) se realiza implícitamente).
También, en tu main
tienes un certificado global patient
, pero eso no está inicializado. Probar:
patient.number = 3;
patient.name = "John";
patient.address = "Baker street";
patient.birthdate = "4/15/2012";
patient.gender="M";
antes de acceder a cualquiera de sus miembros
También, strcpy
es intrínsecamente inseguro ya que no tiene verificación de límites (se copiará hasta el primer '\0'
se encuentra, escribiendo más allá de la memoria asignada si la fuente es demasiado larga). Usar strncpy
en cambio, donde al menos puede especificar la cantidad máxima de caracteres copiados; lea la documentación para asegurarse de pasar el valor correcto, es fácil cometer un error de uno.
-
No debe encasillar mientras usa malloc.
– Alok Guardar
15 de abril de 2012 a las 12:56
-
No.
patient
no está declarado globalmente, es un typdef. Pero incluso si fuera global, no lo inicializaría así.– Kralyk
15 de abril de 2012 a las 13:04
-
No debe encasillar mientras usa malloc.
– Alok Guardar
15 de abril de 2012 a las 12:56
-
No.
patient
no está declarado globalmente, es un typdef. Pero incluso si fuera global, no lo inicializaría así.– Kralyk
15 de abril de 2012 a las 13:04