当我启动程序时,我遇到了问题,它在功能完全崩溃并推送第70和78行(Linux)。我试着解决它,但我总是在同一个地方崩溃。
#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
(这个名字在btw中没有意义)在快速查看代码时正在做一些我不明白的事情。
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
时,这个函数需要一个struct stack *
作为它的第一个参数和一个int
作为它的第二个参数。让我们解决这个问题: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
。它避免了分支,因此运行得更快。
这就是所有人。仍然不确定您的代码应该做什么,但您只询问如何修复您的段错误。现在请记住。编译时不要发出任何警告。
谢谢。