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 :

Manipuler une chaîne de caractères


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 374
    Points : 47
    Points
    47
    Par défaut Manipuler une chaîne de caractères
    Bonsoir à tous,

    En ce moment je fais l'acquisition d'une chaine de caractère depuis un fichier.txt dont voici le format :

    Ceci se répète ligne par ligne 1023 fois : J'essaie d'isoler le nombre suivant : Ainsi, Je pensais utiliser ce 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
     
        int w=0;
        int y=0;
        int k3=0;
        char don_nanometre_char[1023][50];
        char donnee[1023][50];
     
        for (y=0 ; y<=1023 ; y++)
        {
            k3=0;
            for (w=0 ; w<=36 ; w++)
            {
                if (w>=26)
                {
                    don_nanometre_char[y][k3]=donnee[y][w];
                    k3++;
                }
            }
     
        }
    Je me trouve face à un problème en début du code : don_nanometre_char[0]=0.360000 au lieu de 336.668600 .

    ------------------------

    Dans le même esprit de manipulation de chaînes de caractères, j'ai le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int w=0;
    int k2=0;
    char donnee_stock[1039][50];
    char donnee[1023][50];
     
    for (w=0 ; w<=1039 ; w++)
        {
            if (w>14){
                strcpy(donnee[k2],donnee_stock[w]);
                k2++;
        }
    J'aimerais obtenir ne garder que les 1024 valeurs de fin de donnee_stock[w].
    Ce code fonctionne mais je ne trouve pas ça très "optimal".

    Si vous avez des propositions pour le premier code qui me pose plus de problème.

    Pour indication, je travail sous QtCreator en C++.

    Bonne soirée à tous

  2. #2
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,
    Citation Envoyé par joffrey575 Voir le message
    Pour indication, je travail sous QtCreator en C++.
    Et pourtant ton code ressemble plus à du C qu'autre chose.

    std::vector / std::array (ou équivalent Qt) sont préférables aux tableaux type C.
    std::string (ou QString) est préférable à un char[].

    Sinon les flux permettent de faire ce que tu cherches facilement
    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
    struct Line {
    	double a, b;
    };
     
    std::istream& operator>>(std::istream& is, Line& line) {
    	return is >> line.a >> line.b;
    }
     
    std::ostream& operator<<(std::ostream& os, Line const& line) {
    	return os << line.a << " " << line.b;
    }
     
    std::ifstream is("data.txt");
     
    std::vector<Line> lines;
    Line l;
     
    // lecture du fichier
    while(is >> l) {
    	lines.push_back(l);
    }
     
    // affichage
    for(auto const& l: lines) {
    	std::cout << l << '\n';
    }
    edit : au passage, attention à tes boucles. Tu fais une itération de trop et tu touches à de la mémoire qui n'appartient plus à tes tableaux.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 374
    Points : 47
    Points
    47
    Par défaut
    Oui, jusqu'ici j'ai codé en C.

    Effectivement je vais peut être devoir coder en C++.

    Ton concept est bon, j'ai décortiqué ton programme avec un livre C++.

    Le compilateur gcc 64 bits est moins d'accord sous QtCreator :

    Le corps du programme se trouve dans une classe dite MainWindow sous QtCreator :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void MainWindow::on_pushButton_clicked()
    {
    //code
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::istream& operator >> (std::istream& is, Line& line) {
        return is >> line.a >> line.b;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    mainwindow.cpp:410: erreur : a function-definition is not allowed here before '{' token 
    std::istream& operator >> (std::istream& is, Line& line) {
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::ostream& operator << (std::ostream& os, Line const& line) {
        return os << line.a << " " << line.b;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mainwindow.cpp:414: erreur : a function-definition is not allowed here before '{' token 
    std::ostream& operator << (std::ostream& os, Line const& line) {
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Line> lines; //tableau objet "lines" de type double,double
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mainwindow.cpp:420: erreur : invalid type in declaration before ';' token
     std::vector<Line> lines; //tableau objet "lines" de type double,double
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // lecture du fichier
    while(is >> l) { //tant que le fichier is n'est pas vide
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mainwindow.cpp:424: erreur : no match for 'operator>>' (operand types are 'std::ifstream {aka std::basic_ifstream<char>}' and 'MainWindow::on_pushButton_clicked()::Line')
    while(is >> l) { //tant que le fichier is n'est pas vide
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(auto const& l: lines) {
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    mainwindow.cpp:429: erreur : ISO C++ forbids declaration of 'l' with no type [-fpermissive]
     for(auto const& l: lines) {
     
    mainwindow.cpp:429: erreur : range-based 'for' loops are not allowed in C++98 mode
     for(auto const& l: lines) {
    Des erreurs quelque peu compréhensible

  4. #4
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par joffrey575 Voir le message
    Pour le deuxième argument je n'ai pas bien saisi ce que veux dire expression de type classe.
    >> et << sont des opérateurs binaires (comme '+', '-', etc..); ils prennent 2 paramètres : 1 à gauche et 1 à droite de l'opérateur. Le 1er paramètre est celui de gauche, le 2eme est celui de droite.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::istream& operator>>(std::istream& gauche, Line& droite) { /* ... */ }
    Un opérateur est une fonction qui peut être appelée avec une syntaxe particulière
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Line l;
    std::cout << l;
     
    // équivalent à
    Line l;
    operator<<(std::cout, l);
    Ou dans le cas d'une addition, si c'est plus clair
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int i, j;
    i + j;
     
    // équivalent à
    operator+(i, j);
    Citation Envoyé par joffrey575 Voir le message
    La surcharge de l'opérateur est bien la syntaxe suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::istream& operator>>
    ?
    Oui, note que les paramètres sont fixes (avec T le type qui t'intéresse)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    std::istream& operator>>(std::istream& is, T& obj) {
       // lecture du flux pour donner les bonnes valeurs à obj;
       return is; // on retourne le flux pour pouvoir chainer les appels
    }
    Citation Envoyé par joffrey575 Voir le message
    Par contre, en début du fichier.txt j'ai mis d'autres renseignements. La structure est fixe mais chaque valeur se trouve à des positions différentes bien connu. Je suppose ne pas connaitre la longueur des valeurs pour permettre une utilisation plus large.

    Comment faire pour traiter cette partie non-régulière et la partie régulière?

    Peut être est-il possible de se servir du curseur de position ou alors du fait qu'avant chaque valeur se trouve le caractère ' : ' ! Mais la je reste sans voix pour le moment.
    Il te faut une façon de délimiter ces 2 parties :
    - soit tu sais que l'entête va faire un nombre précis de lignes (ou caractères)
    - soit tu marques une limitation entre l'entête et la partie régulière (un caractère, ou chaine de caractère particulière).

    Pour ça il peut être pratique d'avoir une classe représentant les données de ton fichier, contenant le header et les données "normales".

    Par exemple si ton fichier ressemble à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    foo 42
    bar "abc"
    fin_entete
    1500.000000               336.668600
    2300.000000                 6.668600
    Tu peux avoir un truc du genre
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    struct Line {
    	double a, b;
    };
     
    std::istream& operator>>(std::istream& is, Line& line) {
    	return is >> line.a >> line.b;
    }
     
    std::ostream& operator<<(std::ostream& os, Line const& line) {
    	return os << line.a << " " << line.b;
    }
     
    struct Data {
    	std::map<std::string, string> header;
    	std::vector<Line> lines;
     
    	static Data fromFile(std::string& fileName) {
    		Data d;
    		std::ifstream is(fileName);
     
    		std::string headerLine;
    		bool headerDone = false;
    		while(is) { // lecture du header
    			std::getline(is, headerLine);
    			if(headerLine == "fin_header") {
    				break;
    			}
    			std::string key, value;
    			std::sstream ss;
    			ss << headerLine;
    			ss >> key >> value; // on recupère le coucle clef / valeur de chaque ligne
    			d.header.insert(std::make_pair(key, value));
    		}
     
    		// puis le bloc de données "normales"
    		Line l;
    		while(is >> l) {
    			d.lines.push_back(l);
    		}
    		return d;
    	}
     
    private:
    	Data() { }
    };
     
    Data d(Data::fromFile("data.txt"));
     
    // affichage
    for(auto const& l: d.lines) {
    	std::cout << l << '\n';
    }
    edit : hum... tu as complètement édité tes 2 posts entre temps.

    Pour les erreurs, lire un cours de C++ à partir de 0 t'aidera : où définir un fonction (la réponse n'est pas dans le corp d'une autre fonction ^^"), rôle des includes etc... C'est vraiment les bases qu'il te manque.
    Pour les range based loops, active c++11 sur ton compilo.

Discussions similaires

  1. Manipulation d'une chaîne de caractères
    Par RRahl dans le forum Général Java
    Réponses: 8
    Dernier message: 27/03/2013, 19h47
  2. Réponses: 8
    Dernier message: 12/02/2013, 01h08
  3. Réponses: 3
    Dernier message: 17/08/2011, 14h40
  4. Réponses: 3
    Dernier message: 10/01/2007, 18h44
  5. Réponses: 3
    Dernier message: 09/05/2002, 01h39

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