Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 8 của 8
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Cần giúp về danh sách liên kết lồng nhau...

    Mình có đoạn code như sau:

    Mã:
    #include <iostream>#include <conio.h>using namespace std;  //XÂY DỰNG CÁC CẤU TRÚC DANH SÁCH KHÁCH HÀNG //Cấu trúc khách hàngstruct khach_hang{    char c_phase[25];    char c_name[30];    char c_code[11];    char c_address[80];    int c_kwh;}; //Cấu trúc một node trong danh sách khách hàngtypedef struct c_node ptr_client;struct c_node{    khach_hang client;    ptr_client *next;}; //Cấu trúc danh sách khách hàngtypedef struct c_ds ptr_ds;struct c_ds{    int c_numnode;    ptr_client *c_head, *c_tail;}; //XÂY DỰNG CẤU TRÚC DANH SÁCH NHÂN VIÊN //Cấu trúc nhân viênstruct nhan_vien{    char e_code[11];    char e_name[30];    char e_start[10];    ptr_ds c_list;}; //Cấu trúc một node trong danh sách nhân viêntypedef struct e_node ptr_employee;struct e_node{    nhan_vien employee;    ptr_employee *next;}; //Cấu trúc danh sách nhân viêntypedef struct e_ds ptr_list;struct e_ds{    int e_numnode;    ptr_employee *e_head, *e_tail;}; //FUNCTION//Hàm khởi tạo danh sách khách hàngvoid initialize_client_list(ptr_list *list){    list->e_head->employee.c_list.c_head=NULL;    list->e_head->employee.c_list.c_tail=NULL;    list->e_head->employee.c_list.c_numnode=0;}//Hàm khởi tạo danh sách nhân viênvoid initialize_employee_list (ptr_list *list){    list->e_numnode=0;                                  //-------------------------------//    list->e_head=NULL;                                  //  Khởi tạo danh sách nhân viên //    list->e_tail=NULL;                                  //-------------------------------//}//Hàm con dùng để nhập danh sách khách hàng của mỗi nhân viênvoid input_client (ptr_list *list){    char c_select[1];    int temp=1;    do    {        ptr_client *c_newnode = new ptr_client;             //Tạo 1 node mới để chứa thông tin khách hàng        //Gắn node c_newnode vào danh sách        if (list->e_head->employee.c_list.c_numnode>0)        {            list->e_head->employee.c_list.c_tail->next=c_newnode;       //Chèn vào sau node cuối            list->e_head->employee.c_list.c_tail=c_newnode;             //Cập nhật lại node cuối        }        else        {            c_newnode->next=list->e_head->employee.c_list.c_head;            list->e_head->employee.c_list.c_head=c_newnode;            list->e_head->employee.c_list.c_tail=c_newnode;        }        cin.ignore(1);        cout<<"    "<<temp<<". Ten khach hang: ";        cin.getline(c_newnode->client.c_name,30);        cout<<"       Ma khach hang: ";        cin>>c_newnode->client.c_code;        cout<<"       So kw tieu thu: ";        cin>>c_newnode->client.c_kwh;        cin.ignore(1);        cout<<"       Ky thu: ";        cin.getline(c_newnode->client.c_phase,25);        cout<<"       Dia chi: ";        cin.getline(c_newnode->client.c_address,80);        cout<<"
           Nhap them khach hang? [Y/N]: ";        cin>>c_select[0];        temp++;        list->e_head->employee.c_list.c_numnode++;    }while((c_select[0]=='Y')||(c_select[0]=='y'));}//Hàm nhập nhân viên và khách hàng (khi mới chạy chương trình lần đầu)void input_employee (ptr_list *list){    char e_select[1];    do{        ptr_employee *e_newnode = new ptr_employee; //Tạo 1 node mới để chứa thông tin nhân viên        //Gắn node e_newnode vào danh sách        if (list->e_numnode>0)                      //Nếu trong danh sách đã có ít nhất 1 node        {            list->e_tail->next=e_newnode;           //Chèn vào sau node cuối            list->e_tail=e_newnode;                 //Cập nhật lại node cuối        }        else                                        //Nếu danh sách chưa có node nào        {            e_newnode->next=list->e_head;            list->e_head=e_newnode;            list->e_tail=e_newnode;        }        initialize_client_list(list);               //Khởi tạo danh sách khách hàng của nhân viên hiện tại        cout<<"
     --------------------------------------------
    ";        cout<<" Ten nhan vien: ";        cin.ignore(1);        cin.getline(e_newnode->employee.e_name,30);        cout<<" Ma nhan vien: ";        cin>>e_newnode->employee.e_code;        cout<<" Ngay bat dau lam [dd/mm/yy]: ";        cin>>e_newnode->employee.e_start;        cout<<" Chiu trach nhiem thu tien nhung khach hang: 
    ";        input_client (list);        cout<<"
           Nhap them nhan vien? [Y/N]: ";        cin>>e_select[0];        list->e_numnode++;    }while ((e_select[0]=='Y')||(e_select[0]=='y'));}  //------------------------------------------------------------------// void main (){    ptr_list *list;    list = new ptr_list;    initialize_employee_list (list);    cout<<"
    \t\t   CHUONG TRINH QUAN LY THONG TIN CONG TY DIEN LUC
    
    
    ";    cout<<" Day la lan dau chay chuong trinh. Nhan phim Enter de bat dau nhap thong tin...
    ";    getch();    system("cls");    cout<<"
    \t\t   CHUONG TRINH QUAN LY THONG TIN CONG TY DIEN LUC
    
    
    ";    input_employee(list);      //cout<<"
    ten khach hang thu nhat cua nhan vien thu nhat: "<<list->e_head->employee.c_list.c_head->client.c_name;              //cout<<"
    So khach hang cua nhan vien thu nhat: "<<list->e_head->employee.c_list.c_numnode;                //cout<<"
    Ten khach hang thu 2 cua nhan vien thu nhat: "<<list->e_head->employee.c_list.c_head->next->client.c_name;           //cout<<"
    Ten nhan vien thu 2: "<<list->e_head->next->employee.e_name;     //cout<<"
    So khach hang cua nhan vien thu 2: "<<list->e_head->next->employee.c_list.c_numnode;*/    }
    Chương trình mình đặt tên theo kiểu c_ và e_ (c là client, e là employee)...
    Mình muốn tạo danh sách khách hàng trong mỗi node nhân viên. Khi chạy chuơng trình lần đầu thì người dùng nhập nhân viên, rồi nhập các khách hàng của nhân viên đó, sau đó chuyển sang nhân viên thứ 2...
    Mình code và thử xuất 1 số thông tin (trong phần in đậm - code) thì thông tin của nhân viên thứ 2 bị đè lên nhân viên thứ nhất. Minh chưa hiểu bị sai chỗ nào. Mong các bạn chỉ dùm... Cám ơn đã đọc bài.

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Mã:
    //Hàm con dùng để nhập danh sách khách hàng của mỗi nhân viênvoid input_client (ptr_list *list)
    Nhập danh sách khách hàng cho nhân viên thì tham số phải là e_node để nhập danh sách cho node này chứ
    Sao lại nhập cho cả list nhân viên luôn

    Đến khi nhập thôn tin cho nhân viên, sau khi nhập họ tên xong
    Nhập danh sách khách hàng cho nhân viên đó thì gọi
    input_client(e_newnode) chứ

  3. #3
    Ngày tham gia
    Sep 2015
    Đang ở
    hà nội
    Bài viết
    0
    Trích dẫn Gửi bởi clchicken
    Mã:
    //Hàm con dùng để nhập danh sách khách hàng của mỗi nhân viênvoid input_client (ptr_list *list)
    Nhập danh sách khách hàng cho nhân viên thì tham số phải là e_node để nhập danh sách cho node này chứ
    Sao lại nhập cho cả list nhân viên luôn

    Đến khi nhập thôn tin cho nhân viên, sau khi nhập họ tên xong
    Nhập danh sách khách hàng cho nhân viên đó thì gọi
    input_client(e_newnode) chứ
    Cám ơn bạn. Mình cũng mới phát hiện ra. Thêm 1 lỗi của mình nữa là chỉ mới khởi tạo 1 cái danh sách khách hàng. mà quên mất mỗi node nhân viên lại có 1 danh sách khác nhau dẫn đến c_numnode tăng sai. Vấn đề đã được giải quyết. Cám ơn bạn nhiều...

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Hix. Quả thực là cách đặt tên biến/trường/struct của bạn đọc khó quá. Đọc mệt
    Code nửa Việt nửa Anh, lại ko đặt code vào tag [code=cpp] ... có màu

    Không quen với cái kiểu đặt tên này nên vừa đọc xong mấy cái struct là 2 con mắt tớ xòe ra 2 bên rồi
    Thành thật xin lỗi

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi clchicken
    Hix. Quả thực là cách đặt tên biến/trường/struct của bạn đọc khó quá. Đọc mệt
    Code nửa Việt nửa Anh, lại ko đặt code vào tag [code=cpp] ... có màu

    Không quen với cái kiểu đặt tên này nên vừa đọc xong mấy cái struct là 2 con mắt tớ xòe ra 2 bên rồi
    Thành thật xin lỗi
    Mình đã sửa bài lại rồi. Bạn xem giúp mình với nhé. Nhìn code thì khá rối mắt nhưng cũng không khó hiểu đâu bạn. VD như c_name là tên khách hàng còn e_name là tên nhân viên. *c_newnode là 1 node mới trong danh sách khách hàng, còn *e_newnode là 1 node mới trong danh sách nhân viên...

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Bạn sẽ để ý rằng dù bạn có nhập bao nhiêu Nhân viên tron danh sách nhân viên thì Số nhân viên (numnode) của danh sách vẫn =0 . Do đó sẽ luôn thực hiện công việc Gắn node ở cái else. Gắn node ở chỗ này thì có tạo ra bao nhiêu node thì cũng chỉ có 1 node đc đắp vào thôi
    Điều tương tự sẽ xảy ra với nhập danh sách Khách hàng cho 1 nhân viên.

    Lý do: Bạn truyền list theo tham trị chứ ko phải tham biến.
    Tham trị sẽ tạo 1 biến mới có các trường dữ liệu = với tham số. Và hàm sẽ thực hiện trên biến này. Thực hiện xong biến sẽ bị xóa.
    Nếu các trường là trường con trỏ đến vùng nhớ thì OK. Ta tác động đổi giá trị của vùng nhớ nên khi ra khỏi hàm vùng nhớ vẫn còn giá trị
    Nhưng với các trường không phải là con trỏ mà là kiểu dữ liệu , int , char, .. thì nó sẽ bị BYEBYE.

    Do đó để cho an toàn. Bạn phải truyền tham số theo kiểu tham biến(dùng con trỏ hoặc tham chiếu)
    Hãy tâm niệm 1 điều dễ nhớ sau: Nhập(hay tác động) cho 1 phần tử thì Phần tử có khả năng bị thay đổi giá trị(Ví dụ nhập nhân viên, thì 1 nhân viên khi mới tạo thì các trường của nó = null chẳng hạn, nhập xong nó sẽ có dữ liệu). Mà công việc nào làm THAY ĐỔI GIA trỊ của tham số khi thực hiện thì cần phải truyền theo tham biến
    Khắc phục:
    Ở các hàm nhập. Truyền tham số list theo kiểu tham biến :
    cách 1 (đơn giản, dùng tham chiếu): Thêm dấu & vào định nghĩa hàm như sau : Hàm nhập( ... *&list)
    Cách 2 (phức tạp, dùng con trỏ): Thêm dấu * vào định nghĩa hàm như sau: Hàm nhập(.... **list)
    Và trong hàm này ta xem (*list) là 1 biến. như bao cái tên bình thường khác : a , b ,c d e ...
    Thao tác dữ liệu trên này thông qua con trỏ đều cần dấu * ở phía trước. cin>>**list->gì gì đấy ...
    Nếu nắm vững con trỏ thì làm cái này, còn không thì làm cách 1 cho khỏe

  7. #7
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi clchicken
    Bạn sẽ để ý rằng dù bạn có nhập bao nhiêu Nhân viên tron danh sách nhân viên thì Số nhân viên (numnode) của danh sách vẫn =0 . Do đó sẽ luôn thực hiện công việc Gắn node ở cái else. Gắn node ở chỗ này thì có tạo ra bao nhiêu node thì cũng chỉ có 1 node đc đắp vào thôi
    Điều tương tự sẽ xảy ra với nhập danh sách Khách hàng cho 1 nhân viên.

    Lý do: Bạn truyền list theo tham trị chứ ko phải tham biến.
    Tham trị sẽ tạo 1 biến mới có các trường dữ liệu = với tham số. Và hàm sẽ thực hiện trên biến này. Thực hiện xong biến sẽ bị xóa.
    Nếu các trường là trường con trỏ đến vùng nhớ thì OK. Ta tác động đổi giá trị của vùng nhớ nên khi ra khỏi hàm vùng nhớ vẫn còn giá trị
    Nhưng với các trường không phải là con trỏ mà là kiểu dữ liệu , int , char, .. thì nó sẽ bị BYEBYE.

    Do đó để cho an toàn. Bạn phải truyền tham số theo kiểu tham biến(dùng con trỏ hoặc tham chiếu)
    Hãy tâm niệm 1 điều dễ nhớ sau: Nhập(hay tác động) cho 1 phần tử thì Phần tử có khả năng bị thay đổi giá trị(Ví dụ nhập nhân viên, thì 1 nhân viên khi mới tạo thì các trường của nó = null chẳng hạn, nhập xong nó sẽ có dữ liệu). Mà công việc nào làm THAY ĐỔI GIA trỊ của tham số khi thực hiện thì cần phải truyền theo tham biến
    Khắc phục:
    Ở các hàm nhập. Truyền tham số list theo kiểu tham biến :
    cách 1 (đơn giản, dùng tham chiếu): Thêm dấu & vào định nghĩa hàm như sau : Hàm nhập( ... *&list)
    Cách 2 (phức tạp, dùng con trỏ): Thêm dấu * vào định nghĩa hàm như sau: Hàm nhập(.... **list)
    Và trong hàm này ta xem (*list) là 1 biến. như bao cái tên bình thường khác : a , b ,c d e ...
    Thao tác dữ liệu trên này thông qua con trỏ đều cần dấu * ở phía trước. cin>>**list->gì gì đấy ...
    Nếu nắm vững con trỏ thì làm cái này, còn không thì làm cách 1 cho khỏe
    Mình hiểu lời bạn nói rồi... Đúng là kiến thức của mình còn sơ sài quá... Cám ơn bạn nhiều, mình sửa lại code !!!

    Bạn ơi. Mình đã kiểm tra lại như lời bạn nói. Mình thấy đã tăng numnode của danh sách nhân viên bằng dòng lệnh list->e_numnode++; rồi. Chạy thử chương trình và xuất ra numnode thì nó vẫn tăng đều đều sau mỗi vòng lặp mà. Còn cái phương thức truyền mình đã sửa theo cách của bạn nhưng nó vẫn xuất thông tin chồng lên nhau (thông tin node sau đè lên node trước)... bạn xem lại giúp mình với nhé !!!

  8. #8
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    chào Hacker1805! thật sự mình rất thích bài code này và đồ án mình đang làm cũng có lien quan đến bài của bạn nửa đó...Bạn có thể cho mình xin toàn bộ bài làm này của bạn được không..mình cảm ơn bạn rất nhiều.
    mail của mình : binhanit.gd@gmail.com

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •