2017-08-28 2 views
2

J'ai écrit le code suivant pour obtenir des chaînes triées dans un tableau de caractères 2-Dde caractères à bulles sorte

#include <stdio.h> 
#include <string.h> 

void swap(char *,char *); 

void main() { 
    char a[20][20]; 
    int Pass = 0, i = 0, j = 0, n; 

    printf("\nHow many elements you want to sort ? >> "); 
    scanf("%d", &n); 
    printf("\n\nEnter the elements to be sorted :\n"); 
    for (i = 0; i < n; i++) 
     scanf("%s", a[i]); 
    for (Pass = 1; Pass < n; Pass++) { 
     for (j = 0; j < n - Pass; j++) 
      if (strcmp(a[j], a[j + 1]) < 0) 
       swap(a[j], a[j + 1]); 
     printf("\n\nPass = %d\n", Pass); 
     for (i = 0; i < n; i++) 
      printf(" %s ", a[i]); 
    } 
} 

void swap(char *a, char *b) { 
    char *t; 
    *t = *a; 
    *a = *b; 
    *b = *t; 
} 

Mais, je reçois la sortie comme

How many elements you want to sort ? >> 5 
Enter the elements to be sorted : 
1 2 3 4 5 
Pass = 1 
2 3 4 5 1 
Pass = 2 
3 4 5 2 1 
Pass = 3 
4 5 3 2 1 
Pass = 4 
Segmentation fault (core dumped) 

Pourquoi est-ce que je rencontre la segmentation faute? (Le même code fonctionne correctement si j'utilise un tableau d'entiers au lieu d'un groupe de caractères)

+0

principale doit retourner 'int ' –

+0

Votre fonction' swap' est incorrecte. 1) 'char * t; * t = * a; ': Utilisation d'une variable non initialisée. 2) Ce qui devrait être échangé est un tableau plutôt qu'un pointeur (ou un 'char'). – BLUEPIXY

+0

Gagnez du temps, activez tous les avertissements du compilateur: 'char * t; * t = * a; 'devrait avertir que' t' est utilisé avant l'initialisation. – chux

Répondre

1

Point d'entrée maindevrait être définie comme

int main() 

ou (avec des arguments)

int main(int argc, char* argv[]) 

mais peut ou ne peut pas retourner une certaine valeur.


En fonction swap vous accédez pointeur non initialisée qui provoque undefined behavior. Il n'y a pas besoin d'utiliser le pointeur. Utilisez simplement char.

void swap(char *a,char *b) 
{ 
    char t; 
    t=*a; 
    *a=*b; 
    *b=t; 
} 

également pour éviter le débordement de la mémoire tampon, vous devez dire scanf() combien de caractères pour numériser à partir tampon d'entrée

scanf("%19s",a[i]); 

et vérifier si la numérisation a réussi.

Vous devriez maintenant obtenir des résultats corrects. Here is fixed code.

+0

C spec n'est pas d'accord avec vos échantillons limités de signatures 'main()' acceptables car d'autres signatures définies par l'implémentation, et non UB, sont possibles. – chux

+0

Merci pour info. Une fois que quelqu'un m'a dit «void main» a UB et depuis que je vit dans le mensonge. –

+2

@ FilipKočica la plupart du temps 'void main()' fonctionnera quand même. Le problème ici était évidemment le pointeur non initialisé. –

1

Vous vous trompez avec vos pointeurs dans la méthode swap. À l'heure actuelle que vous faites:

void swap(char *a,char *b) 
{ 
    char *t; 
    *t=*a; 
    *a=*b; 
    *b=*t; 
} 

Cette ligne *t = *a semble être un candidat très probable pour SEGV, puisque t est un pointeur de caractère qui est non initialisée. J'ai couru votre code via gdb et gdb aussi dit la même chose:

Reading symbols from a.out...done. 
(gdb) run 
Starting program: /home/rohan/Documents/src/a.out 

How many elements you want to sort ? >> 5 


Enter the elements to be sorted : 
1 2 3 4 5 

Program received signal SIGSEGV, Segmentation fault. 
0x0000555555554a21 in swap (a=0x7fffffffdce0 "1", b=0x7fffffffdcf4 "2") at testBubble.c:26 
26  *t=*a; 
(gdb) 

Vous n'avez pas besoin t comme une variable de pointeur. C'est juste une variable temporaire nécessaire pour l'échange. Donc changer votre méthode comme celui-ci, qui fixe la faute de segmentation dans mon cas:

void swap(char *a,char *b) 
{ 
    char t; 
    t=*a; 
    *a=*b; 
    *b=t; 
} 
0

La fonction swap est incorrecte: vous déréférencement le pointeur uninitialized t, ce qui provoque un comportement non défini: dans votre cas une erreur de segmentation.

Vous devriez plutôt définir t comme char:

void swap(char *a, char *b) { 
    char t; 
    t = *a; 
    *a = *b; 
    *b = t; 
} 

Mais cela ne fonctionne que pour les mots avec un seul caractère.

Pour échanger des mots de jusqu'à 19 octets, utilisez ceci:

void swap(char *a, char *b) { 
    char t[20]; 
    strcpy(t, a); 
    strcpy(a, b); 
    strcpy(b, t); 
} 

Et pour ajouter quelques tests supplémentaires et des protections dans la fonction main pour éviter un comportement non défini:

int main(void) { 
    char a[20][20]; 
    int Pass = 0, i = 0, j = 0, n; 

    printf("\nHow many elements you want to sort ? >> "); 
    if (scanf("%d", &n) != 1 || n < 0 || n > 20) 
     return 1; 
    printf("\n\nEnter the elements to be sorted :\n"); 
    for (i = 0; i < n; i++) { 
     if (scanf("%19s", a[i]) != 1) 
      return 1; 
    } 
    for (Pass = 1; Pass < n; Pass++) { 
     for (j = 0; j < n - Pass; j++) { 
      if (strcmp(a[j], a[j + 1]) < 0) 
       swap(a[j], a[j + 1]); 
     } 
     printf("\nPass = %d\n", Pass); 
     for (i = 0; i < n; i++) 
      printf(" %s", a[i]); 
     printf("\n"); 
    } 
    return 0; 
}