2017-06-18 52 views
-1

我遇到问题,当我开始它的程序崩溃在功能全和推线70和78(Linux)。我试图解决它,但我总是在同一个地方崩溃。这样做的学校,并需要尽快修复它...推按功能C中的堆栈中的分段错误功能C语言

#include <stdio.h> 
    #define SIZE 64 

    struct stack{ 
     int TowerTop; 
     int Elem[SIZE]; 
    }; 

    /* Forward Declarations */      
    void push(int Elem, struct stack *x); 
    int create (struct stack *x); 
    int full(const struct stack *x); 
    void pop(struct stack *x); 
    int lolol(struct stack *x,struct stack *x2,struct stack *x3,int a); 

    void main() { 
     int j; 
     int a = 5; 

     //scanf("%d",&a); 

     struct stack Tower1; 
     struct stack Tower2; 
     struct stack Tower3; 

     create(&Tower1); 
     create(&Tower2); 
     create(&Tower3); 

     for(int i=0; i<=SIZE-1; i++) { 
      Tower1.Elem[i]=0; 
      Tower2.Elem[i]=0; 
      Tower3.Elem[i]=0; 
     } 

     for(int i=0; i<=a; i++){ 
      Tower1.Elem[i]=i+1; 
     } 

     // Display initial tower setup 
     for(int i=0; i<a; i++){ 
     printf("%d %7d %7d\n",Tower1.Elem[i],Tower2.Elem[i],Tower3.Elem[i]); 
     } 

     lolol(&Tower1,&Tower2,&Tower3,a); 

     // Display Tower after move made by lolol 
     printf("%d\n", j); 
     for(int i=0; i<a; i++) { 
     printf("%d %7d %7d\n",Tower1.Elem[i],Tower2.Elem[i],Tower3.Elem[i]); 
     } 
    } 

    int lolol(struct stack *x,struct stack *x2,struct stack *x3,int a) { 
     if(a == 1) { 
      printf("\n Disk 1 move to"); 
      push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]); j++; 
      pop(x->Elem[x->TowerTop]); 
      return 0; 
     } 

     lolol(x, x3, x2, a-1); 
     push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]); j++; 
     pop(x->Elem[x->TowerTop]); 
     lolol(x3, x2, x, a-1); 
     } 

     int create(struct stack *x) { 
     x->TowerTop = -1; 
     } 

     int full(const struct stack *x) { 
      if (x->TowerTop == SIZE-1) { 
      return 1; 
      } else { 
      return 0; 
      } 
     } 

     void push(int Elem, struct stack *x){ 
      if(full(x)) { 
      printf("Stack is full"); 
      } else { 
      x->TowerTop++; 
      x->Elem[x->TowerTop]=Elem; 
      } 
     } 

     void pop(struct stack *x) { 
      if(x->TowerTop== -1) { 
      printf("Empty"); 
      } else { 
      x->TowerTop--; 
      } 
     } 
+1

你做了什么调试?你是否查找了导致Segfault的原因? – Carcigenicate

+2

尼斯缩进。 – tkausl

+1

学习[问]并提供[mcve]。注:作业题目有额外的要求,要成为话题。你的老师希望你自己解决它。编程包括调试。习惯它。 – Olaf

回答

1

我们将调试你的代码在一起。但首先,我会告诉你更多关于如何在论坛上提问的问题(StackOverflow)。

首先没有'尽可能快',因为我们都在这里帮助。我们会尽力而为,并且可能会也可能不会按时。然后请再次用您的代码读取您的消息,并问问自己,这是可读的吗?我真的很希望你的代码在你的文件中看起来不一样,你只是以某种方式失败了复制/粘贴,因为这段代码是不可读的。

第一步:更改代码以使其可读。

我会跳过此步骤的详细程度,但基本上它是缩进,需要等时

#include <stdio.h> 

#define SIZE 64 

struct stack 
{ 
    int TowerTop; 
    int Elem[SIZE]; 
}; 

void push(int Elem, struct stack *x); 
void pop(struct stack *x); 
int create (struct stack *x); 
int full(const struct stack *x); 
int lolol(struct stack *x, struct stack *x2, struct stack *x3, int a); 

int a; 
int j; 

void main() 
{ 

    //scanf("%d", &a); 
    a = 5; 
    struct stack Tower1; 
    struct stack Tower2; 
    struct stack Tower3; 
    create(&Tower1); 
    create(&Tower2); 
    create(&Tower3); 

    for (int i = 0; i <= SIZE - 1; i++) 
    { 
     Tower1.Elem[i] = 0; 
     Tower2.Elem[i] = 0; 
     Tower3.Elem[i] = 0; 
    } 

    for (int i = 0; i <= a; i++) 
    { 
     Tower1.Elem[i] = i + 1; 
    } 

    for (int i = 0; i < a; i++) 
    { 
     printf("%d %7d %7d\n", Tower1.Elem[i], Tower2.Elem[i], Tower3.Elem[i]); 
    } 

    lolol(&Tower1, &Tower2, &Tower3, a); 

    printf("%d\n", j); 

    for (int i = 0; i < a; i++) 
    { 
     printf("%d %7d %7d\n", Tower1.Elem[i], Tower2.Elem[i], Tower3.Elem[i]); 
    } 
} 

int lolol(struct stack *x, struct stack *x2, struct stack *x3, int a) 
{ 
    if (a == 1) 
    { 
     printf("\n Disk 1 move to"); 
     push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]); 
     j++; 
     pop(x->Elem[x->TowerTop]); 
     return 0; 
    } 
    lolol(x, x3, x2, a - 1); 
    push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]); 
    j++; 
    pop(x->Elem[x->TowerTop]); 
    lolol(x3, x2, x, a - 1); 
} 

int create(struct stack *x) 
{ 
    x->TowerTop = -1; 
} 

int full(const struct stack *x) 
{ 
    if (x->TowerTop == SIZE-1) 
    { 
     return 1; 
    } 
    else 
    { 
     return 0; 
    } 
} 

void push(int Elem, struct stack *x) 
{ 
    if (full(x)) 
    { 
     printf("Stack is full"); 
    } 
    else 
    { 
     x->TowerTop++; 
     x->Elem[x->TowerTop] = Elem; 
    } 
} 

void pop(struct stack *x) 
{ 
    if (x->TowerTop == -1) 
    { 
     printf("Empty"); 
    } 
    else 
    { 
     x->TowerTop--; 
    } 
} 

请不,我没有改变任何逻辑或类型或任何增加的空间。

第二步:读取代码。

其实我可能会在稍后再回来,但我快速阅读,有一些基本的东西需要说。 main函数应始终返回int。根据C标准,只能用两种方式声明main函数:int main(void)(不带参数)或int main(int argc, char *argv[]);(带命令行参数)。

然后,您必须知道,两个变量aj是全局文件。这意味着你可以在同一个源文件中的任何地方访问它们。听起来不错,不起作用。除非您没有其他选择(例如使用sigaction),否则您应该永远不要做全局变量。在你的情况下,他们真的不需要。

最后,评论。请赞扬你的代码。虽然大部分内容在这里很容易理解,但函数lolol(该名称根本没有意义)正在做一些我在快速查看代码时无法理解的内容。

第三步:在编译

gcc file.c => 4警告。除非你知道自己在做什么,并且是一位经验丰富的C程序员 - 你还没有(当然),编译时不应该有任何警告。此外,您应该使用-Wall -Wextra开关进行编译。这将会抛出更多的警告,但可以让你在错误发生之前就发现它们。

因此,我们将修复警告:

  • warning: return type of ‘main’ is not ‘int’ [-Wmain]。好的,让我们切换。正如我前面所说,void main()变成int main(void)
  • file.c:64:34: warning: passing argument 2 of ‘push’ makes pointer from integer without a cast [-Wint-conversion] =>好的,在这里您使用push函数,我假设你写了。但是,当您传递int时,此功能需要第一个参数intstruct stack *,因为它的第二个参数是 。让我们来修正:push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]);变成push(x->Elem[x->TowerTop], x2);,因为您要将x->Elem[x->TowerTop]推到x2堆栈的顶部。
  • 在未来三年的警告同样的事情,作为pop线66,push线70和pop线72
  • 接下来两个警告是相同的:file.c:74:1: warning: control reaches end of non-void function [-Wreturn-type] =>我仍然不知道什么是lolol这意味着要做,所以我只需在其末尾添加一个return 0,并将create函数切换为void类型。

下面是更正后的代码:

#include <stdio.h> 

#define SIZE 64 

struct stack 
{ 
    int TowerTop; 
    int Elem[SIZE]; 
}; 

void push(int Elem, struct stack *x); 
void pop(struct stack *x); 
void create (struct stack *x); 
int full(const struct stack *x); 
int lolol(struct stack *x, struct stack *x2, struct stack *x3, int a); 

int a; 
int j; 

int main(void) 
{ 

    //scanf("%d", &a); 
    a = 5; 
    struct stack Tower1; 
    struct stack Tower2; 
    struct stack Tower3; 
    create(&Tower1); 
    create(&Tower2); 
    create(&Tower3); 

    for (int i = 0; i <= SIZE - 1; i++) 
    { 
     Tower1.Elem[i] = 0; 
     Tower2.Elem[i] = 0; 
     Tower3.Elem[i] = 0; 
    } 

    for (int i = 0; i <= a; i++) 
    { 
     Tower1.Elem[i] = i + 1; 
    } 

    for (int i = 0; i < a; i++) 
    { 
     printf("%d %7d %7d\n", Tower1.Elem[i], Tower2.Elem[i], Tower3.Elem[i]); 
    } 

    lolol(&Tower1, &Tower2, &Tower3, a); 

    printf("%d\n", j); 

    for (int i = 0; i < a; i++) 
    { 
     printf("%d %7d %7d\n", Tower1.Elem[i], Tower2.Elem[i], Tower3.Elem[i]); 
    } 
} 

int lolol(struct stack *x, struct stack *x2, struct stack *x3, int a) 
{ 
    if (a == 1) 
    { 
     printf("\n Disk 1 move to"); 
     push(x->Elem[x->TowerTop], x2); 
     j++; 
     pop(x); 
     return 0; 
    } 
    lolol(x, x3, x2, a - 1); 
    push(x->Elem[x->TowerTop], x2); 
    j++; 
    pop(x); 
    lolol(x3, x2, x, a - 1); 
    return 0; 
} 

void create(struct stack *x) 
{ 
    x->TowerTop = -1; 
} 

int full(const struct stack *x) 
{ 
    if (x->TowerTop == SIZE-1) 
    { 
     return 1; 
    } 
    else 
    { 
     return 0; 
    } 
} 

void push(int Elem, struct stack *x) 
{ 
    if (full(x)) 
    { 
     printf("Stack is full"); 
    } 
    else 
    { 
     x->TowerTop++; 
     x->Elem[x->TowerTop] = Elem; 
    } 
} 

void pop(struct stack *x) 
{ 
    if (x->TowerTop == -1) 
    { 
     printf("Empty"); 
    } 
    else 
    { 
     x->TowerTop--; 
    } 
} 

编译并没有SIGSEGV运行。

最后一步:进一步说

我将谈论的话题更先进,但它可能是对你有用。首先,获取有关堆栈的更多信息以及它们如何工作,因为我不确定您是否完全理解它。

此外,要调试您的程序,您可以使用valgrind,它是一个内存检查器工具,非常有用,并且总是很方便。要使用它,在编译时添加标志-g

我建议看看gdb以及GNU Linux调试器。很强大。

功能full可以更改为简单return x->TowerTop == SIZE - 1。它避免了分支,因此运行速度会更快。

这就是所有人。仍然不确定你的代码应该做什么,但你只问如何解决你的段错误。现在请记住。 编译时不要发出任何警告。

谢谢。

+0

非常感谢。我很抱歉我的话。英语不是我第一次尝试适应它的语言 –

+0

不要担心它没问题。我只希望你能理解你的错误,并成为一名更好的程序员。 :) –

+0

@MatthewDarens请接受Doe的答案,如果它解决了你的问题 –