首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用C语言快速实现Union

问用C语言快速实现Union
EN

Stack Overflow用户
提问于 2013-12-18 22:24:05
回答 3查看 424关注 0票数 0
代码语言:javascript
复制
#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);
}

编译时,不显示任何错误消息。然而,当我尝试执行这个程序时,它却显示“分段错误(核心转储)。为什么会发生这种情况?正如可能已经注意到的,这是为了实现快速联合。

快速查找是使用相同的文件"a.txt“实现的,只需对此代码进行一些调整即可。在运行gdb时,它说:

“程序接收信号SIGSEGV,分段故障

代码语言:javascript
复制
0x08048729 in rt (i=134761) at i.c:47"

每次运行变量"i“时,它的值都是134761,这是不应该的,因为在文本文件中,值的范围只在1到11之间。

*是或否是针对用户的查询。

EN

回答 3

Stack Overflow用户

发布于 2013-12-18 22:53:55

最后一个fscanf失败了,您无法判断。查看gdb的以下输出

a.txt是

代码语言:javascript
复制
5

(仅限于此)

当我们运行gdb时,我们得到了段错误,我们询问它发生在哪里,它打印调用堆栈

代码语言:javascript
复制
(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是

代码语言:javascript
复制
22         fscanf(file,"%d %d",&p,&q);
23         if(!connected(p,q))
24             unn(p,q);

我们看到fscanf p为0,q为4195888 (它与您的运行不同,这发生在未定义的行为上;)。这是因为没有数字可供scanf读取。你的while (!feof(file))将无法工作,因为即使我们还没有到达文件的末尾,也没有更多的数字(我认为我们可以通过扫描循环中的“%d%d\n”和开始中的"%d\n“来”修复“这个问题)。

更正确的方法应该是

代码语言:javascript
复制
22         if(2 == fscanf(file,"%d %d",&p,&q))
23             if(!connected(p,q))
24                 unn(p,q);

2指的是2个格式说明符。scanf和friends返回匹配元素的数量。这样,我们就可以确保只在有效的输入上工作。(这对我来说不是段错误,我认为它完全修复了它)

我们应该从这一切中得到的是,I/O是棘手的,我们应该指定准确地读取我们想要读取的内容,并注意格式错误的文件。

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

票数 1
EN

Stack Overflow用户

发布于 2013-12-18 22:29:14

总是检查fopen()的结果;

票数 0
EN

Stack Overflow用户

发布于 2013-12-18 22:41:58

在你的根函数中,你有:

代码语言:javascript
复制
i=*(id+i);

它不检查id+i增量是否在有效范围内,因为您只使用了一段时间来迭代数据结构。问题是,在某些情况下,您将耗尽分配的内存。

一些评论:

  • 请添加每个函数的显式返回类型:)
  • 当问到一个问题时,编译器说第XX行,请指出这一行,我得数一下:)

干杯

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20660711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档