2017-07-13 5 views
1

Je continue d'obtenir une erreur de segmentation lorsque j'essaie d'ajouter un caractère au test de chaîne. J'ai essayé plusieurs itérations et je n'arrive pas à comprendre pourquoi j'ai l'erreur. J'ai essayé d'avoir le test mis à \0. Je n'arrive pas à comprendre comment j'accède aux tests externes.Erreur de segmentation en C lors de la tentative de concaténation d'une chaîne et d'un caractère

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

#define _XOPEN_SOURCE 
#include <unistd.h> 
#include <crypt.h> 

//this intializes the argument count and argument vector 
int main(int argc, string argv[]) { 
    //this makes sure it is a string 
    if (argv[1] != NULL) { 
     //this makes sure that the user typed 2 arguments, 
     // the second being the keyword 
     if (argc != 2) { 
      printf("no hash inputed\n"); 
      return 1; 
     } 

     //main program once the keyword has been verified 
     int h_len = strlen(argv[1]); 
     string hash = argv[1]; 
     string test = "A"; 
     int p_len = 0; 
     printf("H len is %i and P len is %i\n", h_len, p_len); 
     printf("%s and test: %s\n", hash, test); 

     //this will iterate through the 1st space and test the charachters 
     for (int j = 0; j < 4; j++) { 

      //iterates through the characters that can be used in the password 
      //for (int i = A; i < z; i++) 
      //for (char ch = 'A' ; ch <= 'z' ; ch == 'Z' ? ch = 'a' : ++ch) 
      for (char i = 'A'; i <= 'z'; i++) { 
       //this skips the ASCII inbetween Z and a 
       if (i > 'Z' && i < 'a') { 
        i = 'a'; 
       } 
       printf("%c", i); 
       //test[j] = test[j] + (char)i; 
       test = strncat(test, &i, 1); 
       printf(" test is %s\n", test); 
       ... 
+3

Vous devez vérifier 'argc' _before_ vous avez accès' argv [1] '. –

+1

Vous avez alloué un caractère à tester et vous avez essayé de l'ajouter. – Spaceghost

+1

Le code a '// cela s'assure que l'utilisateur a tapé 2 arguments'. Ceux-ci seront dans 'argv [1]' et 'argv [2]' sauf si vous les mettez entre guillemets, par exemple '' un deux '', quand ils seront passés au même argument. Mais le code a 'if (argc! = 2)' qui teste un seul argument ** utilisateur ** - le premier est le nom de l'exécutable. –

Répondre

-1

tout est faux ici

vous ne pouvez pas strcat char * et l'adresse du char comme vous ne savez jamais s'il est nul après ce caractère. Votre chaîne est trop courte pour pouvoir contenir plus d'une chaîne de caractères. Ensuite, vous essayez de faire quelque chose avec la mémoire RO puisque votre test pointe vers le littéral de chaîne.

Acheter un bon livre sur C

+0

'strncat' fonctionne si vous passez 1 n'a pas besoin de null-terminator. Et la chaîne est trop courte mais surtout c'est un pointeur pas un tableau donc segfault quelle que soit la taille –

+0

ouais je pensais que c'est strcat –

+1

@ Jean-FrançoisFabre: plus précisément, il a un comportement indéfini car il pointe vers un * chaîne littérale *. – chqrlie

0

Vous avez une chaîne avec un caractère en elle (test = « A ») il a une longueur de 2 (A + nul char) et essayez d'ajouter d'autres caractères à lui, donc il va accéder en dehors du test.

+1

Réponse incomplète. 'test' pointe vers un littéral de chaîne: tenter de le modifier a un comportement indéfini quand même. – chqrlie

4

Dans cette déclaration

string test = "A"; 

il est déclaré le pointeur test à la chaîne littérale "A". Vous ne pouvez pas modifier les littéraux de chaîne.

Selon la norme C (6.4.5 Les littéraux chaîne)

7 Il est précisé si ces matrices sont distinctes fournies leurs éléments ont les valeurs appropriées. Si les tentatives de programme à modifier un tel tableau, le comportement est indéfini

Cependant, dans cette déclaration

test = strncat(test, &i,1); 

il y a une tentative de modifier la chaîne littérale pointée par le pointeur test.

Vous devez déclarer un tableau de caractères disposant de suffisamment d'espace pour stocker des caractères supplémentaires.

En outre, si vous utilisez la fonction strncat pour copier n caractères de la chaîne de source que vous devez réserver la mémoire dans le tableau de destination pour n + 1 caractères parce que la fonction toujours la terminaison ajoute zéro.

Cela est (la norme C, 7.23.3.2 La fonction strncat, note 302)

302) Ainsi, le nombre maximum de caractères qui peuvent se retrouver dans la matrice pointée par s1 est strlen (s1) + n + 1.

+1

@chux Pour clarifier j'ai ajouté la note avec une note de bas de page de la norme. :) –

+0

Cette note de bas de page a non seulement ajouté de la clarté ici, mais m'a amené à revoir divers articles que j'ai faits au fil des ans. – chux

+1

@chux: oui, 'strncat()' est beaucoup plus acceptable que 'strncpy() '. C'est en fait une manière décente d'implémenter une copie de chaîne tronquée: 'char dest [10] =" "; strncat (dest, src, sizeof (dest) - 1); ' – chqrlie

1

Notez que dans cette CS50 horrible, string est défini comme char *, donc string test = "A"; est équivalent à char *test = "A"; qui fera le point de test à une constante chaîne de longueur 1 plus un nul!Donc, même si ce serait assez long pour concaténer quelque chose, vous ne pouvez pas parce que c'est en lecture seule, et même si ce n'était pas en lecture seule, vous ne pouvez pas parce que ce n'est pas assez long.