推按功能C中的堆栈中的分段错误功能C语言
我遇到问题,当我开始它的程序崩溃在功能全和推线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--;
}
}
我们将调试你的代码在一起。但首先,我会告诉你更多关于如何在论坛上提问的问题(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[]);
(带命令行参数)。
然后,您必须知道,两个变量a
和j
是全局文件。这意味着你可以在同一个源文件中的任何地方访问它们。听起来不错,不起作用。除非您没有其他选择(例如使用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
时,此功能需要第一个参数int
和struct 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
。它避免了分支,因此运行速度会更快。
这就是所有人。仍然不确定你的代码应该做什么,但你只问如何解决你的段错误。现在请记住。 编译时不要发出任何警告。
谢谢。
非常感谢。我很抱歉我的话。英语不是我第一次尝试适应它的语言 –
不要担心它没问题。我只希望你能理解你的错误,并成为一名更好的程序员。 :) –
@MatthewDarens请接受Doe的答案,如果它解决了你的问题 –
你做了什么调试?你是否查找了导致Segfault的原因? – Carcigenicate
尼斯缩进。 – tkausl
学习[问]并提供[mcve]。注:作业题目有额外的要求,要成为话题。你的老师希望你自己解决它。编程包括调试。习惯它。 – Olaf