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 :

[chaine de caractere] remplacement de caractères spéciaux


Sujet :

C++

  1. #1
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 97
    Points : 49
    Points
    49
    Par défaut [chaine de caractere] remplacement de caractères spéciaux
    Bonjour,
    J'écris un programme qui parcours un fichier et remplace ƒ, par f, pour le rendre XML-valide.
    Pour cela, j'utilise la fonction "replace".
    Or il y a une erreur à la compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    replace(paquet,paquet+nbOctetsLus,'\x192','f') ;
    \x192 étant la représentation héxadécimal du caractère dont l'entité html est &fnof.
    l'erreur dit que \x192 est trop grand pour un caractère.
    Que dois-je faire ?

    merci d'avance pour toute réponse.

    Sempire

  2. #2
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Points : 5 778
    Points
    5 778
    Par défaut
    je ne connais pas la foncton replace mais si le parametre auquel tu affecte
    '\x192' attend un caractere signe, c'est normal que '\x192' soit trop grand.
    un caractere signe est code sur 1 octet, donc peut prendre les valeurs de -128 à 127 (en decimal).

  3. #3
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 97
    Points : 49
    Points
    49
    Par défaut
    Merci pour ta réponse.
    Quel serait la solution si on veut absolument faire en sorte de remplacer ce caractère ?

  4. #4
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Points : 5 778
    Points
    5 778
    Par défaut
    il n'existe pas de solution standard.
    personnellement je ne me suis pas attardé sur ce probleme
    mais le probleme des caracteres speciaux (ou accents) à ete abordé plusieurs fois sur le forum et en cherchant un peu dans le site et la faq tu devrais trouver de quoi t'aider

  5. #5
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 97
    Points : 49
    Points
    49
    Par défaut
    j'ai trouvé cette solution.
    Il s'agit toujours du caractère ƒ que j'aimerai remplacer par un f.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    replace(paquet,paquet+nbOctetsLus,wchar_t(402), wchar_t(70));
    Mais ca ne marche pas. Il semble ne pas repérer ce caractère.


    Merci d'avance

  6. #6
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Points : 5 778
    Points
    5 778
    Par défaut
    code ascii (decimal) :
    'f' = 102
    'F' = 70

    'ƒ' = 159

  7. #7
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Attention, 159 est hors de la plage ASCII.
    Il faut voir dans quel encodage est ton fichier : ISO-8859-1, OEM850, UTF8, ... Il y en a tellement.
    Il n'existe pas des bibliothèques qui savent déjà faire ça ?

  8. #8
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 97
    Points : 49
    Points
    49
    Par défaut
    159 est hors de la plage ascii, c'est bien pour ca que j'utilise la fonction wchar.
    je m'emêle les pinceaux : ascii c'est équivalent à décimal ? dans ce cas, qu'est ce qu'ils entendent par décimal sur ce site http://cjandia.com/2001/espx-tinyxsl/ ?c'était ma doc de référence.
    Et ca, ca ne marche pas non plus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    replace(paquet,paquet+nbOctetsLus,wchar_t(159), wchar_t(70)) ;
    il me semble qu'en c++ c'est tout ce qu'on a (fonction replace).
    Sinon TIDY de la W3c fait un bon boulot par rapport à ca, mais il y a des éléments qui passent outre, notamment certains caractères imprimables.

    je suis en ISO-8859-1.
    Merci de votre participation.

    Sempire

  9. #9
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    ASCII -> -127 à +127
    char : un octet
    wchar_t : deux octets.

    Quitte à utiliser des constantes magiques, si ce n'est que pour du latin1, autant directement taper ton code dans le même format et utiliser directement 'ƒ' dans ton code. Non ?

  10. #10
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 97
    Points : 49
    Points
    49
    Par défaut
    mon editeur ne l'accepte pas, mais je sais ce n'est pas une excuse
    j'ai essayé, ca ne change rien à l'éxécution.
    J'envoie 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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
     
    #include <cwchar>
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <ctime>
    #include <algorithm>
    using namespace std ;
     
    const int Csize=1000 ;
     
    void main()
    {
    	fstream fLu ;
    	fstream fEc ;
    	wchar_t paquet[Csize] ;
    	int nbOctetsLus ;
    	char *p=NULL ;
    	clock_t debut = clock() ;
     
    	fLu.open("ess1.txt",ios::binary|ios::in) ;
    	fEc.open("essecr.txt",ios::binary|ios::out) ;
     
    	fLu.read((char*)paquet,Csize*sizeof(wchar_t)) ;
    	nbOctetsLus = fLu.gcount() ;
    	while( nbOctetsLus!=0 ){
    		// f.gcount() retourne le nombre d'octest lus
    		// dans notre cas c'est toujours Csize sauf pour le dernier
    		// bloc lu dans le fichier qui peut être <=Csize
     
     
     
    		replace(paquet,paquet+nbOctetsLus,wchar_t('ƒ');,wchar_t('f')) ;
    		//remove(paquet,paquet+nbOctetsLus,wchar_t('f'));
     
    		fEc.write((char*)paquet,nbOctetsLus) ;
    		fLu.read((char*)paquet,Csize*sizeof(wchar_t));
    		nbOctetsLus = fLu.gcount() ;
    	}
     
    	fLu.close() ;
    	fEc.close() ;
     
    	clock_t fin = clock() ;
    	double duree_sec = double(fin-debut) / CLOCKS_PER_SEC ;
    	cout << endl ;
    	cout << "duree en sec = " << duree_sec << endl ;
    }
    J'ai donc egalement essayé de passer les paramétre pour replace en décimal.
    le problème peut venir aussi du code.
    Car quand je fais un simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    replace(paquet,paquet+nbOctetsLus,'h','t') ;
    ...ca plante à l'éxécution avec un problème d'accès mémoire.


    Merci pour la rapidité.

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    80
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 80
    Points : 63
    Points
    63
    Par défaut
    Citation Envoyé par sempire
    je suis en ISO-8859-1.
    Cette version est la bonne a mon avis, avec mon lycée on a presenter tout un truc sur le codage et ascii en fait partie. En revanche Luc Hermitte ASCII IOS-8859-1 est sur un octet et vas de 0 a 255 soit 8 bits.
    Ey d'apres ce site http://www.bbsinc.com/iso8859.html ( le tableau est plus bas dans la page, il est en hexadécimal) le craractère rechecher est le sivant 83 (hexa : 0x83 ) 1000 0011 (binaire) 131 (décimal)

    Juste quelque petit renseigement si ca peu vous servir

  12. #12
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 97
    Points : 49
    Points
    49
    Par défaut
    Merci. ca confirme comme quoi le problème vient de mon code exposé dans mon message d'avant.
    car :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    replace(paquet,paquet+nbOctetsLus,wchar_t(131),wchar_t(070)) ;
    ...ne marche pas mieux.

    Merci de ta participation.

  13. #13
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Reste en char.
    (C'est bizarre, il me semblait pourtant avoir posté il y quelques jours (hier?) et parlé de transform et autres streambuf filtrants)
    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
     
    struct change_chars {
        char operator()(char c) const {
            switch (c) {
            case 'ƒ' : return 'f';
            default: return c;
            }
        }
    };
    ....
    std::transform(
        std::istreambuf_iterator<char>(fin),
        std::istreambuf_iterator<char>(),
        std::ostreambuf_iterator<char>(fout),
        change_chars()
    );
    C'est pas hyper propre, mais devrait être bon.

    ISO-8859-1 n'est pas l'ASCII, c'est latin1. Et effectivement, j'avais dit une bétise (mais où avais-je la tête...?) ASCII ne va que de 0 à 127, vu que ce n'est codé que sur 7bits. Au delà, ce n'est plus l'ASCII. Ce qui n'empêche pas que tous les ISO-8859-x ont une base ASCII pour les 128 premiers éléments, et que l'UTF a une base latin1 si je me souviens bien.

  14. #14
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 97
    Points : 49
    Points
    49
    Par défaut
    j'en demande surement un peu trop, mais ou placer ce bout de code dans mon code de base ?mon code est-il adaptable par rapport à ta solution ?
    je n'arrive pas à très bien comprendre ce que ca fait.

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    80
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 80
    Points : 63
    Points
    63
    Par défaut
    Comment on fait pour dire au compilateur que nous voulons travailler avec l'ascii ios 8859-1 ?

  16. #16
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Tu inclus <iterator>, <algorithm> et <fstream>
    "fin" correspond à ton "fLu" que tu ouvres toujours en binaire.
    "fout" correspond à ton "fEc" que tu ouvres toujours en binaire.

    Ce que ça fait ? Cela itère sur tous les éléments du flux entrant, les transforme (à l'aide du foncteur change_chars), et stockes le résultat dans le flux sortant. On retrouve le même principe que std::copy appliqué aux flux, mais avec une transformation au milieu.

    Des éléments d'explication sont donnés dans la FAQ.

    Sinon, il existe une commande *nix qui fait très exactement ce que tu sembles vouloir faire -> tr. (=> man tr)

    De ce que je sais, le compilo n'a aucune idée de l'encodage que tu utilises. Un caractère tapé dans un fichier source (.cpp, .h, ...) est compris comme un nombre (dont la valeur va dépendre de l'encodage dans lequel tu le vois), et à l'exécution, c'est un nombre sur un octet (char ; ou deux -> wchar_t) qui sera manipulé.

  17. #17
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 97
    Points : 49
    Points
    49
    Par défaut
    on inclurait dans le cadre de ma boucle parcourant le fichier par paquet, ou bien ca viendrait à la place de la boucle ?

  18. #18
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    A la place.

  19. #19
    Membre du Club
    Inscrit en
    Juin 2003
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 97
    Points : 49
    Points
    49
    Par défaut
    Je profite de ce topic pour essayr de résoudre avec vous un autre problème en relation avec celui-ci.
    Je remercie Luc Hermitte pour sa solution qui marche (la propreté attendra :-) ).
    Il m'a été utile sauf que j'ai remarqué que ce n'était pas le caractère qui était problématique, mais bien l'entité HTML qui le présentait (il s'agissait de manipuler des documents XML de 50 MO avec SAXON, et le message d'erreur n'était pas clair. et il est inutile de vous faire savoir que ces documents XMLne sont pas éditables en les ouvrant par un simple double-click).
    Le but maintenant est de remplacer cette entité HTML. voici le petit programme que j'ai écris et qui ne passe pas la compil.
    Pour la fonction replace, on est obligé d'utiliser des itérateurs, n'est ce pas?Or la classe string n'a pas d'itérateur, ce qui fait que je passe par un vector de string. Mais il blocke que des affectations, conversion de type...
    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <ctime>
    #include <algorithm>
    #include <vector>
    using namespace std;
     
     
    void main() {
     
     
    	long nbtrouve=0;
    	long indice=0;
    	string str="&fnof"; // chaine a rechercher
    	string strCorrection="entiteFNOFIndefinie"; //chaine de remplacement
     
    	ifstream file("essai.txt");
    	ofstream log  ("log.txt");
    	ofstream corrige ("corrigeSL.xml");
     
     
    	typedef vector<string> stringVector;
    	typedef stringVector::iterator stringVectorIt;
     
     
    	stringVector buffer;
    	stringVectorIt pos;
    	stringVectorIt start;
    	stringVectorIt end;
     
     
    	clock_t debut = clock() ;
     
    	while(getline(file,buffer[indice]))  {
     
    		//string::size_type pos; 
    		start=buffer[indice].begin();
    		end=buffer[indice].end();
     
     
    		if((pos==buffer[indice].find(str))!=end) {
     
    			nbtrouve++;
    			log << "la chaine se trouve a l'octet "<<pos<<'\n';
    			log <<buffer[indice]<<endl;
    			log <<"++++++++++++++++++++++++++++++++++++++++"<<endl;
    			log <<"FIN : LA CHAINE A ETE TROUVEE "<<nbtrouve<<" fois"<<endl;
     
    			//remplacement de la chaine  
    			replace(pos, end, str, strCorrection);
    			corrige<<buffer[indice];
    		}
    		indice++;
     
    	}
     
     
    	if (nbtrouve==0) {
    		log<<"La chaine n'a pas ete trouvee"<<endl;
    	}
     
    	clock_t fin = clock() ;
    	double duree_sec = double(fin-debut) / CLOCKS_PER_SEC ;
    	log << endl ;
    	log << "duree en sec = " << duree_sec << endl ;
     
    }

    Je commence tout juste mes premiers avec la stl ce qui explique ma maladresse (sans vraiment la justifier :-) ).

    Merci d'avance pour toute réponse. surtout pour votre patiente.

    Sempire

  20. #20
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Les chaines std::string fournissent bien des itérateurs (change de doc ?).
    Sinon charger ta ligne dans un élément non encoré réservé du vecteur va t'exploser à la figure. On commence toujours par lire la chaine, pour pouvoir ensuite l'empiler.

    Note: stocker dans un vecteur risque de ne pas être super efficace si tu comptes charger un fichier de 50Mo. Surtout que tu ne dois pas t'intéresser à stocker en mémoire l'intégralité des résultats.

    N'oublie pas que replace() ne remplace qu'un seul caractère par un autre caractère, et non des groupes de caractères.

    Tu auras plus vite fait de t'installer tr, sed ou perl.

Discussions similaires

  1. Remplacer des caractères spéciaux dans une chaine
    Par enzostar dans le forum Langage
    Réponses: 5
    Dernier message: 30/09/2012, 00h16
  2. Fonction qui remplace des caractères spéciaux
    Par ViRouF dans le forum SQL Procédural
    Réponses: 6
    Dernier message: 07/08/2006, 11h24
  3. [chaine de caractères]Remplacement de caractères spéciaux
    Par zeke the mouarfor dans le forum C
    Réponses: 5
    Dernier message: 05/06/2006, 19h30
  4. Soucis avec le remplacement de caractères spéciaux
    Par Oluha dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 04/07/2005, 12h42
  5. Remplacement de caractères spéciaux
    Par willowII dans le forum Format d'échange (XML, JSON...)
    Réponses: 2
    Dernier message: 26/04/2005, 19h13

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