IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

strcat efface le début de chaine


Sujet :

C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 5
    Points : 2
    Points
    2
    Par défaut strcat efface le début de chaine
    Bonjour,

    Ca fait plusieurs heures que je m'arrache les cheveux sur ces lignes de codes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        nvarc.nomArc = malloc(sizeof(char)*(strlen(src.nomSommet)+strlen(arr.nomSommet)+4));
     
        strcpy(nvarc.nomArc,src.nomSommet);
        strcat(nvarc.nomArc, " -> ");
        strcat(nvarc.nomArc,arr.nomSommet);
     
        printf("nvarc : %s\n",nvarc.nomArc);
    Mes variables src et arr sont cohérentes mais si j'ai par exemple :
    src.nomSommet ="test"
    arr.nomSommet = "blabla"

    je vais me retrouver avec un résultat égal à " -> blablatest" alors que je devrais avoir "test -> blabla". Si je remplace " -> " par "\t->\t" , je vais avoir quelques caractères de la première chaine puis "->" puis la seconde chaine. Il y a donc un écrasement.

    Et lors d'un affichage préalable de src et arr, je trouve des chaines tout à fait cohérentes.

    A quoi cela peut il être dû ? J'ai pensé à un \0 présent en début de chaine sur src.nomSommet qui ferait planter le strcat mais je suppose que dans ce cas là, un printf("%s", src.nomSommet) ne fonctionnerait pas... Hors tout roule.

    Remplacer le strcpy par nvarc.nomSommet = src.nomSommet me crée la même erreur.

    Remplacer les valeurs de src.nomSommet par une valeur en dur fonctionne (strcpy(nvarc.nomSommet , "test")).

    Le nom d'un sommet est créé par cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    struct Sommet nouveauSommet(char *s)
    {
        struct Sommet res;
        res.nomSommet= malloc(sizeof(char)*strlen(s)+1);
        strcpy(res.nomSommet,s);
     
        return res;
    }
    qui prend en paramètre une chaine d'un fichier traité avec la fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void clearChaine(char* s)
    {
        char *pch = strrchr(s, '\n');
        if (pch) {
           *pch = '\0';
        }
    }
    pour enlever le retour ligne.

    Je ne pense pas pouvoir donner plus de détails pertinents que ça.

    Merci d'avoir lu jusque là

  2. #2
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bonsoir.
    Étrange, en effet...

    À tout hasard, tu travailles sous quel OS ?
    Et le fichier a été écrit avec quelle norme de fin de ligne ?

    Tu peux essayer d'utiliser sprintf à la place de de strcpy et strcat, histoire de voir si ça change quelque chose.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sprintf(nvarc.nomArc, "%s -> %s", src.nomSommet, arr.nomSommet);
    Ou tu peux mettre d'abord le premier caractère de nvarc.nomArc à '\0' et ne faire que des strcat...


    Sinon...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nvarc.nomArc = malloc(sizeof(char)*(strlen(src.nomSommet)+strlen(arr.nomSommet)+4));
    Ta chaîne intermédiaire fait 4 caractères de long.
    Tu as donc oublié le caractère '\0' final dans ton décompte.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    res.nomSommet= malloc(sizeof(char)*strlen(s)+1);
    C'est soit sizeof(char) * (strlen(s) + 1), soit strlen(s) + 1, mais ne mélange pas les deux.

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 862
    Points : 219 061
    Points
    219 061
    Billets dans le blog
    120
    Par défaut
    Pour plus de précaution, je remplacerai malloc par un calloc.

    De plus, il faut tester si malloc (ou calloc) ne retourne pas un pointeur NULL (aucun effet sur ce problème, mais je le dis).
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    Merci pour l'aide mais pas d'amélioration avec sprintf.

    Voici le code + affichage :

    Le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    printf("src.nomSommet : %s\n", src.nomSommet);
    printf("arr.nomSommet : %s\n", arr.nomSommet);
     
    sprintf(nvarc.nomArc, "%s -> %s", src.nomSommet, arr.nomSommet);
     
    printf("nvarc : %s\n",nvarc.nomArc);
    L'affichage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    src.nomSommet : Si (flag==1)
    arr.nomSommet : res = 3-res;
     -> res = 3-res;==1)
    (on peut voir qu'il y a un souci avec le flux de sortie, (?)))

    PS : j'ai modifié les autres erreurs signalées et essayé avec calloc sans plus de succès. Intéressant calloc, je ne connaissais pas encore.

    EDIT : je viens de me rendre compte qu'avec un affichage ultérieur, on obtenait " -> res = 3-res;" ce qui n'est toujours pas la solution.

  5. #5
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Juste par curiosité, ça donne quoi ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%s -> %s\n", src.nomSommet, arr.nomSommet);

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    Je ne peux pas test ici, je regarde ça ce soir.

    J'ai peut être trouvé, il manquait un +1 à un malloc, ce qui peut expliquer l'absence d' \0 dans src.nomSommet

    Je teste ça dès que je peux, merci de m'avoir fait remarquer l'erreur sur le malloc

  7. #7
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Points : 2 505
    Points
    2 505
    Par défaut
    Citation Envoyé par sildar Voir le message
    J'ai peut être trouvé, il manquait un +1 à un malloc, ce qui peut expliquer l'absence d' \0 dans src.nomSommet
    Steph_ng8 te l'avait signalé dans la 1ère réponse...

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    Yep, d'où "je te remercie de m'avoir fait remarqué l'erreur sur le malloc". Une erreur similaire était présente sur la déclaration du nomSommet.

    Mais finalement l'erreur ne venait pas de là (même si ça restait une erreur à enlever).
    En passant en pas à pas, j'ai fini par voir qu'un \r se trouvait à la fin de mes chaines et une fois enlevé, tout est rentré dans l'ordre. C'est d'ailleurs en écrivant ces lignes que je me rends compte de ce que fait le \r :p (première fois que je le rencontre).

    Bref, erreur difficile à trouver, même en ayant le code. Merci en tout cas pour votre aide à tous.

    EDIT : je n'avais pas répondu à toutes les questions, mais je programme sous Linux et je n'ai pas testé le printf() du coup vu que ça à l'air de fonctionner. Le \r faisait bug l'affichage visiblement, et peut être que le +1 du malloc oublié ajoutait son grain de sel dans les affichages postérieurs. Je n'ai pas retesté chacun séparément.

  9. #9
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Le caractère '\r', « carriage return » ou « retour chariot », sert à ramener le curseur au début de la ligne.
    Comme sur les machines à écrire où, lorsqu'on voulait taper en début de ligne, il fallait faire revenir le chariot à la position la plus à droite...

    Selon le système d'exploitation, il n'a pas tout à fait le même effet.
    Sous Windows et UNIX, il fait revenir le curseur en début de ligne, mais sous MAC, il le fait en plus passer à la ligne suivante.

    Comme tu le sais sans doute, les systèmes d'exploitation ne sont pas d'accord sur la manière d'indiquer qu'il faut passer à la ligne.
    Mais ils se basent tous sur une combinaison des caractères '\r' et '\n'new line » / « line feed ») :
    • Windows "\r\n" ;
    • UNIX : '\n' ;
    • MAC : '\r'.

    C'est pour cette raison que je te demandais sur quel OS tu travailles, et avec quelle convention de marquage de fin de ligne le fichier avait été écrit.

    Je soupçonnais ton fichier d'utiliser la convention Windows, mais vu que les affichages fonctionnaient normalement, j'avais un doute...

    Voilà.
    Bonne continuation.

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    On travaille en binôme, mon binôme avait créé le fichier sous windows, moi, je travaille uniquement sous linux (oui, pratique je sais...).

    Merci pour les précisions, je connaissais le fonctionnement du \r, pas son utilisation dans les différents systèmes d'exploitation.

  11. #11
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 862
    Points : 219 061
    Points
    219 061
    Billets dans le blog
    120
    Par défaut
    Citation Envoyé par sildar Voir le message
    On travaille en binôme, mon binôme avait créé le fichier sous windows, moi, je travaille uniquement sous linux (oui, pratique je sais...).

    Merci pour les précisions, je connaissais le fonctionnement du \r, pas son utilisation dans les différents systèmes d'exploitation.
    Pour la conversion il existe dos2unix ... qui a changé de nom depuis Ubuntu 10.04 et que j'ai encore oublié le nom. Ah si, "fromdos".
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 16/03/2007, 15h25
  2. [i18n]Espace en début de chaine
    Par plegat dans le forum NetBeans
    Réponses: 3
    Dernier message: 20/11/2006, 22h17
  3. [Expression régulière] Début de chaine
    Par navis84 dans le forum Oracle
    Réponses: 8
    Dernier message: 10/10/2006, 13h52
  4. RegExp: Récupérer une valeur en début de chaine
    Par pekka77 dans le forum Langage
    Réponses: 8
    Dernier message: 23/08/2006, 16h07
  5. Suppresion d'un caractère NULL en début de chaine
    Par GingGing dans le forum Delphi
    Réponses: 5
    Dernier message: 10/08/2006, 09h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo