Besoin d'aide extraction de mot d'un fichier collé !!

Fermé
propsac - Modifié le 14 déc. 2021 à 14:08
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 - 7 janv. 2022 à 12:59
Bonjour à tous,

Je veux vous montrer ce petit bout de code car j'ai un problème... Je vous laisse lire de quoi il s'agit et en espérant avoir des réponses et que ça puisse servir aussi à d'autre...
  • Détecter un chaîne de caractère dans un texte.
  • Le fichier compare une chaîne de caractère dans un gros fichier (
    .json
    ) et doit en ressortir la chaîne de caractère + des caractères en plus (jusqu'à un "." par exemple ou juste 8 caractères après) dès lors qu'il le trouve dans le fichier (qu'on colle dedans).
  • Vous pouvez essayer par exemple vous taper :
    azertyuiopqsdfghjklmazerty456789
    , entrée, et ensuite
    zer
    , entrée. De ça, il sort
    zertyuiopq
    et
    zerty45678.
    .


Les problèmes sont :
  • call an instance std::out_of_range donc il fait bien toutes les itérations mais bloque ensuite (il n'affiche donc pas
    voila tout
    à la fin)
  • N'accepte pas les espaces dans le texte
  • N'accepte pas un fichier faisant plus de
    4094
    dans le string
    D
    .


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

using namespace std;
int j = 0;
int i = 0;
int g = 1;
int tailleC;
int tailleD;
string D;
string C;

class step
{
    public:
        void deb();
};

void step::deb()
{
    cout << "Colle le fichier .json ici :" << endl;
    cin >> D;
    tailleD = D.size();
    cout << "Le fichier .json comporte " << tailleD << " caracteres." << endl;
    cout << "Colle la chaine de caracteres ici :" << endl;
    cin >> C;
    tailleC = C.size();
};

int main()
{
    step deb;
    deb.deb();
    while (i < D.size())
    {
        while (j < C.size())
        {
            if (D.at(i) != C.at(j))
            {
                i+=1;
                j=0;
            }
            if (D.at(i) == C.at(j))
            {
                i += 1;
                j += 1;
            }
        }
        cout << "Occurence : " << g << " ==> "
            << C + D.at(i) + D.at(i+1) + D.at(i+2) + D.at(i+3) + D.at(i+4) + D.at(i+5) + D.at(i+6) + D.at(i+7) + D.at(i+8) + D.at(i+9)
            << endl; //Affiche les 10 caractères suivants.
        i += 1;
        j = 0;
        g += 1;
    }
    cout << "Voila tout !" << endl;
}


Merci beaucoup pour votre temps à consacrer à cet outil qui me sera très utile si cela fonctionne !! :)
A voir également:

8 réponses

mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 751
Modifié le 14 déc. 2021 à 14:28
Bonjour,

Tu te compliques la vie car :
  • tu devrais utiliser des boucles
    for
    plutôt que des
    while
    , ce serait plus concis ;
  • tu devrais utiliser
    std::string::find
    qui permet de chercher l'occurrence d'une sous-chaîne dans une chaîne.
  • tu peux extraire une sous chaîne avec
    std::string::substr
    .


Ensuite les trucs que tu devrais revoir :
  • Indente ton code, ça t'aidera à le relire.
  • Je ne comprends pas trop où l'aspect json entre dans ton programme. On est d'accord que ça pourrait être n'importe quel fichier texte et que tu n'as pas l'intention d'exploiter la structure du fichier
    .json
    ?
  • Évite les variables globales. C'est une mauvaise habitude de programmation qui te posera des problèmes par la suite (notamment quand tu feras des programmes parallélisés).
  • Utilise les headers C++, pas ceux du C, notamment :
    • #include <cstdio>
      au lieu de
      #include <stdio.h>
      ;
    • #include <cstdlib>
      au lieu de
      #include <stdlib.h>
      ;
    • #include <cstring>
      au lieu de
      #include <string.h>
      ;
    • ... ou mieux, supprime les car tu n'en as pas besoin :-)
  • Ta classe n'est pas réellement exploitée, je ne vois pas trop pourquoi tu n'as pas directement écrit une fonction (rien ne l'interdit en C++).


Voilà à quoi ça pourrait ressembler :

#include <iostream>
#include <string>

int main(){
    using namespace std;
    string s1, s2;
    size_t i, j, len;
    
    cout << "s1?" << endl;
    cin >> s1;
    cout << "s1 contient " << s1.size() << " caractères" << endl;
    cout << "s2?" << endl;
    cin >> s2;
    cout << "s2 contient " << s2.size() << " caractères" << endl;
    
    i = s1.find(s2);
    if (i == std::string::npos) {
        cerr << s2 << " n'apparaît pas dans " << s1 << endl;
        return 1;
    } 
    j = s1.find(".", i);
    len = (j == std::string::npos) ? 8 : j - i;
    cout << s1.substr(i, len) << endl;
    return 0;
}


Résultat :

(mando@silk) (~) $ g++ toto.cpp && ./a.out 
s1?
azertyuiopqsdfghjklmazerty456789
s1 contient 32 caractères
s2?
zer
s2 contient 3 caractères
zertyuio


Note que ici on extrait
len = 8
caractères car c'est comme ça que je comprends ton énoncé, mais rien n'empêche de choisir
s1.size() + 8
si tu préfères. Dans ton énoncé, la manière dont tu traites les "." ne me paraît pas cohérente avec ton exemple, donc je t'ai mis ce que j'ai compris et te laisse corriger à ton idée...

Bonne chance
0
propsac Messages postés 1 Date d'inscription vendredi 10 décembre 2021 Statut Membre Dernière intervention 14 décembre 2021
14 déc. 2021 à 17:24
Bonjour,
Merci pour ta réponse avec la plupart des aides. Néanmoins j'ai encore plus d'interrogations ^^
J'ai due mal m'exprimer car ce n'est pas assez clair; le code y compris (je le reposte avec les commentaires).
Contexte :
Je cherche à faire un fichier qui scrute (dans mon code C'est la manière caractère par caractère) un peu fastidieux mais c'est tout ce que je pu réussir à pondre de ce que je sais faire avec ma tête.. Je sais qu'il y a plusieurs façon de programmer mais ce ne serait donc pas la bonne manière de procédé sachant que je ne connais pas bien les librairies et choses possible de faire.
En tout cas : pour mieux expliquer : j'ai besoin d'analyser des fichiers qui sont en .json mais ça fonctionne pour n'importe quel texte (qui ne contient pas d'espace car dans mon code il ne les veux pas; surement du au "string".
En sortie il me faut une le nombre de fois ou la chaine apparait dans le texte (la données) plus les caractères qui suivent (qui correspondent aux valeurs). Si j'ai pris 8 ou 10 caractères après c'est pour être sûr qu'ils contiendront les valeurs qui suivent la données. Ducoup je peux donner un bout d'exemple en photo. Les problèmes sont que : la taille du collage est limitée.
La fonction se termine en bloquant sur le une valeur qui est hors champ finalement --'
Pour ce qui est du "." c'est enfaite pour le résultat pour qu'il soit sous la forme de : "nbd'occurence//ladonnée/lavaleur" Qui ferait plus "propre" tout simplement. (voir l'exemple après si la photo à bien été chargé)
Pour ce qui est d'utilisé les boucles "for" j'ai essayé de le faire auparavant mais il faudrait les imbriquer, d'où les while, j'aimerai bien voir comment avec des for... car je ne pense pas que l'imbrication soit faisable...
Pour ce qui est des headers, effectivement je n'avais jamais su ça x) et enfaite d'ailleurs je ne sais pas vraiment comment les utiliser car je n'ai pas bien connaissance de tout ce qu'ils comportent.
- Je ne savais pas pour les variables globale mais pourtant ça aide bien que ce soit en global non ? ça dépend de ce qu'on veut faire..?

- Header en trop : supprimé.
- Indenter ... Je pensais que c'était déjà assez clair..

En essayant ton code, le problème dedans est qu'il ne donne que la première valeur alors qu'il devrait sortir azert456 en plus dans ton exemple..
J'espère que c'est plus clair

//Détecter un chaine de caractère dans un texte
//Par Vincent SNPI4 2021
//Pas d'espace / ***Pas de sortie de boucle*** / N'accepte pas un fichier faisant plus de 4094 dans le string D. 
#include <iostream>
#include <string.h>

using namespace std;

int j=0;
int i=0;
int g=1;
int tailleC;
int tailleD;
string D;
string C;

class step
{
public:
     void deb();
};

void step::deb()
{
    cout << "Colle le fichier .json ici :" << endl;
    cin >> D;
    tailleD=D.size ();        //Passage de string à un int
    cout << "Le fichier .json comporte " << tailleD << " caracteres." << endl;
    cout << "Colle la chaine de caracteres ici :" << endl;
    cin >> C;
    tailleC=C.size ();        //Passage de string à un int
};

int main()
{
step deb;
deb.deb();                   //Permet juste de faire le début en amont du traitement des données

while (i!=D.size ())         //se déroule tant que le gros fichier n'a pas totalement été scruté
{
    while (j!=C.size ())     //se déroule tant que la chaine de caractère qu'on veut recenser n'a pas totalement été déroulé
      {
        if (D.at(i)!=C.at(j))    // Si le caractère 0 du gros fichier et le caractère 0 de la chaine sont différents alors on remet incrémente de 1 le caractère du gros fichier et remet à 0 la chaine
       {
       i+=1;
       j=0;
       }
        if (D.at(i)==C.at(j))     //Si le caractère 0 de la chaine et le caractère N du gros fichier sont égaux on incrémente les deux pour voir si leur caractères suivant sont égaux aussi
               {
               i+=1;
               j+=1;
               }
      }                          // Boucle jusqu'à ce que le compteur J de la taille de la chaine soit égale à la taille de la chaine
cout << "Occurence : " << g << " ==> " << C + D.at(i) + D.at(i+1) + D.at(i+2) + D.at(i+3) + D.at(i+4) + D.at(i+5) + D.at(i+6) + D.at(i+7) + D.at(i+8) + D.at(i+9) << endl; //Affiche la chaine trouvé dans le gros fichier et affiche les 10 caractères suivants.
i+=1;                //incrémente le gros fichier
j=0;                 // Remet le compteur de la chaine à 0
g+=1;                //incrémente l'afficheur
}                    // Une fois la taille du gros fichier égale à l'incrémenteur : sort de la boucle.
cout << "Voila tout !" << endl;       //Ne s'affiche pas car : instance out_of_range appelé alors que il devrait sortir de la boucle dès une fois que : i==D.size ()
}


Pour ce qui est de string::find c'est intéressant mais on dirait qu'il prend le premier trouver et c'est tout.. Peux-tu expliquer avec des commentaires ton bout de code poster avant car j'ai du mal sur es lignes 17; 21/22/23 et pourquoi "cerr" à la place d'un "cout" ? Est-ce juste pour identifier dans le code que c'est en cas d'erreur ?
Merci beaucoup :)

0
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 751
Modifié le 14 déc. 2021 à 18:59
Bonjour,

Merci d'éviter les captures d'écran quand tu peux faire un copier coller ce sera plus pratique pour tout le monde. Je reprends ton message.

Je sais qu'il y a plusieurs façon de programmer mais ce ne serait donc pas la bonne manière de procédé sachant que je ne connais pas bien les librairies et choses possible de faire.

Je comprends ce que tu veux dire si le but est de bosser l'algorithmique. Après il faut bien garder à l'esprit que dans la vraie vie, tout le monde utiliserait les fonctions fournies par la STL autant que possible. Ça améliore grandement la lisibilité (plus concis, plus parlant), limite les erreurs d'implémentation etc.

Et c'est l'opportunité d'apprendre à découvrir des fonctions. Généralement, ça vaut le coup quand on utilise une classe sur étagère (genre
std::string
) de regarder sa documentation pour voir les fonctionnalités qu'elle offre. Généralement, il y a quelques exemples qui montrent comment les utiliser.

En tout cas : pour mieux expliquer : j'ai besoin d'analyser des fichiers qui sont en .json mais ça fonctionne pour n'importe quel texte (qui ne contient pas d'espace car dans mon code il ne les veux pas; surement du au "string".

Ok, c'est ce qu'il me semblait.

En sortie, il me faut une le nombre de fois où la chaîne apparaît dans le texte (la données), plus les caractères qui suivent (qui correspondent aux valeurs).

Ah ok, je n'avais pas compris que tu cherchais toutes les occurrences. Alors dans le bout de code que j'ai donné, rien n'empêche de répéter
s1.find(s2, i)
en incrémentant
i
jusqu'à arriver en fin de fichier.

Si j'ai pris 8 ou 10 caractères après c'est pour être sûr qu'ils contiendront les valeurs qui suivent la données.

Je n'ai pas compris ce que tu voulais dire. Il faut les extraire ou pas ?

Du coup je peux donner un bout d'exemple en photo [...]

Désolé c'est trop peu clair, entre le texte et la capture d'écran...

Pour ce qui est d'utilisé les boucles "for" j'ai essayé de le faire auparavant mais il faudrait les imbriquer, d'où les while, j'aimerai bien voir comment avec des for... car je ne pense pas que l'imbrication soit faisable...

Un
for
est strictement plus général. Au pire
while(condition) { }
, peut toujours s'écrire
for(; condition; ) { }
, et dans ton cas tu peux bénéficier du premier élément et du troisième élément pour initialiser et incrémenter tes compteurs.

Pour ce qui est des headers, effectivement je n'avais jamais su ça x)

C'est très simple : il suffit de regarder dans la documentation d'un objet ou d'une fonction pour voir quel header le fournit :-)
  • Concernant le C : les headers du C qui s'incluent en C via
    #include <xyz.h>
    s'incluent en C++
    #include <cxyz>
    en C++. Si tu veux utiliser des fonctions du C en C++, il suffit de les chercher dans les pages de man (soit via google, soit via ton terminal si tu es sous Linux ou MacOS). Par exemple si tu cherches
    man printf
    , tu vois les headers mis en jeu dans la documentation.
  • Concernant le C++ (plus exactement la STL) : Les headers du C++ fournissent généralement l'objet dont ils portent le nom (e.g.,
    #include <string>
    fournit
    std::string
    ), comme le montre cette page.


Par rapport à ton code, le header
#include <iostream>
fournit :
  • std::cout
    ,
  • std::cin
    ,
  • std::cerr
    ,
  • std::endl
    .


Je ne savais pas pour les variables globale mais pourtant ça aide bien que ce soit en global non ? ça dépend de ce qu'on veut faire..?

C'est plutôt le contraire. Tu peux avoir des conflits avec tes variables (genre des paramètres qui masquent des variables globales), ça nuit à la lisibilité du code (car tu ne vois pas l'ensemble des variables dont dépend une fonction) et à terme ça nuit au design du code. N'importe quelle personne qui a un peu d'expérience en développement te déconseillera les variables globales.

Par contre, des constantes globales peuvent avoir du sens (mais ça n'est pas ce que tu fais ici), car parfois cela permet de paramétrer le comportement du programme à la compilation (voir
#define
et option
-D
dans
g++
).

Peux-tu expliquer avec des commentaires ton bout de code poster avant car j'ai du mal sur les lignes 17; 21/22/23
  • Pour la ligne 17 : je te renvoie à la documentation de
    std::string::find
    .
    std::string::npos
    est la valeur que tu obtiens quand
    s2
    n'est pas trouvée dans
    s1
    à partir de l'index
    i
    .


    j = s1.find(".", i);
    len = (j == std::string::npos) ? 8 : j - i;
    cout << s1.substr(i, len) << endl;
  • Pour les lignes 21-23 :
    • La première cherche "." dans
      s1
      à partir de l'index
      i
      . Cette valeur est sauvée dans
      j
      .
    • La seconde regarde en fonction de
      j
      si
      s2
      a été trouvée dans
      s1
      si oui, len vaut
      8
      , sinon
      j - i
      .
    • La troisième extrait la sous chaîne de
      s1
      faisant
      len
      caractères à partir de l'index
      i
      .


... et pourquoi "cerr" à la place d'un "cout"
  • std::cout
    désigne le flux de sortie standard (donc les résultats du programme).
  • std::cin
    désigne le flux d'entrée standard (donc les résultats du programme).
  • std::cerr
    désigne la sortie d'erreur standard (donc les résultats du programme).


Quand le programme est lancé seul dans un programme :
  • lire dans
    std::cin
    revient à lire la saisie clavier,
  • écrire dans
    std::cout
    revient à écrire dans le terminal,
  • écrire dans
    std::cerr
    revient à écrire dans le terminal.


Quand le programme est lancé seul dans un programme est impliqué dans un pipe (ce qui en shell, sous linux, s'écrit sous la forme
prgm1 | prgm2 | prgm3
, concernant
prgm2
:
  • lire dans
    std::cin
    revient à lire ce qui est écrit par
    prgm1
    dans la sortie standard,
  • écrire dans
    std::cout
    revient passer de l'information à l'entrée standard de
    prgm3
    ,
  • écrire dans
    std::cerr
    revient à écrire dans le terminal.


En bref, on distingue les flux dans lesquels les messages sont écrits afin de ne pas polluer les informations qui circulent de
prgm1
vers
prgm2
et de
prgm2
vers
prgm3
.

Ne crois pas non de pipe soit spécifique à Linux. Elle existe dans tous les systèmes d'exploitation (ce qui inclue Windows, MacOS, Android, ...). Elle est très communément utilisée sous Linux, et c'est uniquement pour ça que j'ai pris cet exemple. À titre indicatif, sous Linux, on combine régulièrement des commandes qui interrogent le système avec des commandes qui traitent du texte en vue de remettre en forme l'information qu'on récupère.

Bref, ma recommandation, c'est d'être rigoureux au flux de sortie dans lequel on écrit.

Note que dans la même veine, le code d'exécution du programme (le fameux
return 0
de la fonction
main
quand tout va bien et une autre valeur sinon) a également de l'importance vis-à-vis du shell (et donc un programme qui plante devrait retourner une valeur non nulle au niveau du
main
pour quel shell s'en rende compte).

Bonne chance
0
Bonsoir, merci pour ce cours, néanmoins je n'arrive toujours pas à faire en sorte que le fichier de traité le soit entièrement (limite des 4094caractères). Penses-tu que pour ça il faut absolument que je fasse un programme qui ouvre un fichier etc pour l'analyser ? Je suis bloqué ici aussi.. Je vais essayer en attendant ta réponse de faire en sorte qu'avec ton programme il répète l'occurrence correctement.. De ce que je vois quand on comprends un peu mieux comment ça fonctionne ça devient plus facile pour écrire et comprendre lors de la relecture.
Merci beaucoup et si ce n'est pas trop t'en demander ; Est-ce possible d'avoir une correction de ton programme pour qu'il ressorte les occurrence ? Afin d'avoir la correction et une deuxième méthode certainement moins bugger :p
Bonne fêtes de fin d'année !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 751
Modifié le 22 déc. 2021 à 21:38
Bonjour,

Ci-joint le programme modifié :

#include <iostream>
#include <string>

int main(){
    using namespace std;
    string s1, s2;
    size_t i, j, len;
    bool found = false;

    cout << "s1?" << endl;
    getline(std::cin, s1);
    cout << "s2?" << endl;
    getline(std::cin, s2);

    for (i = 0;; i++) {
        cout << "search '" << s2 << "' in '" << s1 << "' from " << i << endl;
        i = s1.find(s2, i);
        if (i != std::string::npos) {
            found = true;
            j = s1.find(".", i);
            if (j == std::string::npos) {
                len = (i + 8 >= s1.size()) ? std::string::npos : 8;
            } else {
                len = j - i;
            }
            cout << "found at index " << i << ": '" << s1.substr(i, len) << "'" << endl;
        } else break;
    } 

    if (!found) {
        cerr << "'" << s2 << "' is not in '" << s1 << "'" << endl;
        return 1;
    }   
    return 0;
}


Résumé des modifications
  • J'utilise maintenant
    std::getline()
    au cas où la chaîne saisie contient des espaces ;
  • Pour chercher toutes les occurrences de
    s2
    dans
    s1
    , je fais la recherche à partir de l'index
    i
    que j'incrémente (cela permet en particulier de trouver les occurrences qui se chevauchent)
  • Pour m'assurer qu'au moins une occurrence a été trouvée, j'utilise maintenant la variable
    found
    .
  • J'ai corrigé le calcul de
    len
    pour éviter le plantage du programme si
    s2
    apparaît près de la fin de
    s1
    (dans la version précédente,
    i + len
    dépasser
    s1.size()
    , ce qui n'est pas correct).
  • La condition d'arrêt du
    for
    est omise car elle est réalisée par le
    else break
    . Si on avait écrit
    for(i = 0; i != std::string::npos; i++)
    ,
    i
    est incrémenté avant d'évaluer le test
    i != std::string::npos
    et passe donc à ...
    0
    . Et on ne peut pas écrire
    for(i = 0; i != 0; i++)
    sinon on ne rentre pas dans la boucle.


Exemple

(mando@silk) (~) $ g++ -W -Wall toto.cpp && ./a.out 
s1?
aaaxyzbbxyzccc
s2?
xyz
search 'xyz' in 'aaaxyzbbxyzccc' from 0
found at index 3: 'xyzbbxyz'
search 'xyz' in 'aaaxyzbbxyzccc' from 4
found at index 8: 'xyzccc'
search 'xyz' in 'aaaxyzbbxyzccc' from 9


Concernant les gros fichiers

En fait ce n'est pas vraiment dans l'esprit de "copier coller" des chaînes de caractères dans le terminal. C'est peu pratique, le programme a difficile à automatiser, bref ce n'est pas pratique. Il vaudrait mieux que le programme prenne en paramètre le chemin du fichier à analyser et la chaîne à rechercher.

Pour lire un fichier tu peux utiliser la classe
std::ifstream
(i = input, file = file). En admettant que tu t'interdises la recherche d'une chaîne contenant un retour à la ligne, il suffit de lire le fichier ligne par ligne et de procéder à la recherche pour chaque ligne. C'est exactement ce qui est fait dans cette discussion. D'après la documentation de
std::getline
, la ligne lue peut être arbitrairement grande (du moins... tant que tu as de la mémoire :p).

Voici comment tu peux faire :

#include <iostream>
#include <string>
#include <fstream>

int main(int argc, char **argv) {
    using namespace std;
    string s1, s2;
    size_t i, j, len, no_line;
    bool found = false;

    if (argc != 3) {
        cerr << "usage: " << argv[0] << " filename pattern" << endl;
        return 1;
    }

    string filename = argv[1];
    ifstream ifs(filename);
    if (ifs) {
        string s2 = argv[2];
        for (no_line = 0; getline(ifs, s1); no_line++) {
            for (i = 0;; i++) {
                /*
                cout << "search '" << s2 << "' in '"
                     << s1 << "' (line " << no_line << ") from "
                     << i << endl;
                */
                i = s1.find(s2, i);
                if (i != std::string::npos) {
                    found = true;
                    j = s1.find(".", i);
                    if (j == std::string::npos) {
                        len = (i + 8 >= s1.size()) ? std::string::npos : 8;
                    } else {
                        len = j - i;
                    }
                    cout << "found at line " << no_line << ", index " << i << ": '"
                         << s1.substr(i, len) << "'" << endl;
                } else break;
            }
        }
        if (!found) {
            cerr << "'" << s2 << "' is not in '" << s1 << "'" << endl;
            return 1;
        }
        ifs.close();
    } else {
        cerr << argv[0] << "cannot open " << filename << endl;
        return 1;
    }

    return 0;
}


Exemple

Supposons que
fichier
contienne :

aaaaxyzbbbxyzcccxyzddd
xyzxyz
eeexyz
xyzfff


On obtient à l'exécution :

(mando@silk) (~) $ g++ -W -Wall toto.cpp && ./a.out fichier xyz
found at line 0, index 4: 'xyzbbbxy'
found at line 0, index 10: 'xyzcccxy'
found at line 0, index 16: 'xyzddd'
found at line 1, index 0: 'xyzxyz'
found at line 1, index 3: 'xyz'
found at line 2, index 3: 'xyz'
found at line 3, index 0: 'xyzfff'


Bonne chance
0
Bonjour,

Tout d'abord : bonne année et meilleurs vœux :)

Ensuite, j'ai eu un temps de latence avec les fêtes de fin d'année.. d'où la réponse tardive.

Mais aussi le fait que j'ai tenté beaucoup de temps en vain de faire quelque chose chose. Malgré tout je me suis penché sur
std::ifstream
pour faire la même chose que toi, mais je n'y arrive pas :-(((((( un problème de nom de fichier ou de base de programmation tout simplement.
Merci pour la réponse en tous cas.

Le deuxième code que tu as fais m'intéresse et à l'air de fonctionner pour toi.

*****Supprimé par la modération hors charte CCM*****

Si c'est impossible selon vous, qu'est ce qui fait que
filename pattern
ne fonctionne pas ? J'ai essayé de mettre le "chemin" puis en voyant sur internet, des fois il faut juste mettre le nom etc je ne comprends pas...

Merci encore bien sûr, même si je ne réponds pas directement je constate les efforts !

Je suis frustré d'avoir les outils à ma disposition mais de ne pas pouvoir les mettre en œuvre. C'est pour ça que je souhaite mobiliser un peu de ton temps en échange de quelques euros en guise de remerciement et de satisfaction.

Bonne journée !
0
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 751
Modifié le 5 janv. 2022 à 12:28
Bonjour,

Malgré tout je me suis penché sur
std::ifstream
pour faire la même chose que toi mais je n'y arrive pas :(((((( un problème de nom de fichier ou de base de programmation tout simplement.


Qu'entends tu par "te pencher" ? Quelle est l'erreur ?

Pour exécuter le programme, il faut que le chemin du fichier soit valide. Dans mon exemple
fichier
est le nom du fichier que je traite. Si dans ton cas il s'appelle
toto.txt
, il faut appeler ton programme en passant
toto.txt
en paramètre. S'il est dans un autre répertoire que ton exécutable, il faut que le chemin relatif ou absolu que tu passes au programme soit correct. Sans ces informations, impossible de savoir pour moi de comprendre ton problème.

Donc par exemple, si je veux traiter
toto.txt
qui est dans le répertoire du dessus (par rapport à mon exécutable
a.out
) et que je cherche le motif
xyz
je vais lancer :

./a.out ../toto.txt xyz


S'il s'agit du fichier
/home/toto/tata.txt
(par exemple parce que je suis sous linux ou MacOS) ou
C:\Users\toto\Mes Documents\titi.txt
(windows) je vais lancer :

./a.out /tmp/toto/tata.txt xyz
./a.out C:\\Users\\toto\\Mes\ Documents\\titi.txt xyz


Le deuxième code que tu as fais m'intéresse et à l'air de fonctionner pour toi.

Effectivement il marche, sinon je ne verrai pas l'intérêt de le partager :D

Même si je ne réponds pas directement je constate les efforts !

:-))))))))))))

Je suis frustré d'avoir les outils à ma disposition mais de ne pas pouvoir les mettre en œuvre. C'est pour ça que je souhaite mobiliser un peu de ton temps en échange de qq euro en guise de remerciement et de satisfaction.

Ce n'est pas comme ça que ça marche sur ce forum. Les intervenants de ce forum travaillent bénévolement et quand ils en ont envie. Ils le font par altruisme et pas pour l'argent. Mais les remerciements font toujours plaisir, et ça fait partie des choses qui nous donnent envie de continuer à aider les autres ;-)

Bonne chance
0
Bonjour,

Je travaille sous windows, et je n'arrive pas à lancer ce programme autrement qu'avec le compilateur...

J'ai cette erreur :

In function 'int main(int, char**)':

17 26 C:\Users\a040658\Documents\CCM\toto.cpp ::::::::::::: [Error] no matching function for call to 'std::basic_ifstream<char>::basic_ifstream(std::string&)'

17 26 C:\Users\a040658\Documents\CCM\toto.cpp ::::::: [Note] candidates are:

3 0 C:\Users\a040658\Documents\CCM\Corr.cpp In file included from C:\Users\a040658\Documents\CCM\Corr.cpp

470 7 C:\Program Files (x86)\Dev-Cpp\MinGW64\lib\gcc\x86_64-w64-mingw32\4.9.2\include\c++\fstream :::::::::::: [Note] std::basic_ifstream<_CharT, _Traits>::basic_ifstream(const char*, std::ios_base::openmode) [with _CharT = char; _Traits = std::char_traits<char>; std::ios_base::openmode = std::_Ios_Openmode]


En fait, je ne sais pas par où commencer ni par ou le lancer comme il s'agirait seulement de ça... Ni comment placer mes répertoire finalement..

Le programme est sous le nom de
toto
et le fichier
titi
sont tous les deux dans le dossier
C:\Users\a040658\Documents\CMM
.

J'ai l'impression qu'on avance. Lentement mais surement (encore heureux) :)
Merci encore pour ces derniers indices :p
Car c'est vrai que ce qui intéressant dans tout ça c'est de créer un script facile d'utilisation !

Bonne journée et hâte de voir ta réponse !
0
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 751
7 janv. 2022 à 12:59
Bonjour,

Selon ce lien, selon ton compilateur, il se peut que tu ne puisses pas créer un
std::ifstream
en prenant en paramètre une
std::string
. Essaye de changer :

string filename = argv[1];
ifstream ifs(filename);


... en :

const char * filename = argv[1];
ifstream ifs(filename);


Ensuite quelques remarques par rapport à ton message :

Je n'arrive pas à lancer ce programme autrement qu'avec le compilateur...

Il faut distinguer :
  • compiler un programme : c'est-à-dire demander à ton compilateur, e.g.
    g++
    ) de traiter ton code source en vue de produire un binaire (e.g. une librairie, exécutable, etc.) ;
  • lancer (ou exécuter un programme) (qui n'est possible que si ledit programme a été compilé avec succès).


Car c'est vrai que ce qui intéressant dans tout ça c'est de créer un script facile d'utilisation !

En toute rigueur tu ne peux pas parler de script. Un script est un programme écrit dans un langage interprété ou pseudo-compilé (e.g. un script batch, shell, php, perl, python, javascript). Quand il s'agit d'un langage compilé, on parle plutôt de code source.

Ensuite il faut distinguer le code (qui peut être lisible, bien organisé, modulaire, bref tous les aspects qui concernent le développeur) et le logiciel (qui peut être ergnonomique, rapide, bref tous les aspects qui concernent l'utilisateur).

Bonne chance
0