Tôi có chương trình C sau để triển khai danh sách liên kết tăng dần. Vấn đề nằm ở hàm buildList() nên bạn có thể bỏ qua các hàm khác ngoại trừ hàm main() và buildList().
#include
#include
nút cấu trúc
{
dữ liệu int;
nút cấu trúc *tiếp theo;
};
void buildList(nút cấu trúc **, int);
void printList(nút cấu trúc **);
int main()
{
nút cấu trúc *đầu;
head = NULL /*Danh sách trống*/
int giữ, i, j;
printf("Danh sách này có bao nhiêu số nguyên: ");
scanf("%d",&i);
j = 1;
for(i; i > 0; i--)
{
printf("Số nguyên %d: ",j);
scanf("%d",&hold);
buildList(&head, hold);
j++;
}
printList(&head);
return 0;
}
void buildList(nút cấu trúc **headRef, dữ liệu int)
{
nút cấu trúc *newNode;
newNode = malloc(sizeof(struct node));
nút cấu trúc *hiện tại, *current1;
hiện tại = *headRef;
// Nếu danh sách trống, hãy thêm số đó làm nút đầu tiên.
nếu (hiện tại == NULL)
{
newNode->data = dữ liệu;
newNode->next = *headRef;
*headRef = newNode;
}
//Nếu danh sách không trống.
khác
{
//Nếu số không lớn hơn số đầu tiên.
if (dữ liệu <= hiện tại-> dữ liệu)
{
newNode->data = dữ liệu;
newNode->next = hiện tại;
*headRef = newNode;
}
//Nếu số lớn hơn số đầu tiên trong danh sách.
khác
{
cờ int = 0;
trong khi (dữ liệu> (hiện tại-> dữ liệu))
{
current1 = hiện tại;
hiện tại = hiện tại-> tiếp theo;
}
newNode->data = dữ liệu;
current1->next = newNode;
newNode->next = hiện tại;
}
}
}
// In các nút và tổng số nút.
void printList(nút cấu trúc **headRef)
{
số int = 0;
nút cấu trúc *hiện tại;
hiện tại = *headRef;
trong khi (hiện tại != NULL)
{
count++;
printf("%d ",current->data);
hiện tại = hiện tại-> tiếp theo;
}
printf("\nTổng số nút: %d\n",count);
}
Chương trình này hoạt động tốt cho đến khi tôi đưa ra một số lớn hơn bất kỳ số nào có trong danh sách. Trong trường hợp đó tôi nhận được một segfault.
Trường hợp 1 (đầu ra tốt và chính xác)
-bash-4.1$ ./a.out
Có bao nhiêu số nguyên trong danh sách này: 3
Số nguyên 1: 5
Số nguyên 2: 1
Số nguyên 3: 4
1 4 5
Tổng số nút: 3
-bash-4,1$
Tình huống 2 (mã bị gián đoạn (lỗi phân đoạn))
-bash-4.1$ ./a.out
Có bao nhiêu số nguyên trong danh sách này: 3
Số nguyên 1: 5
Số nguyên 2: 6
Lỗi phân đoạn
-bash-4,1$
Sau một thời gian dài cố gắng tìm hiểu xem mã của mình có vấn đề gì, tôi nhận thấy rằng khi một số lớn hơn bất kỳ số nào trong danh sách, trong trường hợp đó nó nên được chèn vào cuối danh sách, câu lệnh này (trong phần hàm buildList( ) trong phần else cuối cùng gây ra sự cố:
hiện tại = hiện tại-> tiếp theo;
Cuối cùng tôi đã phát hiện ra rằng câu lệnh này gây ra lỗi seg khi current->next là NULL.
Tôi đã nghĩ ra một cách giải quyết như hình dưới đây cho kết quả đầu ra chính xác.
khác
{
cờ int = 0;
trong khi (dữ liệu> (hiện tại-> dữ liệu))
{
current1 = hiện tại;
if(current->next != NULL)
{
hiện tại = hiện tại-> tiếp theo;
}
khác
{
cờ = 1;
phá vỡ;
}
}
newNode->data = dữ liệu;
current1->next = newNode;
nếu (cờ == 1)
{
newNode->next = NULL;
}
khác
{
newNode->next = hiện tại;
}
}
Bây giờ tôi nhận được đầu ra chính xác.
-bash-4.1$ ./a.out
Có bao nhiêu số nguyên trong danh sách này: 3
Số nguyên 1: 5
Số nguyên 2: 1
Số nguyên 3: 10
1 5 10
Tổng số nút: 3
-bash-4,1$
Bây giờ tôi đang tự hỏi tại sao current = current->next; không hoạt động khi current->next là NULL. Tôi đang mong đợi tuyên bố này sẽ gán NULL cho hiện tại.
Bất cứ ai có thể cho tôi biết lý do của việc này là gì? Giải pháp của tôi có tốt không? Hoặc có cách nào tốt hơn?
Xin lỗi vì câu hỏi dài, nhưng sau khi dành khoảng 2 giờ để gỡ lỗi này, tôi nghĩ mình sắp phát điên.
Cảm ơn.
Kỹ thuật gỡ lỗi của bạn hơi bị hiểu lầm. Vấn đề là ở vòng lặp này:
trong khi (dữ liệu> (hiện tại-> dữ liệu))
{
current1 = hiện tại;
hiện tại = hiện tại-> tiếp theo;
}
Nhưng không phải theo cách bạn nghĩ. nếu như hiện tại-> tiếp theo
为 NULL
,Nhưng hiện hành
sẽ được đặt theo mô tả của bạn NULL
. Tuy nhiên, hành động tiếp theo xảy ra là điều kiện vòng lặp - nó hủy đăng ký hiện hành
. Bramo. Bạn có thể muốn một cái gì đó như thế này:
while (hiện tại && (dữ liệu > hiện tại->dữ liệu))
{
current1 = hiện tại;
hiện tại = hiện tại-> tiếp theo;
}
Tôi chưa lập hồ sơ toàn bộ chương trình của bạn, vì vậy tôi thực sự không thể nhận xét về tính chính xác của phần này ngoài sự cố rõ ràng.
Tôi là một lập trình viên xuất sắc, rất giỏi!