2017-06-18 9 views
-1

J'avais rencontré le problème avec lui quand j'ai démarré le programme il s'est écrasé à la pleine fonction et a poussé les lignes 70 et 78 (Linux). J'essaye de le réparer mais je tombe toujours au même endroit. Le faire pour l'école et besoin de résoudre le plus rapidement possible ...Erreur de segmentation dans la pile dans la fonction C de poussée

#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

Quel débogage avez-vous fait? Avez-vous cherché ce qui cause une Segfault? – Carcigenicate

+2

Belles indentations. – tkausl

+1

Apprenez [demander] et fournir un [mcve]. Note: les questions de devoirs ont des exigences supplémentaires pour être sur le sujet. Votre professeur vous attend pour le résoudre vous-même. La programmation comprend le débogage. Habituez-vous. – Olaf

Répondre

1

Nous allons déboguer votre code ensemble. Mais d'abord, je vais vous en dire plus sur la façon de poser des questions sur les forums (donc sur StackOverflow).

D'abord il n'y a pas de 'aussi vite que possible' puisque nous sommes tous là pour vous aider. Nous ferons de notre mieux et il se peut que ce ne soit pas à l'heure. Alors s'il vous plaît relisez votre message avec votre code et demandez-vous, est-ce lisible? J'espère vraiment que votre code ne sera pas le même dans votre fichier et que vous avez tout simplement échoué à copier/coller car ce code est illisible.

Première étape: Modifiez le code pour le rendre lisible.

Je vais sauter la verbosité de cette étape mais, fondamentalement, il est en retrait, en ajoutant des espaces lorsque nécessaire, etc.

#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--; 
    } 
} 

S'il vous plaît pas que je ne change aucune logique ou types ou autre.

Deuxième étape: lecture du code.

En fait, je reviendrai probablement à cela plus tard, mais j'ai pris une lecture rapide et il y a quelques éléments de base qui ont besoin d'être dit. La fonction main doit toujours renvoyer un int. Conformément à la norme C, vous pouvez uniquement déclarer la fonction main de deux manières: int main(void) (ne prend aucun paramètre) ou int main(int argc, char *argv[]); (prend les paramètres de ligne de commande). Ensuite, vous devez savoir que les deux variables a et j sont globales dans le fichier. Cela signifie que vous pouvez y accéder partout dans le même fichier source. Ça sonne bien, ça ne marche pas. Vous ne devez JAMAIS faire de variables globales, sauf si vous n'avez AUCUN AUTRE CHOIX (par exemple en utilisant sigaction). Dans votre cas, ils ne sont vraiment pas nécessaires.

Enfin, COMMENTAIRES. S'il vous plaît, félicitez votre code. Alors que la plupart d'entre elle est facilement compréhensible ici, la fonction lolol (ce nom n'a pas de sens du tout) fait quelque chose que je ne comprends pas en jetant un coup d'œil au code.

Troisième étape: la compilation

gcc file.c => 4 avertissements. À moins que vous sachiez ce que vous faites et que vous soyez un programmeur C expérimenté - ce que vous n'êtes pas (encore!), Vous ne devriez pas avoir d'avertissements lors de la compilation. En outre, vous devez compiler avec les commutateurs -Wall -Wextra. Cela enverra plus d'avertissements mais vous permettra d'attraper des bugs avant même qu'ils existent.

Nous fixerons les avertissements:

  • warning: return type of ‘main’ is not ‘int’ [-Wmain]. D'accord, passons à autre chose. void main() devient int main(void), comme je l'ai dit plus tôt.
  • file.c:64:34: warning: passing argument 2 of ‘push’ makes pointer from integer without a cast [-Wint-conversion] => D'accord, vous utilisez ici la fonction push que je suppose que vous avez écrite.Toutefois, cette fonction attend un int en tant que premier paramètre et un struct stack * car il est deuxième paramètre lorsque vous lui passez un int. Réglons cela: push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]); devient push(x->Elem[x->TowerTop], x2);, puisque vous poussez x->Elem[x->TowerTop] sur le dessus de la pile x2.
  • Même chose pour les trois avertissements, étant la ligne pop 66, la push ligne 70 et la ligne 72. pop
  • suivant deux avertissements sont les mêmes: file.c:74:1: warning: control reaches end of non-void function [-Wreturn-type] => Je ne suis toujours pas sûr de ce que lolol est destiné à faire, donc je vais juste ajouter un return 0 à la fin de celui-ci, et passer la fonction create au type void.

Voici le code corrigé:

#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--; 
    } 
} 

et en cours d'exécution sans Compiler SIGSEGV.

Dernière étape: aller plus loin

Je vais parler de sujets plus avancés, mais il pourrait être utile pour vous. D'abord, obtenez plus d'informations sur la pile et leur fonctionnement car je ne suis pas sûr que vous l'ayez complètement compris.

Aussi, pour déboguer vos programmes, vous pouvez utiliser valgrind, c'est un outil de vérification de la mémoire qui est très utile et est toujours utile. Pour l'utiliser, ajoutez l'indicateur -g lors de la compilation.

Je suggère aussi de regarder dans gdb, le débogueur Linux GNU. Très puissant. La fonction full peut être remplacée par return x->TowerTop == SIZE - 1. Cela évite les branchements et donc va courir plus vite.

Et c'est tout. Vous ne savez toujours pas ce que votre code devrait faire, mais vous avez seulement demandé comment corriger votre erreur de segmentation. Maintenant s'il te plaît, souviens-toi. Ne laissez aucun avertissement lors de la compilation.

Merci.

+0

merci beaucoup. Je suis désolé pour mes mots. L'anglais n'est pas ma première langue à essayer de m'y habituer –

+0

Ne vous inquiétez pas, ça va. J'espère juste que vous comprenez vos erreurs et devenez un meilleur programmeur. :) –

+0

@MatthewDarens S'il vous plaît accepter la réponse de Doe si elle résout votre question –