Danh sách liên kết không nhập được?

Đề bài: tạo danh sách liên kết đơn để nhập thông tin danh bạ với thông tin: tên, địa chỉ, email, số điện thoại cơ quan, số điện thoại bàn, số điện thoại di động.

Ở đây mình viết Code nhưng không hiểu vì sao lại chỉ nhập được 1 lần rồi sau đó có lỗi đó .
mọi người giúp mình với!
Code:

#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<malloc.h>

/* Cac buoc giai bai toan danh sach lien ket:
    1. Khai bao du lieu
    2. Khoi tao danh sach lien ket
    3. Tao Node
    4. Them Node vao danh sach <--Sau khi tao Node xong phai the Node vao danh sach
    5. Cac tuy chon : In ra, Sua, Duyet, Xoa, Tim Kiem, ...

*/

// 1. Khai bao kieu du lieu

struct SINHVIEN
{
	char name[20];
	char ID[10];
	int Mark;
}sinhvien[100];

typedef struct SINHVIEN sv;

struct NODE
{
	sv data;
	struct NODE* pNext;
};

typedef struct NODE node;

struct LIST
{
    node* pHead;
    node* pTail;
};

typedef struct LIST list;

// 2. Khoi tao danh sach lien ket

void Init(list l)
{
    l.pHead = NULL;
    l.pTail = NULL;
}

// 3. Tao NODE

void Mk_Node(node* p)
{
        p = (node* )malloc(sizeof(struct NODE));
        /// *** Kiem tra neu het bo nho  *** ///
        if (p == NULL) printf("het bo nho roi em oi!\n");
        else    // Con thua bo nho
        {
            /*
            strcpy(&(p->data.name),&(name));
            strcpy(&(p->data.ID),&(ID));
            p->data.Mark = Mark;
            */
            p->pNext = NULL;
        }

}

// 4. Them Node moi vao danh sach

void InsertFirst(list l,node* p)
{
    char name[20], ID[10];
    int mark;
    p -> pNext = l.pHead;
    p = l.pHead;
    strcpy(p->data.name,name);
    strcpy(p->data.ID,ID);
    p->data.Mark = mark;

}

void InsertLast(list l, node* p)
{
    char name[20], ID[10];
    int mark;
    l.pTail -> pNext = p;
    p ->pNext = NULL;
    p = l.pTail;
    strcpy(p->data.name,name);
    strcpy(p->data.ID,ID);
    p->data.Mark = mark;

}
// 5. Nhap gia tri cho phan DATA cua danh sach lien ket

void Input(int n,node* p)
{
    int i;
    char name[20];
    char ID[10];
    int mark;
    for (i=1; i <= n; i++)
    {
        fflush(stdin);
        printf("sinh vien thu %d\n",i);
        printf("nhap ten: \n");
        gets(name);
        fflush(stdin);
        printf("nhap ID: \n");
        gets(ID);
        fflush(stdin);
        printf("nhap diem: \n");
        scanf("%d",&mark);

        strcpy(p->data.name,name);
        strcpy(p->data.ID,ID);
        p->data.Mark = mark;
        Mk_Node(p);
    }
}

// 6. Output

void Output(list l,node* p)
{
    if (l.pHead == NULL)
            printf("Danh sach rong, ban can nhap danh sach\n");
    else
    {

        for (p = l.pHead ; p == l.pTail ; p = p -> pNext )
        {
            printf("\n Ten sinh vien la: %c", *(p->data.name));
            printf("\n ID cua sinh vien la : %c",*(p ->data.ID));
            printf("\n Diem cua sinh vien la: %d",p->data.Mark);
        }
    }
}

int main(void)
{
    int n;
    list l;
    node* p;
    printf("nhap so sinh vien can chinh sua/ them: \n");
    scanf("%d",&n);
    Input(n,p);
    Output(l,p);
	getch();
	return 0;
}

Ai biết giúp mình với ạ. Hình như là cái vòng for nó bị lỗi hay sao mà nó cứ hiện lên như thế này ạ

phần 1 - thừa sinhvien[100] chỗ khai báo struct SINHVIEN.
phần 2 - khởi tạo list l phải truyền con trỏ:

void Init(list* pList)
{
    pList->pHead = pList->pTail = NULL;
}

phần 3 - hàm Mk_Node() thì chắc là bạn muốn truyền name, ID và mark vào luôn (có thể truyền luôn cả pNext vào). Ở đây ko cần truyền node* p vào làm gì, Cho Mk_Node() trả về node* p.
sửa lại cho tiện

node* Mk_Node(const sv* pNewSV, node* pNext)
{
    node* p = (node* )malloc(sizeof(node));
    if (p)
    {
        strcpy(p->data.name, pNewSV->name);
        strcpy(p->data.ID, pNewSV->ID);
        p->data.mark = pNewSV->mark;
        p->pNext = pNext;
    }
    return p;
}
1 Like

thank nha bạn. để mình kiểm tra lại nha

phần 4 - hàm InsertFirst: truyền con trỏ tới l. Ở đây thêm 1 sv mới vào list, nên truyền sv*:

void InsertFirst(list* pList, const sv* pNewSV)
{
    node* p = Mk_Node(pNewSV, pList->pHead);
    pList->pHead = p;
    if (pList->pTail == NULL) pList->pTail = p;
}

bạn có thể viết gộp lại thành

void InsertFirst(list* pList, const sv* pNewSV)
{
    pList->pHead = Mk_Node(pNewSV, pList->pHead);
    if (!pList->pTail) pList->pTail = pList->pHead;
}

hoặc nếu chưa quen thì viết lại hàm Mk_Node ko nhận con trỏ pNext nữa, p sẽ gán pNext sau:

void InsertFirst(list* pList, const sv* pNewSV)
{
    node* p = Mk_Node(pNewSV);
    p->pNext = pList->pHead;
    pList->pHead = p;
    if (pList->pTail == NULL) pList->pTail = p;
}
1 Like

phần 5 - insert last: khai báo tương tự insert first:

void InsertLast(list* pList, const sv* pNewSV)

ở đây thêm vào pTail thay vì pHead:

void InsertLast(list* pList, const sv* pNewSV)
{
    node* p = Mk_Node(pNewSV, NULL);
    pList->pTail->pNext = p;
    pList->pTail = p;
}

nhưng có 1 lỗi rất lớn là lỡ pList->pTail == NULL thì sẽ ko có pNext mà trỏ tới ở dòng thứ 2
vậy ta phải kiểm tra NULL:

void InsertLast(list* pList, const sv* pNewSV)
{
    node* p = Mk_Node(pNewSV, NULL);
    if (pList->pTail) 
    {
        pList->pTail->pNext = p;
        pList->pTail = p;
    }
    else //pTail NULL tức là *pList rỗng
    {
        pList->pHead = pList->pTail = p;
    }
}

có thể viết gọn lại thành

void InsertLast(list* pList, const sv* pNewSV)
{
    if (pList->pTail) 
        pList->pTail = pList->pTail->pNext = Mk_Node(pNewSV, NULL); ////////
    else
        pList->pHead = pList->pTail = Mk_Node(pNewSV, NULL);
}
1 Like

Bạn xem luôn hộ mình cái hàm Input với.
Mình cho code của bạn vào check thì vẫn báo lỗi ko biết là lỗi gì

input thì phải có con trỏ tới dslk, ko có thì làm sao biết thêm vào dslk nào ~.~

void Input(list* pList, int n)
{
    sv temp;
    int i;
    for (i = 0; i < n; i++)
    {
        //nhập temp.name        
        
        //nhập temp.ID        
        
        //nhập temp.mark
        
        //thêm temp vào cuối dslk (thêm vào phía trước thì gọi InsertFirst)
        InsertLast(pList, &temp);
    }
}
1 Like

OK. Thank bạn nha. Mình làm được rồi. :smile:

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?