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

Langage C++ Discussion :

Problème à la compilation pour début programme de diff


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 10
    Par défaut Problème à la compilation pour début programme de diff
    Bonjour,

    j'ai voulu commencer un code pour faire un diff entre deux chaines de caractère. mais je bloque dès le début au moment de la compilation. Et j'avoue que l'erreur retourné ne m'aide pas beaucoup est ce que quelqu'un peut m'aider?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    template<typename CHAR = char>
       ...
       typedef basic_string<CHAR> String;
       typedef list<String> Lstring;
        ...
        Lstring::const_iterator it;
    erreur retourné par GCC:
    error: expected ‘;’ before ‘it’
    Note j'utilise GCC 4.4.3
    le fichier source est: SFNDiff.cpp
    les erreurs de compilation sont dans le fichier: sortie.txt

    A+,
    Mahorais
    Fichiers attachés Fichiers attachés

  2. #2
    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
    Ajoute déjà typename en début de ligne 34.

  3. #3
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Bonjour.


    Dans ta classe, Lstring est un typedef sur un type qui dépend d'un paramètre template std::list< std::basic_string<CHAR> >.
    Autrement dit, il n'est pas vraiment défini tant que le paramètre template (en l'occurence, CHAR) n'est pas unifié avec un type réel.
    Du coup, le compilateur ne sait pas a priori que Lstring::iterator est un lui aussi type.

    Pour le lui indiquer, il faut utiliser le mot-clé typename :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typename Lstring::iterator
    D'ailleurs, tu aurais peut-être intérêt à faire un typedef dans ta classe.
    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef typename Lstring::iterator Literator

    Les paramètres template d'une classe template ne peuvent être déterminés automatiquement, contrairement à une fonction template.
    En effet, un type template ne peut être complètement défini que lorsque les paramètres template sont déteminés ; comment faire s'il faut attendre l'appel au contructeur pour déterminer ces paramètres ?
    Surtout que le constructeur appelé ne permettra pas forcément de déterminer tous les paramètres template...

    Il faut donc toujours indiquer explicitement quels paramètres template utiliser.
    Dans ton cas, je suppose qu'il s'agit de :
    [Edit]Je viens de voir que le paramètre template prend une valeur par défaut...
    Dans ce cas, je pense que l'erreur vient du fait que le type SFNDiff::String est privé.
    Par défaut, les éléments d'une classe sont privés.
    Du coup, de l'extérieur la compilateur ne peut pas faire la conversion char* => SFNDiff::String.
    Enfin, je crois...[/Edit]


    Sinon, après avoir regardé rapidement ton code, j'ai quelques remarques.
    En C++, on évite les #define.
    À la place, on définit des constantes de classe (à la place des « constantes » nommées), ou on utilise des fonctions inline (à la place des macros).
    F.A.Q. C++: Pourquoi utiliser une fonction inline au lieu d'une macro #define ?


    Une directive #if se termine toujours par la directive #endif.
    #ifndef est une directive #if...

    D'ailleurs, on ne met une garde du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #ifndef FICHIER_H
    #define FICHIER_H
    ...
    #endif
    que pour les fichiers d'en-tête.
    Les fichiers d'implémentation n'ont pas vocation à être inclus dans d'autres fichiers, donc cette garde y est inutile.

    Par ailleurs : F.A.Q. C++: Quels sont les identificateurs interdits par la norme ?.


    Au cas où...
    F.A.Q. C++: Quand utiliser / ne pas utiliser using namespace ?


    À part ça, la donnée membre m_originalText2 ne devrait pas plutôt être du type String ?

  4. #4
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 10
    Par défaut
    Bonjour,

    Merci beaucoup pour vos conseils.
    Je ne savais pas que typename permet de dire que ce qui suis est un type. Je pensais que c'était juste un synonyme de class dans la déclaration d'un template:
    template<class T> ou template<typename T>
    J'ai suivis vos conseils et en effet je n'ai plus le même problème qu'avant. Ceci dit j'ai eut pas mal d'autre problèmes.

    mais avant, les lignes suivantes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #ifndef FICHIER
    #define FICHIER
     
    #endif
    A l'origine je voulais faire 3 fichiers, un pour le .h un pour le .cpp et un autre pour le main(). En cour de route j'ai changé d'avis par pure fainéantise.

    il y a un truc curieux, en effet malgrès le:
    template<typename CHAR = char>
    je suis quand même obligé de définir un type lorsque je crée une instance de SFNDiff

    et j'ai aussi dû modifier le constructeur SFNDiff
    ancien code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	SFNDiff(String iw1,String iw2):m_originalText1(iw1), m_originalText2(iw2)
    	{
    		StoreWord(iw1,FIRST_STRING);
    		StoreWord(iw2,SECOND_STRING);
    	}
    nouveau code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	SFNDiff(String iw1,String iw2)
    	{
    		m_originalText1.assign(iw1.begin(),iw2.end());
    		m_originalText2.assign(iw2.begin(),iw2.end());
    		StoreWord(iw1,FIRST_STRING);
    		StoreWord(iw2,SECOND_STRING);
    	}
    maintenant j'ai un problème à la ligne 50:
    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
     
    ...
    template<typename CHAR = char>
    class SFNDiff
    {
    protected:
    	typedef CHAR Char;
    	typedef std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> > String;
    	typedef std::list<String> Lstring;
    	typedef typename Lstring::const_iterator LConstIterator;
            ...
    	virtual void StoreWord(const String& s,bool isWord1)
            {
                    ...
    		LConstIterator it = (LConstIterator) s.begin();
    l'erreur est:
    SFNDiff.cpp:97: instantiated from here
    SFNDiff.cpp:50: error: no matching function for call to ‘std::_List_const_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::_List_const_iterator(__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >)’
    /usr/include/c++/4.4/bits/stl_list.h:207: note: candidates are: std::_List_const_iterator<_Tp>::_List_const_iterator(const std::_List_iterator<_Tp>&) [with _Tp = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]
    /usr/include/c++/4.4/bits/stl_list.h:204: note: std::_List_const_iterator<_Tp>::_List_const_iterator(const std::_List_node_base*) [with _Tp = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]
    /usr/include/c++/4.4/bits/stl_list.h:200: note: std::_List_const_iterator<_Tp>::_List_const_iterator() [with _Tp = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]
    /usr/include/c++/4.4/bits/stl_list.h:189: note: std::_List_const_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::_List_const_iterator(const std::_List_const_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)
    SFNDiff.cpp:67: instantiated from ‘SFNDiff<CHAR>::SFNDiff(std::basic_string<_CharT, std::char_traits<_CharT>, std::allocator<_CharT> >, std::basic_string<_CharT, std::char_traits<_CharT>, std::allocator<_CharT> >) [with CHAR = char]’


    Et en fait bien vue pour le:
    String m_originalText2;

    note la source est dans:
    Type de fichier : cpp SFNDiff.cpp (2,0 Ko, 0 affichages)

    le résultat de la compilation est dans:
    Type de fichier : txt sortie_v2.txt (3,0 Ko, 0 affichages)

    A+,
    Mahorais
    Fichiers attachés Fichiers attachés

  5. #5
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Toutes les erreurs de compilation n'ont qu'une seule cause : tu essaies de transformer un itérateur de chaîne de caractères en un itérateur de liste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #line 50 "SFNDiff.cpp"
    LConstIterator it = (LConstIterator) s.begin();
    Ces deux types n'ont rien à voir, il est normal que le compilateur te refuse ce code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typename String::const_iterator it = s.begin();
    Ceci dit, étant donné que tu parcours toute la chaîne, autant utiliser une boucle adéquate :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (typename String::const_iterator it = s.begin(); it != s.end(); ++it) {
        (...)
    }

    Je vais profiter de cette erreur pour faire deux petites remarques.
    En C++, on utilise les opérateurs de transtypage C++ (même si celui venu du C fonctionne aussi, en général).
    F.A.Q. C++: Comment effectuer une conversion de type explicite (cast) ?

    Normalement, on peut construire implicitement un itérateur constant (*) à partir d'un itérateur non constant (*) du même type.


    Bon, que dire d'autre...

    Pourquoi inclues-tu le fichier d'en-tête « stdio.h » ?
    Tu n'utilises aucun des éléments qui y sont fournis.
    Si jamais tu devais l'utiliser, sache que, comme d'autres fichiers d'en-tête C importants, il est redéfini pour correspondre aux conventions C++ : #include <cstdio>.


    Pour tes constantes FIRST_STRING et SECOND_STRING, je t'avais dit de faire des constantes de classe.
    Elles n'ont aucune raison d'être visible en dehors du cadre de la classe SFNDiff, et donc ne doivent pas être globales.

    D'ailleurs, je ne suis pas sûr qu'elles soient vraiment utiles.
    Tu peux très bien faire sans.
    Par exemple, pour StoreWord, étant donné qu'elle n'est pas publique, tu peux passer directement en paramètre la liste à remplir, plutôt que ces constantes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    StoreWord(String const& s, Lstring& result)
    {
        (...)
    }
     
     
    // À l'appel :
     
    StoreWord(iw1, m_text1);
    Mais c'est toi qui vois...


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> > String;
    Ne t'embête pas avec les deux derniers paramètres si tu n'as pas l'intention de définir des valeurs autres que celles par défaut.
    La déclaration de std::basic_string est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template <typename CharT, typename Traits = char_traits<CharT>, typename Alloc = allocator<CharT> >
    class basic_string;
    donc, à moins d'avoir vraiment besoin de la classe de traits ou de l'allocateur, ne t'en occupe pas.
    Après tout, std::string est défini comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef basic_string<char> string;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #line 48 "SFNDiff.cpp"
    result.erase(result.begin(),result.end());
    Tu sais, tout conteneur qui se respecte possède une fonction membre clear()...


    Pour le constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SFNDiff(String iw1,String iw2) : m_originalText1(iw1), m_originalText2(iw2)
    {
        (...)
    }
    F.A.Q. C++: Mes constructeurs doivent-ils utiliser les listes d'initialisation ou l'affectation ?


    (*) Comprendre « un itérateur sur des données constantes (resp. non constantes) ».

  6. #6
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 10
    Par défaut ça marche
    Bonjour,
    Merci pour toutes ces conseils et ces éclaircissement.
    Maintenant grâce à vous mon bout de code compile et fonctionne.

    voici ce que ça donne:
    > g++ -g -o sortie SFNDiff.cpp
    > ./sortie "a b c d" "x b c d"
    {SFNDiff[a b c d,x b c d]=abcd,xbcd}
    et 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
    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
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
    #include<iostream>
    #include<list>
    #include<string>
    #include<sstream>
     
     
    template<typename CHAR = char>
    class SFNDiff
    {
    protected:
    	typedef CHAR Char;
    	typedef std::basic_string<Char> String;
    	typedef std::list<String> Lstring;
    	typedef typename String::const_iterator SConstIterator;
    	typedef typename Lstring::const_iterator LConstIterator;
    	Lstring	m_text1;
    	String m_originalText1;
    	Lstring	m_text2;
    	String m_originalText2;
    	static const bool FIRST_STRING = true;
    	static const bool SECOND_STRING= false;
     
    protected:
    	const Lstring &GetText(bool bFirstTextAsked) const
    	{
    		return bFirstTextAsked?m_text1:m_text2;
    	}
     
    	String ToString(bool bFirstTextAsked) const
    	{
    		const Lstring & text = GetText(bFirstTextAsked);
    		String result;
    		if(text.begin()!=text.end())
    		{
    			for(LConstIterator it = text.begin();it!=text.end();it++)
    			{
    				const String &c = *it;
    				result += c;
    			}
    		}		return result;
    	}
     
    	virtual bool IsNotSeparator(const Char &elem) const
    	{
    		return elem!=Char('\t') && elem!=Char(' ');
    	}
    	virtual void StoreWord(const String& s,bool isWord1)
    	{
    		Lstring& result = isWord1?m_text1:m_text2;
    		result.clear();
    		SConstIterator it = s.begin();
    		while(it!=s.end())
    		{
    			if(IsNotSeparator(*it))
    			{
    				String sWorld;
    				sWorld += Char(*it);
    				result.push_back(sWorld);
    			}
    			it++;
    		}
    	}
    	const String& GetString(bool bFirstWord) const
    	{
    		return bFirstWord?m_originalText1:m_originalText2;
    	}
    	template<typename Char>
    	friend std::ostream& operator<<(std::ostream& out,const SFNDiff<Char>& diff);
    	virtual void OutPutStream(std::ostream& out) const
    	{
    		out << "{SFNDiff[" << m_originalText1 << "," << m_originalText2 << "]=";
    		out << ToString(FIRST_STRING) << "," << ToString(SECOND_STRING) << "}";
    	}
    public:
    	SFNDiff(String iw1,String iw2):m_originalText1(iw1),m_originalText2(iw2)
    	{
    		StoreWord(iw1,FIRST_STRING);
    		StoreWord(iw2,SECOND_STRING);
    	}
    };
     
    template<typename Char>
    std::ostream& operator<<(std::ostream& out,const SFNDiff<Char>& diff)
    {
    	diff.OutPutStream(out);
    	return out;
    }
     
     
    bool IsNbArgValid(int argc)
    {
    	return argc==3;
    }
     
    int main(int argc,char* argv[])
    {
    	if(IsNbArgValid(argc))
    	{
    		SFNDiff<char> diff(argv[1],argv[2]);
    		std::cout << diff << std::endl;
    	}else
    		std::cout << argv[0] << " is excpecting 2 arguments" << std::endl;
    	return 0;
    }

  7. #7
    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 mahorais Voir le message
    Je ne savais pas que typename permet de dire que ce qui suis est un type.
    Tu ferais bien de te renseigner sur cette seconde utilisation de typename, sinon, tu vas souvent rencontrer des soucis.

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 11/05/2009, 20h29
  2. Problème de compilation pour une DLL
    Par Faith's Fall dans le forum C++Builder
    Réponses: 8
    Dernier message: 24/03/2008, 15h40
  3. Réponses: 2
    Dernier message: 31/01/2008, 21h41
  4. [UBUNTU] Problème de compilation pour installer le logiciel irssi
    Par Creature_Funebre dans le forum Ubuntu
    Réponses: 4
    Dernier message: 29/04/2007, 18h09

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