C中的快速联盟实施

时间:2013-12-18 14:24:05

标签: c algorithm data-structures segmentation-fault

#include<stdio.h>
#include<stdlib.h>
int *id,N;

main()
{
    FILE* file=fopen("a.txt","r");
    int i,p,q,c;
    fscanf(file,"%d",&N);

    id=(int *)malloc(N*sizeof(int));

    for(i=0;i<N;i++)
        *(id+i)=i;

    while(!feof(file))
    {
        fscanf(file,"%d %d",&p,&q);
        if(!connected(p,q))
            unn(p,q);
    }
    fclose(file);
    c=1;

    while(c==1)
    {
        scanf("%d %d",&p,&q);
        printf("%d\nYes(1) or No(0)    ",connected(p,q));
        scanf("%d",&c);
    }
}

connected(int p,int q)
{
    return((root(p))==(root(q)));
}

unn(int p,int q)
{
    int j=root(q);
    int i=root(p);
    *(id+j)=i;
}

root(int i)
{
    while(i!=(*(id+i)))
        i=*(id+i);
    return(i);
}

编译时,不会显示任何错误消息。但是,当我尝试执行此程序时,它会显示“Segmentation Fault(core dumped)。为什么会发生这种情况? 可能已经注意到,这是尝试实现快速联盟。

快速查找是在没有任何麻烦的情况下使用相同的文件“a.txt”实现的,只需对此代码进行一些调整。 在运行gdb时,它说:

“程序接收信号SIGSEGV,分段故障
   0x98048729在rt(i = 134761)at i.c:47“

每次运行变量“i”的值都是134761,它不应该是,因为文本文件中的值只有1到11之间。
*是或否是用户的查询。

3 个答案:

答案 0 :(得分:1)

最后的fscanf失败了,你无法分辨。看看gdb的这个输出

a.txt是

5

(只有那个)

当我们运行gdb时我们得到段错误,我们要求发生了它打印了调用堆栈

(gdb) run
Starting program: /home/guido/a.out 
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400911 in root (i=4195888) at a.c:53
53      while(i!=(*(id+i)))
(gdb) where
#0  0x0000000000400911 in root (i=4195888) at a.c:53
#1  0x0000000000400889 in connected (p=0, q=4195888) at a.c:41
#2  0x00000000004007cd in main () at a.c:23
(gdb) 

main.c:23是

22         fscanf(file,"%d %d",&p,&q);
23         if(!connected(p,q))
24             unn(p,q);

之后我们看到fscanf p为0且q4195888(它与您的运行不同,这会发生未定义的行为;)。这是因为scanf没有数字要读取。你的while (!feof(file))将无效,因为即使我们还没有到达文件末尾,也没有更多的数字(我想我们可以通过扫描“%d%d \ n”来解决这个问题。循环和“%d \ n”在开始时。)

更正确的方法是

22         if(2 == fscanf(file,"%d %d",&p,&q))
23             if(!connected(p,q))
24                 unn(p,q);

2指的是2格式说明符。 scanf和朋友返回匹配元素的数量。这样我们确保只处理有效的输入。 (这对我来说不是段落错误,我认为它完全解决了这个问题)

我们应该从中得到的是I / O很棘手,我们应该指定准确读取我们想要读取的内容,并注意形成错误的文件。

编辑:顺便说一下,你应该真正声明函数原型并指定返回类型。这是我对代码的“清理”(http://pastebin.com/r0csiCyj)。全球变量也是邪恶的。

答案 1 :(得分:0)

总是检查fopen();

的结果

答案 2 :(得分:0)

在你的根函数中你有:

i=*(id+i);

不会检查id + i增量是否在有效范围内,因为您只是用了一段时间来迭代数据结构。问题是,在某些时候,你已经离开了你分配的内存。

一些意见:

  • 请添加每个函数的显式返回类型:)
  • 在询问编译器说XX行的问题时,请注明行,我不得不算一下:)

干杯