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 :

Un problème avec une std::string


Sujet :

C++

  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 113
    Par défaut Un problème avec une std::string
    Salut à tous,

    je cherche à passer sur mac un code développé sur windows.

    J'ai commencé par être confronté à une différence concernant les chemins relatifs que j'ai réglé avec _NSGetExecutablePath.

    Maintenant je me retrouve avec un comportement étrange sur une std::string (il n'y a peu être aucun rapport avec le passage sur mac mais ça fonctionnait sous windows alors je préfère vous le dire).

    Mon problème est le suivant : je lis dans un fichier le nom d'un autre fichier à l'aide de la fonction :

    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
    string readFileName(string fileName, string tag)
    {
        string line;
        string result;
        string balise = string(tag);
     
        ifstream file(fileName, ios::in);
     
        if(file)
        {
            while(!file.eof())
            {
                getline(file, line);
     
                if (line.find(balise) != string::npos)
                {
                    result = line.substr(balise.length()+3);
                }
            }
        }
     
        file.close();
     
        return result;
    }
    Ma std::string est bien lu mais je ne peut pas la modifier sans comportements étranges.

    Admettons que mon fichier soit : monFichier.txt.

    Si, par exemple, je veux l'afficher encadré par deux lettres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cout << "a" << fileName << "b" << endl;
    j'obtiens : bonFichier.txt (le m à été remplacé par le a puis par le b je suppose).

    Si j'avais écris :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cout << "a" << fileName << "bbb" << endl;
    j'aurais obtenu : bbbFichier.txt

    Et si j'avais voulu concaténer deux std::string :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    fileName += string("b");
    cout << fileName << endl;
    ou encore

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    fileName.append(string("b"));
    cout << fileName << endl;
    j'aurais obtenu dans les deux cas : bonFichier.txt.

    Est ce que ce comportement vous dit quelque chose ?

    Un grand merci d'avance pour votre aide.

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Ce sont tes fins de lignes.
    Il y a deux caractères de fin de lignes: CR (carriage return) et LF (line feed).
    J'ai l'impression que tu es bien revenu au début de la ligne, mais que tu n'es pas passé à la suivante.

    Or, et c'est là l'astuce, windows utilise CR suivi de LF comme passage à la ligne suivante, tandis que les Mac n'utilise que CR. (Et linux uniquement LF)

    Il est inutile de préciser ios::in pour un ifstream, par contre, regarde le fonctionnement de iso::binary.

    Une alternative serait serait de changer les fins de lignes du fichier. Pour linux, il y a dos2unix, j'imagine que la même chose existe pour mac

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 113
    Par défaut
    Merci beaucoup pour cette réponse encore une fois très instructive. Je ne savais pas qu'il y avait une différence dans la lecture des fichiers entre Windows, Linux et Mac.

    J'ai fait fonctionner ma lecture en cherchant le nom de mon fichier entre des guillemets ("fileName.txt" en me servant des guillemets comme balises).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // Fonctionne
    start = line.find("\"");
    end = line.find("\"",start+1);
    result = line.substr(start+1, end - (start+1));
    J'avoue ne pas vraiment comprendre car j'ai essayer de faire de même entre des guillemets " et la balise \n mais cela ne fonctionne pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // Ne fonctionne pas
    start = line.find("\"");
    end = line.find("\n",start+1);
    result = line.substr(start+1, end - (start+1));
    Qu'est ce qui se cache derière les CR et LF ?

    Sous Windows : \n = CR+LF
    Sous Linux : \n = LF
    Sous Mac : \n = CR

    C'est ça ?

    J'ai aussi regardé rapidement du coté de ios::binary mais je n'ai vu aucunes différences de résultats.

  4. #4
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    CR -> "\r".
    LF -> "\n".

    ios::binary sur Linux (et je suppose Mac) ne fait rien. Il n'y a pas de différente entre ouvrir en mode binaire ou en mode texte.

    Si le texte est affiché sur la console, il faut utiliser "\n" pour les sauts de ligne, "\r" permettant de revenir au début de la ligne. À vérifier en affichant des chaînes comme "ab\rc" et "ab\nc".

    Un moyen rapide de supprimer les caractères indésirables est d'utiliser std::remove. Le plus simple reste quand même d'avoir des fichiers dans le bon format. Sans équivalent de dos2unix, il y a toujours sed (sed s'/^\n//g', pas essayé).

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 113
    Par défaut
    Effectivement, tu as raison :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    start = line.find("\"");
    end = line.find("\r",start+1);
    result = line.substr(start+1, end - (start+1));
    fonctionne et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    result = line.substr(balise.length()+3);
    result.erase(remove(result.begin(),result.end(),'\r'),result.end());
    fonctionne également.

    Je vais utiliser l'une de ces solutions pour le moment, j'étudierai plus en détail ios::binary, dos2unix et sed dans un second temps.

    Merci beaucoup pour votre aide précieuse.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par kipgon Voir le message
    J'ai commencé par être confronté à une différence concernant les chemins relatifs que j'ai réglé avec _NSGetExecutablePath.
    Tu aurais mieux fait d'utiliser boost::filesystem.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 14/06/2010, 15h21
  2. problème avec une variable de type string
    Par marsupilami34 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 14/06/2007, 14h53
  3. Problème de fonction "const" avec une std::map
    Par Clad3 dans le forum SL & STL
    Réponses: 3
    Dernier message: 02/01/2007, 12h38
  4. probléme avec une date/string dans un CommandText
    Par critok dans le forum Bases de données
    Réponses: 5
    Dernier message: 09/02/2005, 15h30
  5. Problème avec une procédure stockée
    Par in dans le forum Langage SQL
    Réponses: 4
    Dernier message: 27/05/2003, 15h33

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