2017-08-13 80 views
-4

我已經用C語言編寫了一個代碼,它將創建一個鏈接列表。鏈表結構有兩個字段,即datanext; data包含整數數據,next是一個結構指針。鏈接列表 - 刪除包含素數的節點

該程序要求用戶輸入數據到列表中。一旦輸入數據,程序將通過列表並檢查節點中的哪些數據包含素數。如果它找到一個這樣的節點,它將刪除它並將下一個節點鏈接到前一個節點,但是我得到了分段錯誤錯誤,我無法解決。

我將下面的代碼。 你能不能幫我解決問題,因爲我不知道如何發現問題?

#include <stdio.h> 
#include <stdlib.h> 

struct node { 
    int data; 
    struct node *next; 
}; 
typedef struct node *nptr; 
nptr H, h, n; 

void deletetheprime(struct node**); 
void display(); 
int prime(int); 

int main() { 
    nptr temp1, temp; 
    int i, N, p; 
    printf("\n if list is completed enter 999\n"); 
    for (;;) { 
     printf("\n enter the data \n"); 
     scanf("%d", &i); 
     if (i == 999) 
      break; 
     else 
     if (H == NULL) { 
      H = h = (nptr)malloc(sizeof(struct node)); 
      H->data = i; 
      H->next = NULL; 
     } else { 
      n = (nptr)malloc(sizeof(struct node)); 
      n->data = i; 
      n->next = NULL; 
      h->next = n; 
      h = n; 
     } 
    } 
    printf("\n data before deletion\n"); 
    display(); 
    temp = H; 

    while (temp != NULL) { 
     N = temp->next->data; 
     p = prime(N); 
     if (p == 1) { 
      deletetheprime(&temp); 
     } else { 
      temp = temp->next; 
     } 
    } 
    printf("\n the data after deletion is\n"); 
    display(); 
    return 0; 
} 

void deletetheprime(struct node **temp2) { 
    nptr temp, temp1; 
    temp = *temp2; 
    temp1 = temp->next; 
    temp->next = temp->next->next; 

    free(temp1); 
    temp = temp->next; 
} 

int prime(int i) { 
    int j, p = 0; 
    for (j = 2; j <= i/2; i++) { 
     if (i % j == 0) { 
      break; 
     } 
    } 
    if (j > i/2) { 
     p = 1; 
    } 
    return p; 
} 

void display() { 
    nptr temp; 
    temp = H; 
    while (temp != NULL) { 
     printf("\n %d", temp->data); 
     temp = temp->next; 
    } 
} 
+1

當你用調試器逐行執行代碼時,你觀察到了什麼? – user0042

+0

「*請解決*」:SO不是調試服務。使用符號進行編譯,在調試器中運行代碼,逐行跟蹤程序,檢查相關變量的值以瞭解真正正在進行的操作。如果出現*特定*問題,請隨時返回此處。 – alk

回答

1

這裏出現的問題,主要

while(temp!=NULL) 
{ 
    N=temp->next->data; 
... 

您檢查是否tempNULL,這是正確的,但訪問next節點,可以NULL的數據,並已將設置爲NULL,接近列表末尾,這會導致未定義的行爲。

簡單地將它修改爲

while(temp!=NULL) 
{ 
    N=temp->data; 
... 

你在哪裏確保溫度不NULL,你不會在這裏得到分割錯誤。它會工作。

或者如果您需要訪問temp->next->next節點的數據,則您必須檢查next->next是否也不是NULL

while(temp!=NULL) 
{ 
    if (temp->next->next != NULL) 
    { 
     N=temp->next->data; 
    } 
    else // temp->next->next is NULL so you can't access the data 
... 
1

的問題是在這裏:

while (temp != NULL) { 
    N = temp->next->data; 

當你到達列表的最後一個元素,temp不是NULL,但temp->next是如此temp->next->data是未定義行爲。

還有其他問題:

  • prime()功能是無效的,並將返回101
  • you deletetheprime()函數刪除節點並更新調用者作用域中的指針,但如果刪除的節點是第一個,則調用者不更新前一個節點中的鏈接,也不更新指針。
  • 你使用全局變量沒有很好的理由,你應該通過Hdisplay()並使所有變量在本地main()
  • 你永遠不會釋放分配的對象,釋放你分配的所有東西是很好的風格。
  • 你不應該隱藏在typedefs後面的指針,要nodestruct node的typedef,但是保持指針可見,避免讓讀者和程序員混淆是一個好習慣。

要刪除節點,你應該使用指針鏈接招:

for (struct node **p = &H; *p;) { 
    if (prime((*p)->data) { 
     nptr np = *p; 
     *p = np->next; 
     free(np); 
    } else { 
     p = &(*p)->next; 
    } 
} 

p最初指向頭指針H,隨後指向前一個節點的next成員。當找到要刪除的節點時,它可用於更新前一節點中的頭指針或鏈接。

這裏是一個糾正和簡化版:

#include <stdio.h> 
#include <stdlib.h> 

typedef struct node { 
    int data; 
    struct node *next; 
} node; 

int isprime(int n) { 
    if (n < 2) 
     return 0; 
    if (n % 2 == 0) 
     return n == 2; 
    for (int i = 3; i * i <= n; i += 2) { 
     if (n % i == 0) { 
      return 0; 
     } 
    } 
    return 1; 
} 

void display(const node *temp) { 
    while (temp != NULL) { 
     printf(" %d", temp->data); 
     temp = temp->next; 
    } 
    printf("\n"); 
} 

int main(void) { 
    node *H = NULL; 
    node **lastp = &H; 
    node *n; 
    int i; 
    printf("Enter values, when list is completed enter 999\n"); 
    for (;;) { 
     printf("\n enter the data: "); 
     if (scanf("%d", &i) != 1 || i == 999) 
      break; 

     n = malloc(sizeof(*n)); 
     if (n == NULL) 
      break; 
     n->data = i; 
     n->next = NULL; 
     *lastp = n; 
     lastp = &n->next; 
    } 
    printf("\n data before deletion: "); 
    display(H); 

    for (node **p = &H; *p;) { 
     if (isprime((*p)->data)) { 
      n = *p; 
      *p = n->next; 
      free(n); 
     } else { 
      p = &(*p)->next; 
     } 
    } 

    printf("\n the data after deletion is: "); 
    display(H); 

    /* free the list */ 
    while (H != NULL) { 
     n = H; 
     H = n->next; 
     free(n); 
    } 
    return 0; 
} 

我將你的屬性請解決它!對你英語水平不佳的態度。請通過仔細研究本網站上的答案,學習如何提高您的溝通和編程技能。