2012-04-15 30 views
13

Tôi đang gặp sự cố khi tạo cơ sở dữ liệu dựa trên danh sách được liên kết đơn lẻ trong C, không phải vì khái niệm danh sách được liên kết mà là các trường chuỗi trong cấu trúc.Làm cách nào để làm việc với các trường chuỗi trong cấu trúc C?

Đây là bài tập trong C và theo như tôi biết (Tôi là người mới), C không nhận ra 'chuỗi' làm loại dữ liệu.

Đây là những gì đang struct của tôi trông giống như:

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

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

Tôi đã nghĩ đến việc thực hiện một struct cho chuỗi mình để tôi có thể sử dụng chúng trong các cấu trúc, như thế này:

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

Sau đó, tôi sẽ malloc() mỗi một trong số họ khi nó được yêu cầu để làm cho dữ liệu mới của loại chuỗi (mảng 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); 
} 

Ai đó có thể giúp tôi tìm ra điều này không?
Cảm ơn bạn.

Trả lời

0

này không hoạt động:

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

string đề cập đến một con trỏ, bạn cần kích thước của cấu trúc bản thân:

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

Note thiếu dàn diễn viên cũng như (chuyển đổi từ void* (Loại trả về của malloc) được thực hiện ngầm).

Ngoài ra, trong số main của mình, bạn có toàn cầu đã bị xóa patient, nhưng điều đó chưa được khởi tạo. Hãy thử:

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

trước khi bạn đọc truy cập bất kỳ của các thành viên

Ngoài ra, strcpy vốn đã không an toàn vì nó không có kiểm tra ranh giới (sẽ sao chép cho đến khi '\0' đầu tiên là gặp phải, viết qua phân bổ bộ nhớ nếu nguồn quá dài). Sử dụng strncpy thay vào đó, nơi bạn ít nhất có thể chỉ định số lượng ký tự tối đa được sao chép - đọc tài liệu để đảm bảo bạn vượt qua giá trị chính xác, thật dễ dàng để thực hiện một lỗi off-by-one.

+0

Bạn [không được nhập] (http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858) trong khi sử dụng malloc. –

+0

Không. 'Bệnh nhân' không được khai báo trên toàn cầu, đó là typdef. Nhưng ngay cả khi nó là toàn cầu, bạn sẽ không khởi tạo nó như thế này. – kralyk

+0

@kralyk - đúng, tôi tự nhận ra và sửa chữa. – Attila

0

Bạn chỉ có thể sử dụng một thậm chí đơn giản hơn typedef:

typedef char *string; 

Sau đó, malloc của bạn sẽ trông giống như một malloc thông thường:

string s = malloc(maxStringLength); 
31

Mở chuỗi và cấp phát bộ nhớ:

Một chuỗi trong C chỉ là một chuỗi gồm char s, vì vậy bạn có thể sử dụng char * hoặc một mảng char bất cứ nơi nào bạn muốn sử dụng một loại chuỗi dữ liệu:

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

Sau đó, bạn cần phải phân bổ bộ nhớ cho cấu trúc chính nó, và cho mỗi chuỗi:

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

Nếu bạn chỉ cần một vài patient s, bạn có thể tránh việc quản lý bộ nhớ tại các chi phí phân bổ bộ nhớ nhiều hơn bạn thực sự cần:

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; 

Trên danh sách được liên kết:

Nói chung, mục đích của danh sách được liên kết là chứng minh quyền truy cập nhanh vào bộ sưu tập các phần tử đã sắp xếp. Nếu llist của bạn có chứa một phần tử được gọi là num (có lẽ có chứa số bệnh nhân), bạn cần cấu trúc dữ liệu bổ sung để tự giữ patient thực tế của chính mình và bạn sẽ cần tra cứu số bệnh nhân mỗi lần.

Thay vào đó, nếu bạn khai báo

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

sau đó mỗi phần tử chứa một con trỏ trực tiếp đến một cấu trúc patient, và bạn có thể truy cập các dữ liệu như thế này:

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 vì vậy về cơ bản tôi không cần phải theo nghĩa đen sử dụng các loại sting và sửa đổi nó thành con trỏ nếu tôi muốn sử dụng nó như một con trỏ của char. cảm ơn bạn điều này thực sự là nhạy cảm. nhưng tôi có một vài câu hỏi ở đây: (a) nói rằng tôi muốn chèn một bản ghi cho một bệnh nhân mới, tôi có phải thực hiện một fuction mới như void chèn()? có một chút nhầm lẫn với cấu trúc bệnh nhân cho typedef struct ở trên (b) hoặc làm tôi phải chèn một mới (nói một nút) sẽ chứa cấu trúc bệnh nhân trong cấu trúc danh sách, bằng cách chèn cho biết, một nút mới để danh sách? là điều này dễ hiểu .. cảm ơn rất nhiều. – fleuracia

+0

Danh sách được liên kết là một trong những cấu trúc dữ liệu cơ bản, có mục đích chung sẽ phục vụ bạn tốt khi bạn hiểu chúng. Nó sẽ là một đầu tư đáng giá để tìm một lời giải thích toàn diện hơn bạn sẽ nhận được ở đây trên SO. Rất nhiều trang web và sách có sẵn. –

1

Trong khi Richard là những gì bạn muốn nếu bạn muốn đi với một typedef, tôi đề nghị rằng nó có lẽ không phải là một ý tưởng đặc biệt tốt trong trường hợp này, như bạn bị mất tầm nhìn của nó là một con trỏ, trong khi không đạt được bất cứ điều gì.

Nếu bạn đang xử lý chuỗi aa hoặc chuỗi có chức năng bổ sung, có thể khác, nhưng tôi thực sự khuyên bạn nên làm quen với việc triển khai chuỗi 'chuẩn' là ' char * '...

Các vấn đề liên quan