Linkedlist和segmentaion错误

时间:2018-01-06 16:47:17

标签: c

这是我的代码。

#include<stdio.h>
#include<stdlib.h>
struct prefix {
   unsigned int IP ;
   unsigned char len ;
  struct prefix *next ;
 };
typedef struct prefix Prefix ;
int cal(int d){
   int i , sum ;
   sum = 2 ;
   for( i = 0 ; i < d-1 ; i++)
     sum = sum * 2 ;
      return sum+1 ; }


Prefix *insert_a_node(Prefix *head,Prefix *node ){
    Prefix *cur ;
      cur = head ;
    if(head == NULL)
        return node ;
    if( node == NULL )
       return head ;
    if( node->IP < head->IP)
      { node->next = head ;
          return node ;  }
    while( cur->next != NULL && cur->next->IP <= node->IP)
        cur = cur->next ;
       node->next = cur->next ;
       cur->next = node ;
      return head ;
                       }

void insert_prefix(Prefix *group_head,Prefix *node){
  int i = 0;
  Prefix *t;

  if(node == NULL) return;
  if(group_head->next == NULL)
        {
         group_head->next=node;

         return ;
        }
  if(node->IP <= group_head->next->IP)
        {
        node->next = group_head->next ;
        group_head->next=node;

        return ;
        }
  t = group_head->next ;
 if(t->next==NULL)
   {  t->next=node;

      return;}
  while(t->next!=NULL && t->next->IP < node->IP)
        t=t->next;
 if(t->next==NULL)
     { t->next=node;

       return;}
   else{
    node->next=t->next;
    t->next=node;

    return;}
}
Prefix *build_list_no_order(Prefix *head,Prefix *node){

     if (head == NULL)
         return node ;
     if (node == NULL)
        return head ;
   Prefix *cur ;
     cur = head ;
   while ( cur->next != NULL)
    cur = cur->next ;
    cur->next = node ;
  return head ;

 }

Prefix *build_routing_table(){
    int a[5],i ;
   int ip = 0 ;
  Prefix *head ;
      head =  NULL ;
 FILE *ofp ;
 ofp = fopen("routing_table","r") ;
 while( fscanf(ofp,"%d.%d.%d.%d/%d",&a[0],&a[1],&a[2],&a[3],&a[4]) != EOF){
       Prefix *node = (Prefix*)malloc(sizeof(Prefix)) ;
   for ( i =0 ; i < 4 ; i++)
   {  ip = ip + a[i] ;
    if ( i != 3 )
      ip = ip<<8 ;  }
        node->IP = ip ;
        ip = 0 ;
        node->len=a[4];
      head = build_list_no_order(head,node);  }
 fclose(ofp);
    return head ;

    }

void segment(int d,Prefix *rout ,Prefix group[],int each_seg_num[]){
   int index=0,i;
 if(rout->len < d)
      index = cal(d)-1;
 else{
   for(i=31 ; i>31-d ; i--){
    if( ( rout->IP & 1<<i ) && ( i!=32-d))
        {index++;
        index=index<<1;}
    if( (rout->IP & 1<<i) && i==32-d)
        index++;
    if( !(rout->IP & 1<<i) && i!=32-d)
        index=index<<1;
                           }
      }
   each_seg_num[index]++;
   insert_prefix(&group[index],rout);
    return ;
   }
int main ( int argc , char *argv[]){
  Prefix *routing_head;
  Prefix *trace_head;
  Prefix *node;
  int d = 5 , i ; //need use argc finally
  int group_num;
  group_num = cal(d);
  Prefix group[group_num] ;
  int each_seg_num[group_num];
 for( i = 0 ; i < group_num ; i++)
  each_seg_num[i] = 0;
  routing_head = build_routing_table();
 int count = 1200 ;
 while(routing_head != NULL &&count>=0){
   node = routing_head ;
   routing_head = routing_head->next ;
   node->next = NULL ;
   segment(d,node,group,each_seg_num);
    count--;
     }
 for( i = 0 ; i < group_num ; i++)
   printf("%d\n",each_seg_num[i]);

     return 0 ;
}

让我解释一下我现在在做什么。

首先,我从routing_table读取了80000个数据(每个数据都有相似之处) 格式如2.10.120.20/8,我将它存储在Prefix的IP(unsigned int)中,你可以称之为IP /前缀长度。)
然后,我想将这些数据分段到不同的组(每组是 一个链表)数字由int d决定,假设d = 2,所以 我有2 ^ 2 + 1组。由于每个数据的第一个&#34; d&#34;我们可以确定哪个 小组应该数据 示例:IP(二进制):01000011 ......它应该进入组[1]
          IP:1000001 .....应该进入组[2]
   如果前缀为len&lt; d如IP:1 ********(*表示不关心位)它应该进入特殊组,组[4]。
第三,每个链表应该按顺序(从小到大)

问题:我想我已经完成了几乎所有代码,但是当我执行我的程序时 它有分段错误。但最令我惊讶的是,当我使用int count时 限制传入segment()的数据量,程序可以正常工作!!
代码可以工作少于传递大约1000个数据。我想知道怎么做 解决我的问题,谢谢你阅读我的问题。

.....最后,我的英语可能还不够完美地解释这个问题.....请原谅我^^

1 个答案:

答案 0 :(得分:0)

insert_prefix中发生崩溃,您将节点插入到组列表中,同时保持列表排序。

首先,定义组时会出现概念错误。有group_num个组,每个组都是一个链表,所以你需要一个指针数组来代替节点数组:

Prefix *group[group_num];

您还应该将每个指针初始化为NULL。您必须将group参数调整为segmentinsert_prefix函数。

在无序链表的实现中,返回新的头节点。在这里,您还必须找到更新头部的方法。在C中,我发现将指针传递给头节点指针很有用。

您可以将此指针用于节点指针以遍历列表:当您调用该函数时,该指针是头节点的地址。之后,它是前一个节点的next指针的地址。

使用这种技术,您的功能变为:

void insert_prefix(Prefix **head, Prefix *node)
{
    if (node == NULL) return;

    while (*head && (*head)->IP < node->IP) {
        head = &(*head)->next;
    }

    node->next = *head;
    *head = node;
}

了解此迭代方法如何处理所有特殊情况。没有必要区分空列表和完整列表。

您应该对程序进行的其他更改是在此处更改group参数:

void segment(int d, Prefix * rout, Prefix *group[], int each_seg_num[])
{
    ....
}

并更改main中的定义和初始化:

group_num = cal(d);
Prefix *group[group_num];
int each_seg_num[group_num];

for (i = 0; i < group_num; i++) {
    group[i] = NULL;
    each_seg_num[i] = 0;
}

您可能还应该在程序结束时引入代码来销毁您的列表。