2012-04-15 10 views
13

Mam problem z utworzeniem bazy danych opartej na pojedynczo połączonej liście w C, nie z powodu połączonej koncepcji listy, ale raczej z polami łańcuchów w samej strukturze.Jak pracować z polami łańcuchowymi w strukturze C?

To jest zadanie w C i o ile wiem (jestem nowicjuszem), C nie rozpoznaje "łańcucha" jako typu danych.

To właśnie mój kod struktura wygląda następująco:

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

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

Myślałam dokonywania struct dla strun się tak, że można używać ich w struktury, tak:

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

Potem będę musiał wykonać każdą z nich, gdy wymagane jest utworzenie nowych danych typu string (tablica znaków).

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

Czy ktoś może mi pomóc rozwiązać ten problem?
Dziękuję.

Odpowiedz

0

To nie działa:

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

string odnosi się do wskaźnika, trzeba rozmiaru struktury samego:

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

Note brak obsady, jak również (konwersja z void* (malloc) jest wykonywany niejawnie).

Ponadto w Twoim main masz globalnie ubrudzony patient, ale to nie jest inicjowane. Spróbuj:

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

przed odczytu dostępu któregokolwiek z jej członków

Również strcpy jest z natury niebezpieczne gdyż nie ma kontroli granicznej (skopiujesz do pierwszego '\0' napotkano, pisanie przeszłość przydzielane pamięć, jeśli źródło jest za długie). Zamiast tego należy użyć strncpy, gdzie można przynajmniej określić maksymalną liczbę skopiowanych znaków - należy przeczytać dokumentację, aby upewnić się, że przekazano poprawną wartość, łatwo jest popełnić błąd "jeden po drugim".

+0

Ty [nie powinieneś typować] (http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858) używając malloc. –

+0

Nie "pacjent" nie jest globalnie zadeklarowany, jest to typdef. Ale nawet jeśli byłby globalny, nie zainicjowałbyś go w ten sposób. – kralyk

+0

@kralyk - poprawne, sam to sobie uświadomiłem i poprawiłem. – Attila

0

mógłby po prostu użyć jeszcze prostsze typedef:

typedef char *string; 

Następnie Twój malloc będzie wyglądał jak zwykły malloc:

string s = malloc(maxStringLength); 
31

Na strunach i alokacji pamięci:

Ciąg w C jest po prostu sekwencją char s, więc możesz użyć char * lub char tablica gdziekolwiek chcesz użyć typu danych Ciąg:

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

Następnie trzeba przydzielić pamięci dla samej struktury, a dla każdego z ciągów:

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

Jeśli będziesz tylko potrzebuję kilku patient s, można uniknąć zarządzanie pamięcią kosztem przydzielenie większej ilości pamięci niż naprawdę potrzebujesz:

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; 

Na listach połączonych:

Ogólnie celem listy połączonej jest wykazanie szybkiego dostępu do uporządkowanego zbioru elementów. Jeśli Twój llist zawiera element o nazwie num (który prawdopodobnie zawiera numer pacjenta), potrzebujesz dodatkowej struktury danych do przechowywania samych samych patient, a za każdym razem będziesz musiał sprawdzać numer pacjenta.

Zamiast tego, jeśli deklarują

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

następnie każdy element zawiera bezpośredni odnośnik do patient struktury, można uzyskać dostęp do danych tak:

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 tak naprawdę nie muszę dosłownie użyć typu żądło i zmodyfikuj go do wskaźnika, jeśli chcę go użyć jako wskaźnik char. dziękuję, to naprawdę wygląda. ale mam kilka pytań tutaj: (a) powiedzieć, że chcę wstawić rekord dla nowego pacjenta, czy muszę zrobić nową funkcję jak void insert()? trochę się pomyliłem z obiektem struktury dla powyższej struktury (b) lub czy muszę wstawić nowy (powiedzmy węzeł), który będzie zawierał strukturę pacjenta w strukturze listy, wstawiając powiedzmy, nowy węzeł do lista? jest to zrozumiałe ... wielkie dzięki. – fleuracia

+0

Listy połączone są jedną z podstawowych struktur danych ogólnego przeznaczenia, które będą Ci dobrze służyć, gdy je zrozumiesz. Byłoby warto zainwestować, aby znaleźć bardziej wyczerpujące wyjaśnienie, niż dostaniesz tutaj na SO. Dostępnych jest wiele dobrych stron internetowych i książek. –

1

Podczas gdy Richard jest to, co chcesz jeśli chcesz iść z typedef, sugerowałbym, że nie jest to szczególnie dobry pomysł w tym przypadku, ponieważ tracisz z oczu to, że jest wskaźnikiem, a nie zyskujesz nic.

Jeśli potraktowałeś go jako łańcuch zliczany lub coś z dodatkowymi funkcjami, to może być inaczej, ale naprawdę poleciłbym, aby w tym przypadku po prostu zapoznał się ze "standardową" implementacją łańcuchów C będącą ". char * '...