1
votes

Comment concaténer des pointeurs char en utilisant strcat en c?

J'apprends les pointeurs en C, sous Linux. J'essaye d'utiliser la fonction strcat , mais cela ne fonctionne pas et je ne comprends pas pourquoi.

Je passe un nom d'utilisateur au main comme argument car je dois concaténer et mettre un chiffre 1 en première position de ce nom d'utilisateur. Par exemple, si j'ai comme argument username123 , je dois le convertir en 1username123

J'ai ce code:

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

int main(int argc, char *arg[]){
    const char *userTemp;
    char *finalUser;

    userTemp = argv[1]; //I got the argument passed from terminal
    finalUser = "1";
    strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
    printf("User: %s\n",finalUser);

    return 0;
}

Le code se compile, mais j'ai une erreur de segmentation et je ne sais pas pourquoi. Pouvez-vous m'aider à aller dans la bonne direction?


1 commentaires

Le premier argument dans strcat , finalUser dans ce cas, doit pointer l'adresse mémoire qui est mutable et suffisamment grande pour contenir le résultat. puisque vous ne pouvez pas muter le contenu de l'adresse mémoire où "1" est stocké, il obtient une erreur de segmentation.


4 Réponses :


-1
votes

Il vous manque quelques notions de base sur C.

char finalUser[32];
finalUser[0] = '1';

Ceci est créé en mémoire "en lecture seule". Vous ne pouvez pas muter cela. Le premier argument de strcat requiert de la mémoire allouée pour la mutation, par exemple

finalUser = "1";


1 commentaires

Vous ne devriez jamais utiliser de tampons de taille fixe, sauf si vous contrôlez ce que vous y mettez.



-1
votes

Contrairement à d'autres langues, il n'y a pas de type de chaîne réel dans C.

Vous voulez ceci:

int main(int argc, char *arg[]){
  if (argc != 2)
  {
     printf("you need to provide a command line argument\n");
     return 1;
  }
  ...

ou encore plus simple:

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

int main(int argc, char *arg[]){
    char finalUser[100];   // finalUser can contain at most 99 characters
    strcpy(finalUser, "1");    // copy "1" into the finalUser buffer
    strcat(finalUser, argv[1]); //To concatenate argv[1] to finalUser
    printf("User: %s\n",finalUser);    
    return 0;
}

Clause de non-responsabilité: par souci de brièveté, ce code contient un tampon de taille fixe et aucune vérification du dépassement de tampon n'est effectuée ici.

Le chapitre traitant des chaînes dans votre livre de texte C devrait couvrir ceci.

BTW, vous devriez également vérifier si le programme est appelé avec un argument:

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

int main(int argc, char *arg[]){
    const char *userTemp;
    char finalUser[100];   // finalUser can contain at most 99 characters

    userTemp = argv[1]; //I got the argument passed from terminal
    strcpy(finalUser, "1");    // copy "1" into the finalUser buffer
    strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
    printf("User: %s\n",finalUser);

    return 0;
}


5 commentaires

Vous ne devriez jamais utiliser de tampons de taille fixe, sauf si vous contrôlez ce que vous y mettez.


Vous devriez corriger cela pour utiliser strncpy ou strncat (ou une autre façon d'éviter le débordement de la mémoire tampon).


Clause de non-responsabilité @paxdiablo ajoutée.


@hyde strncat n'est pas suffisant, si le tampon est trop petit, le texte est simplement tronqué ce qui peut causer d'autres problèmes


@Jabberwocky Souvent vrai, mais dans la plupart des cas, cela empêchera UB, et rendra facile de vérifier si le tampon était rempli (avec 1 tampon de plus que la taille requise, c'est un moyen facile de détecter des chaînes trop longues). Souvent, quelle que soit l'API ou la base de données qui a une taille maximale pour la chaîne, l'utilisation d'une chaîne dynamique dans le code utilisateur n'est généralement pas suffisante non plus.



2
votes

J'essaie d'utiliser la fonction strcat, mais cela ne fonctionne pas et je ne comprends pas pourquoi.

Pour commencer, vous ne devriez pas utiliser strcat () . Utilisez plutôt strlcat () . La version "l" de cette fonction et d'autres fonctions prennent un paramètre supplémentaire qui vous permet d'indiquer à la fonction la taille du tampon de destination, afin que la fonction puisse éviter d'écrire au-delà de la fin du tampon. strcat () n'a pas ce paramètre, donc il compte sur vous pour vous assurer que le tampon est suffisamment grand pour contenir les deux chaînes. Il s'agit d'une source courante de problèmes de sécurité dans le code C. La version "l" s'assure également que la chaîne résultante est terminée par un nul.

Le code se compile, mais j'ai une erreur de segmentation et je ne sais pas pourquoi.

Voici le prototype de la fonction: char * strcat (char * dest, const char * src);

Maintenant, vous appelez cela essentiellement comme ceci: strcat ("1", someString); . Autrement dit, vous essayez d'ajouter someString à "1" , qui est une constante de chaîne. Il n'y a pas de place supplémentaire dans "1" pour la chaîne de caractères de someString , et comme vous utilisez une fonction qui écrira avec plaisir au-delà de la fin du tampon de destination, votre le code écrit effectivement sur tout ce qui se trouve en mémoire à côté de cette constante de chaîne.

Pour résoudre le problème, vous devez:

  1. Passez à strlcat () .
  2. Utilisez malloc () ou tout autre moyen pour allouer un tampon de destination suffisamment grand pour contenir les deux chaînes.

3 commentaires

strcat est très bien à condition de savoir à l'avance que vous disposez de suffisamment d'espace. Mais au moins, vous n'avez pas essayé d'utiliser un tampon de taille fixe comme les autres réponses :-)


@paxdiablo Il y a beaucoup de choses qui sont sans doute bien si vous êtes prudent, mais l'OP ici ne sait pas encore à quoi faire attention, donc surtout dans ce contexte, je pense que l'utilisation cohérente de strlcat () < / code> est indiqué.


Gardez simplement à l'esprit que strlcat n'est pas standard. Je sais qu'OP a déclaré Linux, ce qui explique probablement pourquoi vous avez choisi cela plutôt que le strncat inférieur, mais je préfère prendre en charge la portabilité, même si cela signifie que mon code est plus grand :-). Pourtant, votre réponse est bonne.



2
votes

Ce n'est pas un comportement défini en C pour tenter de modifier une chaîne littérale (comme "1" ). Souvent, ceux-ci sont stockés en mémoire non modifiable pour permettre certaines optimisations.

Laissons de côté pour le moment le fait que tout votre programme peut être remplacé par:

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

int main(int argc, char *argv[]){
    // Check args provded.

    if (argc < 2) {
        puts("User: 1");
        return 0;
    }

    // Allocate enough memory ('1' + arg + '\0') and check it worked.

    char *buff = malloc(strlen(argv[1]) + 2); 
    if (buff == NULL) {
        fprintf(stderr, "No memory\n");
        return 1;
    }

    // Place data into memory and print.

    strcpy(buff, "1");
    strcat(buff, argv[1]);
    printf("User: %s\n", buff);

    // Free memory and return.

    free(buff);
    return 0;
}

La façon dont vous vous assurez d'avoir suffisamment d'espace est de créer une mémoire tampon suffisamment grande pour contenir tout ce que vous voulez faire. Par exemple:

#include <stdio.h>
int main(int argc, char *argv[]){
    printf("User: 1%s\n", (argc > 1) ? argv[1] : "");
    return 0;
}

Ce que vous ne devriez pas faire est d'allouer un tampon de taille fixe et de copier aveuglément les données fournies par un utilisateur. C'est ainsi que se produisent la grande majorité des problèmes de sécurité, lorsque des personnes écrasent les tampons avec des données inattendues.


1 commentaires

Essayer d'écrire dans la mémoire protégée est probablement la véritable cause de l'erreur de segmentation, plutôt que de le faire et d'écraser d'autres données. Bon appel là-bas.