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 :

Position d'un caractère


Sujet :

C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut Position d'un caractère
    Bjour tous,

    j'ai un souci avec une fonction type strpos de php que j'ai faite en C. Elle doit retourner la position d'un caractère dans une chaine. La voici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int substrlen (char *chaine, char *car)
    {
     return (strstr (chaine, car) - chaine);
    }
    Je dois en fait retrouver la position d'un retour chariot dans une chaine pour modifier le caractère (en fait, un header http que je dois couper en lignes). Jusque là, pas de problème, ma fonction me retrouve bien la position de mon caractère. Sauf que, quand j'essaye de modifier mon caractère, je me prends une erreur de segmentation en pleine figure (aïeuhhh, ça picote). Ca ressemble à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char *data = mon_header_http ;
    int i = substrlen (data, "\n");
    strncpy (data+i, "\0", 1) ;
    Quand je change la valeur de i pour mettre un bête chiffre, ça fonctionne.

    J'arrive pas du tout où ça bloque. Quelqu'un de plus expérimenté voir mon erreur ? J'espère que je suis clair

    Merci d'avance

    Enjoy

    The lsd

  2. #2
    Membre éclairé
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Points : 842
    Points
    842
    Par défaut
    Est-ce que tu as alloué de la mémoire pour 'data' ?
    Si tu as affecté une chaîne telle quelle à ton pointeur 'data' il est normal que tu aies une erreur de segmentation parce que la chaîne pointée n'est pas modifiable.

    Pourquoi tu utilises strstr et pas strchr ? strchr recherche 1 caractère dans ta chaîne, strstr recherche une chaîne dans une autre.

    Plutôt que d'utiliser strncpy tu pourrais tout simplement affecter ta valeur : data[i] = '\0';
    Plus tu pédales moins fort, moins t'avances plus vite.

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Pouet_forever Voir le message
    Est-ce que tu as alloué de la mémoire pour 'data' ?
    Si tu as affecté une chaîne telle quelle à ton pointeur 'data' il est normal que tu aies une erreur de segmentation parce que la chaîne pointée n'est pas modifiable.
    ben je l'ai affecté, euhhh oui normalement... 'fin je pense quoi ! Vu que quand je modifie la chaine en mettant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int i = 20;
    strncpy (data+i, "\0", 1) ;
    la chaîne data est bien modifiée. Donc ça devrait être bon. Et je vais poser la question alakon, comment je l'alloue, avec malloc ? Sauf que je connais pas la taille de ma chaine, donc c'pas pratique.


    Citation Envoyé par Pouet_forever Voir le message
    Pourquoi tu utilises strstr et pas strchr ? strchr recherche 1 caractère dans ta chaîne, strstr recherche une chaîne dans une autre.
    Parce que ! C'est le première que j'ai trouvé, donc j'ai pris celle ci :p Mais bon, je vais surement avoir besoin de trouver \r, \n, ou \r\n, donc ça dérange pas.


    Citation Envoyé par Pouet_forever Voir le message
    Plutôt que d'utiliser strncpy tu pourrais tout simplement affecter ta valeur : data[i] = '\0';
    C'est pas un peu crade comme méthode, ça fait pas propre je trouve, mais je me trompe peut être ?

    Enjoy

    The lsd

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 697
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 697
    Points : 30 996
    Points
    30 996
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par the lsd Voir le message
    ben je l'ai affecté, euhhh oui normalement... 'fin je pense quoi ! Vu que quand je modifie la chaine en mettant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int i = 20;
    strncpy (data+i, "\0", 1) ;
    la chaîne data est bien modifiée. Donc ça devrait être bon.
    Ouch cte lacune. En partant comme ça tu vas droit au mur.
    Pour gagner en rapidité, le C ne vérifie jamais rien, partant du principe que "le programmeur sait ce qu'il fait". Ce qui t'autorise donc, en terme de code, à écrire 15 int dans un tableau de 10. Les 5 autres iront écraser une autre variable.
    Donc ça compilera, ça pourra même marcher un temps. Mais un jour ou l'autre...

    C'est à toi de toujours t'assurer que ce que tu stockes a bien la place d'être stocké. Et que si tu tapes dans tab[n] alors n est bien inclus dans les limites du tableau.

    Citation Envoyé par the lsd Voir le message
    Et je vais poser la question alakon, comment je l'alloue, avec malloc ? Sauf que je connais pas la taille de ma chaine, donc c'pas pratique.
    2 solutions
    1) tu connais pas la taille mais tu peux la connaitre (par le biais d'une fonction d'info quelconque) donc tu fais char *chaine=malloc(n * sizeof(char))
    2) tu connais pas la taille et tu ne peux pas la connaitre. Alors il te faut programmer un algo de ce genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    déclarer un char *chaine=NULL, un size_t taille_allouée=0 et un size_t indice=0
    tant que lecture 1 caractère ok
    faire
        si indice=taille_allouée
        alors
              augmenter taille_allouée de B caractères
              chaine=realloc(chaine, taille_allouée * sizeof(char))
        fin si
     
        chaine[indice]=caractère_lu
        indice++
    fin faire
    De cette façon, t'es toujours sûr d'avoir assez de mémoire. Et en utilisant des tampons de taille "B" ça évite les realloc (lourds) à chaque fois que tu dois insérer un élément (surtout que tu peux, si tu le désires quand-même, positionner B à 1). Et en initialisant ton tableau à NULL et tes variables à 0, t'es sûr que t'auras un premier malloc avant toute insertion (le premier if est forcément vrai et quand le tableau initial est à NULL, realloc se comporte comme malloc).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ouch cte lacune. En partant comme ça tu vas droit au mur.
    Pour gagner en rapidité, le C ne vérifie jamais rien, partant du principe que "le programmeur sait ce qu'il fait". Ce qui t'autorise donc, en terme de code, à écrire 15 int dans un tableau de 10. Les 5 autres iront écraser une autre variable.
    Donc ça compilera, ça pourra même marcher un temps. Mais un jour ou l'autre...

    C'est à toi de toujours t'assurer que ce que tu stockes a bien la place d'être stocké. Et que si tu tapes dans tab[n] alors n est bien inclus dans les limites du tableau.
    Ouais, je sais ça, mais je suis toujours dans les bornes de ma variables, puisque i est forcément inférieur au nombre de caractère de data. Donc ça devrais forcément être bon.

    Citation Envoyé par Sve@r Voir le message
    2 solutions
    1) tu connais pas la taille mais tu peux la connaitre (par le biais d'une fonction d'info quelconque) donc tu fais char *chaine=malloc(n * sizeof(char))
    2) tu connais pas la taille et tu ne peux pas la connaitre. Alors il te faut programmer un algo de ce genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    déclarer un char *chaine=NULL, un size_t taille_allouée=0 et un size_t indice=0
    tant que lecture 1 caractère ok
    faire
        si indice=taille_allouée
        alors
              augmenter taille_allouée de B caractères
              chaine=realloc(chaine, taille_allouée * sizeof(char))
        fin si
     
        chaine[indice]=caractère_lu
        indice++
    fin faire
    De cette façon, t'es toujours sûr d'avoir assez de mémoire. Et en utilisant des tampons de taille "B" ça évite les realloc (lourds) à chaque fois que tu dois insérer un élément (surtout que tu peux, si tu le désires quand-même, positionner B à 1). Et en initialisant ton tableau à NULL et tes variables à 0, t'es sûr que t'auras un premier malloc avant toute insertion (le premier if est forcément vrai et quand le tableau initial est à NULL, realloc se comporte comme malloc).
    Bon, ça ok, je sais faire. Mais est ce qu'il faut que je le fasse quand même pour mon char *data ?

    Enjoy

    The lsd

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Bon, alors, après plusieurs tests, je suis heureux de vous apprendre que... rien n'a changé, ça ne fonctionne toujours pas. malloc ou pas, strncpy ou directement avec data[i].
    Ca ne peut venir que de ma fonction substrlen. Quand je la change, pour mettre return 20 par exemple, tout va bien. Mais je vois pas d'erreur dans cette fonction. Quelqu'un en voit une ?

    Enjoy

    The lsd

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Quelqu'un en voit une ?
    Une énorme, oui ! Tu ne vérifies pas si strstr retourne NULL ou pas dans ta fonction. Il ne faut jamais partir du principe que le caractère ou la sous-chaîne à rechercher sera forcément trouvé(e). Car sinon on court à la catastrophe...

    ~~~~~~~~~~

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char *data = mon_header_http ;
    int i = substrlen (data, "\n");
    strncpy (data+i, "\0", 1) ;
    Pourquoi t'embêter à compliquer les choses alors qu'il y a plus simple ? Ca alourdit inutilement le code et les ressources. Et côté optimisation c'est pas terrible.

    Tu peux faire quelque chose comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char *cherche_caractere ;
    cherche_caractere = strchr(mon_header_http , '\n');
    if ( cherche_caractere != NULL )
      *cherche_caractere = '\0' ;
    Ca économise déjà un appel de fonction, le code est plus simple et plus lisible.
    A partir de là, aucun bug possible, sauf si ton '\0' de fin de chaîne dépasse les limites de ta chaîne ou alors si mon_header_http pointe n'importe où (et là, on ne peut pas deviner, vu qu'on n'a pas le code). Donc, si strchr crashe ou si le programme a un comportement bizarre (style, si des variables changent de valeur sans raison apparente), tu sauras pourquoi...

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Bon, ok effectivement, vu sous cet angle, mon code est un peu compliqué. J'ai essayé ta solution, tout fonctionne correctement.

    En fait, c'est moi qui ai été un peu bête ! strstr me renvoyait forcément un NULL, mais avec tout le flot de données, il passait inaperçu...

    Je mets donc en résolu.

    Merci à vous 3 !

    Enjoy

    The lsd

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

Discussions similaires

  1. Syntaxe de recherche de position d'un caractère ???
    Par toyyo dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 01/07/2011, 09h30
  2. Réponses: 4
    Dernier message: 09/09/2009, 10h59
  3. Réponses: 3
    Dernier message: 03/04/2008, 15h29
  4. Réponses: 2
    Dernier message: 19/11/2007, 16h53
  5. Réponses: 6
    Dernier message: 20/02/2006, 22h13

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