2016-10-21 9 views
0

私は、昇順でユーザーから数字を受け取り、使用した一意の番号が何であるかを示すリンクリストを作成して練習しています。 findUnique関数とwhileループをインクルードした後にセグメンテーション違反が発生し続けると、何も印刷されないうちにリストを出力するように設定されています。 これはリンクされたリストの練習なので、どんな助けもありがとうございます。リンクされたリストのセグメンテーションフォールト

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

typedef struct number{ 

    int num; 
    struct number* next; 
}Number; 

Number *addterm(Number*, int); 
void findUnique(Number*); 

int main(void){ 

    Number *Number_List = NULL; 
    int digit = 1; 

    printf("Enter numbers in ascending order(enter 0 to stop): "); 
    scanf("%d", &digit); 

    while(digit != 0){ 
     addterm(Number_List, digit); 
     printf("Enter numbers in ascending order(enter 0 to stop): "); 
     scanf("%d", &digit); 
    } 
    printf("\ntest 1\n"); 

    Number *ptr = Number_List; 
    while(ptr){ 
     printf("%d ", ptr -> num); 
     Number_List = ptr -> next;   
    } 
    printf("\ntest 2\n"); 
    printf("\n"); 

    findUnique(Number_List); 


    return 0; 
} 

Number *addterm(Number* list, int userIn){ 
    Number *newNum = (Number *) malloc (sizeof (Number)); 
    newNum->num = userIn; 
    newNum->next = list; 

    if(list == NULL){ 
     return newNum; 
    } 
    Number *ptr = list; 

    while(ptr->next != NULL){ 
     ptr = ptr->next; 
    } 
    ptr->next = newNum; 
    return list; 
} 
void findUnique(Number* list){ 

    int print, temp; 
    print = list->num; 
    temp = print; 
    printf("The unique numbers you entered are %d", temp); 

    while(list){ 
     print = list->num; 
     if(print == temp){ 
      continue; 
     } 
     else{ 
     temp = print; 
     printf(" %d", temp); 
     } 
     list = list -> next; 
    } 
    return; 
} 
+2

ようこそスタックオーバーフロー!デバッガを使用してコードをステップ実行する方法を学ぶ必要があるようです。良いデバッガを使用すると、プログラムを1行ずつ実行し、どこからずれているかを確認することができます。これはプログラミングをする場合に不可欠なツールです。さらに読む:[小さなプログラムをデバッグする方法](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/) –

答えて

2

エラー1:

addterm(Number_List, digit); 

Number_List = addterm(Number_List, digit); 

あなたは、あなたのリストポインタを更新するのを忘れなければなりません。

エラー2:

while(ptr){ 
    printf("%d ", ptr -> num); 
    Number_List = ptr -> next;   
} 

これは、無限ループを生成している

while(ptr){ 
    printf("%d ", ptr -> num); 
    ptr = ptr -> next;   
} 

であるべきです。

エラー3:

newNum->next = list; //In addTerm() 

newNum->next = NULL; 

新しいノードは次のノードのセットを持っていないはずです。これにより、無限ループも発生しました。

エラー4:

if(print == temp){ 
     continue; 
} 

if(print == temp){ 
     list = list->next; 
     continue; 
    } 

別の無限ループでなければなりません。

+0

segfaultは** Error 1 **の結果です。 Number_Listが常にNULLになるようにポインタを更新するのを忘れてしまった。 findUniqueが呼び出され、list-> numと** BOOM ** – MatzZze

+0

Bahにアクセスしています。私が上記にできる唯一の提案は、最後の条件を 'if(print!= temp){ temp = print;}に変更することです。 printf( "%d"、temp); } '。これは読みやすく、最初に問題に陥った「続行」を避けます。 –

0

私はこの問題を試みましたが、エラーはあなたのfindUnique機能にあると考えています。これらの問題は@MatzZzeの下で既にカバーされており、現在のコードを修正するのに役立ちます。

また、この方法を試すこともできます。リンクされたリストから重複を削除し、リストを適切に更新する別の方法を示します。私が含まれている余分なコードは、単にプログラムを実行するのを助けることでした。

ここにある:

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

typedef int data_t; 

typedef struct node node_t; 

struct node { 
    data_t num; 
    node_t *next; 
}; 

typedef struct { 
    node_t *head; 
    node_t *foot; 
}list_t; 

list_t *make_empty_list(void); 
list_t *add_term(list_t *list, data_t value); 
void read_terms(list_t *list); 
void print_unique_terms(list_t *list); 
list_t *unique_terms(list_t *list); 
void print_list(list_t *list); 
void free_list(list_t *list); 

int 
main(int argc, char const *argv[]) { 
    list_t *list; 

    list = make_empty_list(); 

    read_terms(list); 

    printf("Your numbers are:\n"); 
    print_list(list); 

    unique_terms(list); 

    printf("The unique numbers you entered are:\n"); 
    print_list(list); 

    free(list); 

    return 0; 
} 

void 
read_terms(list_t *list) { 
    int digit; 

    printf("Enter numbers in ascending order(enter 0 to stop): "); 
    while (scanf("%d", &digit) == 1) { 
     if (digit == 0) { 
      break; 
     } else { 
      add_term(list, digit); 
     } 
    } 
} 

list_t 
*add_term(list_t *list, data_t value) { 
    node_t *node; 
    node = malloc((sizeof(*node))); 
    node->num = value; 
    node->next = NULL; 

    if (list->foot == NULL) { 
     list->head = list->foot = node; 
    } else { 
     list->foot->next = node; 
     list->foot = node; 
    } 
    return list; 
} 

list_t 
*unique_terms(list_t *list) { 
    node_t *node = list->head; 

    while (node != NULL && node->next != NULL) { 
     if (node->num == node->next->num) { 
      node->next = node->next->next; 
     } else { 
      node = node->next; 
     } 
    } 
    return list; 
} 

void 
free_list(list_t *list) { 
    node_t *curr, *prev; 
    curr = list->head; 
    while (curr) { 
     prev = curr; 
     curr = curr->next; 
     free(prev); 
    } 
    free(list); 
} 

void 
print_list(list_t *list) { 
    node_t *node = list->head; 

    while (node != NULL) { 
     printf("%d ", node->num); 
     node = node->next; 
    } 
    printf("\n"); 
} 

list_t 
*make_empty_list(void) { 
    list_t *list; 
    list = malloc(sizeof(*list)); 
    list->head = NULL; 
    list->foot = NULL; 
    return list; 
} 
0

これらは偉大な答えであり、彼らは確かにこのコードであなたを助けます。

しかし、私は次のことをお勧め:この質問への本当の答えは、あなたはおそらく知っているように、これは、リンクされたリストであるということである。

+------+  +------+  +------+ 
| data |  | data |  | data | 
+------+  +------+  +------+ 
| next |---->| next |---->| next |----> NULL 
+------+  +------+  +------+ 
^
    | 
START (Keep track of the whole list.) 

あなたに実行することができます最大の危険は、あなたの次のスタートポインタであります。

  1. あなたのIDEでデバッグを有効にして、あなたのプログラムのエントリポイントにブレークポイントを配置します。今、常に次のんのに役立ちますように、あなたの質問に答えます。プログラムに障害が発生するまで、急速に発射してステップオーバーツールを使用します。今あなたはそれを引き起こしている行を知っています。

  2. その行にブレークポイントを置き、その場所にデバッグし、問題の原因となっているポインタがいつ設定されるかを判断します。

  3. 多くのIDEは、指定した変数が指定した値と等しい場合にのみ、ポイントでプログラムを中断する変数に 'watch'を配置するツールを提供しています。

  4. 今ではセグメンテーションが発生しているので、ループのある場所を調べる必要があります。リストの境界を過ぎて繰り返す可能性が高いからです。

この問題を解決するには、デバッグ技術を学ぶことが適切です。

幸運を祈る!

関連する問題