2017-06-18 88 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的答案,如果它解決了你的問題 –