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 :

[strtok] marche pas et je sais pas pourquoi


Sujet :

C

  1. #1
    Membre actif
    Inscrit en
    Juin 2002
    Messages
    409
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 409
    Points : 234
    Points
    234
    Par défaut [strtok] marche pas et je sais pas pourquoi
    Bonjour,
    désolé pour le sujet limite, mais c'est parce que je craque.
    Je veux extraire une chaine d'un fichier csv. Ma ligne line est correct en entrée. Ma fonction marche 1 seule fois. A la 2ieme ligne, ça plante et je ne trouve pas pourquoi.

    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    void getAndSetDataFromCSVLine(string line)
    {
        char *ch;
        char separator = ',';
        ch = new char [line.size()+1];
        strcpy(ch,line.c_str());
     
        _date.clear(); _date = strtok(ch,&separator);
        _time.clear(); _time = strtok(NULL,&separator);
        Status1.clear(); Status1 = strtok(NULL,&separator);
        TA_2m_AVG.clear(); TA_2m_AVG = strtok(NULL,&separator);
        Status2.clear(); Status2 = strtok(NULL,&separator);
        RH_2m_AVG.clear(); RH_2m_AVG = strtok(NULL,&separator);
        Status3.clear(); Status3 = strtok(NULL,&separator);
        DP_2m.clear(); DP_2m = strtok(NULL,&separator);
        Status4.clear(); Status4 = strtok(NULL,&separator);
        PA_2m_AVG.clear(); PA_2m_AVG = strtok(NULL,&separator);
        Status5.clear(); Status5 = strtok(NULL,&separator);
        WindSpeed_AVG.clear(); WindSpeed_AVG = strtok(NULL,&separator);
        Status6.clear(); Status6 = strtok(NULL,&separator);
        WindSpeed_MAX.clear(); WindSpeed_MAX = strtok(NULL,&separator);
        Status7.clear(); Status7 = strtok(NULL,&separator);
        WindSpeed_MIN.clear(); WindSpeed_MIN = strtok(NULL,&separator);
        Status8.clear(); Status8 = strtok(NULL,&separator);
        WindDir_AVG.clear(); WindDir_AVG = strtok(NULL,&separator);
        Status9.clear(); Status9 = strtok(NULL,&separator);
        WindDir_MAX.clear(); WindDir_MAX = strtok(NULL,&separator);
        Status10.clear(); Status10 = strtok(NULL,&separator);
        WindDir_MIN.clear(); WindDir_MIN = strtok(NULL,&separator);
    }
    Merci de votre aide.

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    Peut on voir les deux premières lignes du fichiers CSV ?

    A la 2ieme ligne, ça plante et je ne trouve pas pourquoi.
    Peux tu décrire le crash ?

  3. #3
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 369
    Points
    50 369
    Par défaut
    strtok attend une chaine de caractères comme séparateur, pas l'adresse d'un char

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void getAndSetDataFromCSVLine(string line)
    {
        char *ch;
        char * separator = ",";
        ch = new char [line.size()+1];
        strcpy(ch,line.c_str());
     
        _date.clear(); _date = strtok(ch, separator);
    ...

  4. #4
    Membre actif
    Inscrit en
    Juin 2002
    Messages
    409
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 409
    Points : 234
    Points
    234
    Par défaut
    Bonjour,
    Merci pour vos réponses.
    La modif char en char * "," ne change rien. Malheureusement.

    Voici le message d'erreur :
    Process terminated with status -1073741819 (0 minutes, 7 seconds)
    Voici un extrait de mon fichier csv :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    7/27/09,12:00:03 AM,VALID,17.073,VALID,50.501,VALID,6.706,VALID,939.6,VALID,0.876,VALID,1.398,VALID,0.297,VALID,259.0,VALID,300.0,VALID,214.0,
    7/27/09,12:02:03 AM,VALID,16.603,VALID,53.163,VALID,7.021,VALID,939.558,VALID,1.471,VALID,2.297,VALID,0.703,VALID,285.0,VALID,310.0,VALID,260.0,
    7/27/09,12:04:03 AM,VALID,16.601,VALID,50.637,VALID,6.31,VALID,939.508,VALID,1.318,VALID,2.102,VALID,0.5,VALID,272.0,VALID,304.0,VALID,207.0,
    7/27/09,12:06:03 AM,VALID,16.968,VALID,49.363,VALID,6.278,VALID,939.5,VALID,1.208,VALID,2.203,VALID,0.5,VALID,250.0,VALID,278.0,VALID,210.0,
    7/27/09,12:08:03 AM,VALID,16.857,VALID,51.553,VALID,6.807,VALID,939.45,VALID,1.608,VALID,3.5,VALID,0.297,VALID,274.0,VALID,351.0,VALID,224.0,
    Je ne comprends vraiment pas. Le premier appel passe sans problème et ça plante lors du deuxième appel.

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 369
    Points
    50 369
    Par défaut
    Tu as remplacé le "&separator" par "separator" dans les autres appels à strtok() aussi ?

  6. #6
    Membre actif
    Inscrit en
    Juin 2002
    Messages
    409
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 409
    Points : 234
    Points
    234
    Par défaut
    Oui oui,

    Voici l'appel de la fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    (...openfile...)
            while(! inputStream.eof())
            {
                currentLine.clear();
                getline(inputStream, currentLine);
                getAndSetDataFromCSVLine(currentLine);
                (...)
            }
    La boucle passe bien en revue toutes les lignes de mon fichier. J'ai vérifié. L'état de la variable currentLine est OK avant l'appel de getAndSetDataFromCSVLine.

    Voici le nouveau code de getAndSetDataFromCSVLine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    void getAndSetDataFromCSVLine(string &line)
    {
        char *ch;
        char *separator = ",";
        ch = new char [line.size()+1];
        strcpy(ch,line.c_str());
     
        _date.clear(); _date = strtok(ch,separator);
        _time.clear(); _time = strtok(NULL,separator);
        Status1.clear(); Status1 = strtok(NULL,separator);
        TA_2m_AVG.clear(); TA_2m_AVG = strtok(NULL,separator);
        Status2.clear(); Status2 = strtok(NULL,separator);
        RH_2m_AVG.clear(); RH_2m_AVG = strtok(NULL,separator);
        Status3.clear(); Status3 = strtok(NULL,separator);
        DP_2m.clear(); DP_2m = strtok(NULL,separator);
        Status4.clear(); Status4 = strtok(NULL,separator);
        PA_2m_AVG.clear(); PA_2m_AVG = strtok(NULL,separator);
        Status5.clear(); Status5 = strtok(NULL,separator);
        WindSpeed_AVG.clear(); WindSpeed_AVG = strtok(NULL,separator);
        Status6.clear(); Status6 = strtok(NULL,separator);
        WindSpeed_MAX.clear(); WindSpeed_MAX = strtok(NULL,separator);
        Status7.clear(); Status7 = strtok(NULL,separator);
        WindSpeed_MIN.clear(); WindSpeed_MIN = strtok(NULL,separator);
        Status8.clear(); Status8 = strtok(NULL,separator);
        WindDir_AVG.clear(); WindDir_AVG = strtok(NULL,separator);
        Status9.clear(); Status9 = strtok(NULL,separator);
        WindDir_MAX.clear(); WindDir_MAX = strtok(NULL,separator);
        Status10.clear(); Status10 = strtok(NULL,separator);
        WindDir_MIN.clear(); WindDir_MIN = strtok(NULL,separator);
    }
    L'état de la variable line en entrée est OK !

  7. #7
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Que se passe-t-il entre le premier et le deuxième appel (et les suivants) ?
    C'est à dire qu'y a-t-il comme traitement?
    Je n'ai pas vu de delete ch; à la fin de votre fonction.
    Dans ce cas d'un fichier CSV, on a une idée très précise de la longueur de la ligne. Donc, je ferais 2 modifs
    1- ne pas faire de fonction getAndSetDataFromCSV() mais mettre cela dans la fonction d'appel
    2- faire ch[128]; (par exemple) au lieu d'utiliser new
    Toutes les valeurs lues sont donc en global, ce n'est pas une bonne idée. Il vaut mieux faire une structure qui contienne toutes ces valeurs, et pour vous en servir, il suffit de passer la structure par référence ou avec un pointeur sur cette structure.

    Suite,
    Vos variables dont des string. Etes-vous sûr que vous avez le droit de un "string" = "pointeur sur chaine"? En fait je suis sûr que le problème est là.
    Il ne me parait pas très sain d'utiliser strtok() et string sans faire un transtypage de sécurité. Autrement dit la fonction inverse de c_str()
    Dernière modification par Invité ; 20/09/2010 à 16h50.

  8. #8
    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
    @ kase74 :
    Tu mélanges du C et du C++...

  9. #9
    Membre actif
    Inscrit en
    Juin 2002
    Messages
    409
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 409
    Points : 234
    Points
    234
    Par défaut
    SUPER !!!
    Merci Pierre tu m'as mis sur la piste.
    Effectivement, j'avais oublié tous les delete. Dans mon traitement, il y avait aussi des char* sans delete. Du coup certainement qu'il devait y avoir un effet de bord quelque part. Heu je crois que c'est ça qu'on appel un effet de bord

    Pfff. Il y avait très longtemps que je n'avais pas codé en C/C++. Ben c'est quand même pas de la tarte, j'oublie trop vite

  10. #10
    Membre actif
    Inscrit en
    Juin 2002
    Messages
    409
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 409
    Points : 234
    Points
    234
    Par défaut
    Citation Envoyé par jeroman Voir le message
    @ kase74 :
    Tu mélanges du C et du C++...
    En fait, j'avais essayé tout en C++, avec un istringstream et un getline, mais comme ça ne marchait pas ... j'ai tenté plusieurs choses.
    Maintenant que ça marche je n'y touche plus.

    Moi ça ne me choque pas de mélanger les deux. De toute façon, sauf erreur, les routines C++ font bien appel à du pur C, non ?

  11. #11
    Membre actif
    Inscrit en
    Juin 2002
    Messages
    409
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 409
    Points : 234
    Points
    234
    Par défaut
    Citation Envoyé par Pierre Dolez Voir le message
    Bonjour,
    1- ne pas faire de fonction getAndSetDataFromCSV() mais mettre cela dans la fonction d'appel
    2- faire ch[128]; (par exemple) au lieu d'utiliser new
    3 -Toutes les valeurs lues sont donc en global, ce n'est pas une bonne idée. Il vaut mieux faire une structure qui contienne toutes ces valeurs, et pour vous en servir, il suffit de passer la structure par référence ou avec un pointeur sur cette structure.
    1 - J'ai un gros traitement donc j'ai voulu faire propre.
    2 - Pas possible car les lignes du fichier csv ne font pas toute la même longueur. Pour le même champ, j'ai parfois des flottant à 1, 2 ou 3 décimal.
    3 - Entièrement d'accord. C'est un tout petit exécutable (total 200 lignes). J'ai voulu faire vite. Mais comme d'hab, le temps de me remettre dans le bain le "vite fais-bien fait" a durée plus longtemps que prévu. Mais c'est vrai que j'aurais dû faire quand même une structure. Méa culpa !

    Encore merci à tous pour votre aide.

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

Discussions similaires

  1. [XL-2007] une formule dans une macro ne fonctionne pas je ne sais pas quel est le problème
    Par skipeemed dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 24/11/2010, 13h59
  2. je ne sais pas pourquoi ce code ne marche pas!
    Par hindou90 dans le forum C
    Réponses: 3
    Dernier message: 15/01/2010, 11h59
  3. je ne sais pas pourquoi ça marche pas ce code ?
    Par hafa81 dans le forum Débuter
    Réponses: 2
    Dernier message: 13/01/2010, 22h23
  4. je ne sais pas pourquoi ce code ca marche pas
    Par debutantasp dans le forum ASP
    Réponses: 14
    Dernier message: 23/11/2007, 18h10
  5. Réponses: 18
    Dernier message: 07/10/2007, 00h03

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