30/09/2018, 19:58

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!
");
        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
",i);
        printf("nhap ten: 
");
        gets(name);
        fflush(stdin);
        printf("nhap ID: 
");
        gets(ID);
        fflush(stdin);
        printf("nhap diem: 
");
        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
");
    else
    {

        for (p = l.pHead ; p == l.pTail ; p = p -> pNext )
        {
            printf("
 Ten sinh vien la: %c", *(p->data.name));
            printf("
 ID cua sinh vien la : %c",*(p ->data.ID));
            printf("
 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: 
");
    scanf("%d",&n);
    Input(n,p);
    Output(l,p);
	getch();
	return 0;
}

hamhochoi viết 22:01 ngày 30/09/2018

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 ạ

viết 21:59 ngày 30/09/2018

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;
}
hamhochoi viết 22:06 ngày 30/09/2018

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

viết 21:58 ngày 30/09/2018

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;
}
viết 21:59 ngày 30/09/2018

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);
}
hamhochoi viết 22:11 ngày 30/09/2018

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ì

viết 22:13 ngày 30/09/2018

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);
    }
}
hamhochoi viết 22:01 ngày 30/09/2018

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

Bài liên quan
0