[C++] problème char*
Résolu/Fermé
KX
Messages postés
16755
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
12 février 2025
-
22 mai 2009 à 21:31
mamiemando Messages postés 33566 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 11 mars 2025 - 23 mai 2009 à 16:33
mamiemando Messages postés 33566 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 11 mars 2025 - 23 mai 2009 à 16:33
A voir également:
- [C++] problème char*
- Coco char - Accueil - Réseaux sociaux
- Remplaçant de Coco : quelles solutions pour tchater gratuitement en ligne ? - Accueil - Réseaux sociaux
- Coco chat connexion sur mobile, le tchat est fermé ? ✓ - Forum Réseaux sociaux
- Site coco chat (incitation a payer) ✓ - Forum Vos droits sur internet
- If char ✓ - Forum Programmation
6 réponses
mamiemando
Messages postés
33566
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
11 mars 2025
7 833
23 mai 2009 à 13:11
23 mai 2009 à 13:11
Pour comprendre le code que je t'ai codé il faut d'abord connaître les opérateurs du C sur les bits et la manière dont est stocké en mémoire un entier.
Manipuler des bits (sans mauvais jeu de mot) en C :
Les opérateurs s'appliquent sur des champs de bits faisant le même nombre de bit (éventuellement au travers d'un cast implicite) :
- x & y effectue un ET logique bit à bit de x et y
- x | y effectue un OU logique bit à bit de x et y
- ~x effectue un NON logique bit à bit sur x
- x << n décale le champ de bit x de n cran à gauche. Les bits qui "apparaissent" à droite valent 0. Par exemple 1 << 4 (ie 0000....01 << 4 en binaire revient à écrire 000....010000).
- x >> n fait la même chose, mais à droite
De la même façon que tu as +=, *=, -=, %=, /= pour les opérateurs de base, tu as les opérateurs |=, &=, <<= etc...
Au niveau du stockage d'un entier les bits de poids faible décrivent les puissances de 2 les plus faibles et les bits de poids forts les puissances de 2 les plus élevées. Ainsi 5 = 1*4 + 0*2 + 1*1 s'écrit en binaire 0....0101. Si l'entier est signé (int au lieu de unsigned), le bit de poids fort vaut 1 si le nombre est négatif et 0 sinon.
Les bools (sans mauvais jeu de mot)
Les bool font effectivement 1 octet (pour des histoires d'adressage et de performance j'imagine) mais si ta donnée est une valeur vrai/fausse, ton programme se doit d'être lisible et donc d'utiliser un bool malgré tout.
De plus tu t'en sors bien car un char fera toujours 1 octet mais a priori si le type wide-char n'existait pas il pourrait être amené à grossir (de la même façon que les int font 32 bits ou 64 bits selon ton architecture de machine). Bref, reste rigoureux au niveau des types.
Les std::ostream
Parmi les std::ostream tu as effectivement std::cout mais aussi std::cerr et surtout tout ce qui est std::ofstream et std::ostringstream, c'est-à-dire des flux vers des fichiers ou des buffers.
Bonne chance
Manipuler des bits (sans mauvais jeu de mot) en C :
Les opérateurs s'appliquent sur des champs de bits faisant le même nombre de bit (éventuellement au travers d'un cast implicite) :
- x & y effectue un ET logique bit à bit de x et y
- x | y effectue un OU logique bit à bit de x et y
- ~x effectue un NON logique bit à bit sur x
- x << n décale le champ de bit x de n cran à gauche. Les bits qui "apparaissent" à droite valent 0. Par exemple 1 << 4 (ie 0000....01 << 4 en binaire revient à écrire 000....010000).
- x >> n fait la même chose, mais à droite
De la même façon que tu as +=, *=, -=, %=, /= pour les opérateurs de base, tu as les opérateurs |=, &=, <<= etc...
Au niveau du stockage d'un entier les bits de poids faible décrivent les puissances de 2 les plus faibles et les bits de poids forts les puissances de 2 les plus élevées. Ainsi 5 = 1*4 + 0*2 + 1*1 s'écrit en binaire 0....0101. Si l'entier est signé (int au lieu de unsigned), le bit de poids fort vaut 1 si le nombre est négatif et 0 sinon.
Les bools (sans mauvais jeu de mot)
Les bool font effectivement 1 octet (pour des histoires d'adressage et de performance j'imagine) mais si ta donnée est une valeur vrai/fausse, ton programme se doit d'être lisible et donc d'utiliser un bool malgré tout.
De plus tu t'en sors bien car un char fera toujours 1 octet mais a priori si le type wide-char n'existait pas il pourrait être amené à grossir (de la même façon que les int font 32 bits ou 64 bits selon ton architecture de machine). Bref, reste rigoureux au niveau des types.
Les std::ostream
Parmi les std::ostream tu as effectivement std::cout mais aussi std::cerr et surtout tout ce qui est std::ofstream et std::ostringstream, c'est-à-dire des flux vers des fichiers ou des buffers.
Bonne chance
mamiemando
Messages postés
33566
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
11 mars 2025
7 833
23 mai 2009 à 01:42
23 mai 2009 à 01:42
Dans le cas particulier des bases qui sont une puissances de deux et sur un nombre entier, cette méthode est très peu efficace car le mémoire est déjà encodé en base 2 en mémoire.
Exemple :
De la même façon tu peux facilement faire des fonctions très efficaces pour les bases 8 et 16. Attention pour les int, le bit de poids fort est le bit de signe.
Bonne chance
Exemple :
#include <iostream> void convert_2(std::ostream & out,unsigned x){ unsigned i; for(i=0;i<8*sizeof(x);++i){ out << (x & (1 << (8*sizeof(x) - i - 1)) ? 1 : 0); } out << std::endl; } int main(){ int x = 27; convert_2(std::cout,x); return 0; }
De la même façon tu peux facilement faire des fonctions très efficaces pour les bases 8 et 16. Attention pour les int, le bit de poids fort est le bit de signe.
Bonne chance
KX
Messages postés
16755
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
12 février 2025
3 020
23 mai 2009 à 02:44
23 mai 2009 à 02:44
En fait je faisais ce calcul sur un type gdentier<nbBit> défini par bool T[nbBit+1]
Au départ je faisais comme ça parce que je pensais que bool était défini sur un bit (c'était écrit comme ça dans mon cours)
Mais comme sizeof(gdentier<n>)==n+1 ça veut dire que 1 bool=1 octet, donc autant prendre un char !!!
Du coup je vais recommencer (pas tout heureusement, c'est à ça que sert la conception objet)
Par contre j'ai des questions par rapport à ton code...
Dans les paramètres (std::ostream & out,unsigned x)
Que peut être out sinon std::cout ? Quel est le type de x ?
Et ensuite 1 << (8*sizeof(x) - i - 1) apparemment c'est un bool mais que signifie l'opérateur << ?
Et x & 1, x & 0 ça fait quoi ?
Désolé, j'ai une soif d'apprendre immense, mais mes cours ne suffisent plus ^^
Au départ je faisais comme ça parce que je pensais que bool était défini sur un bit (c'était écrit comme ça dans mon cours)
Mais comme sizeof(gdentier<n>)==n+1 ça veut dire que 1 bool=1 octet, donc autant prendre un char !!!
Du coup je vais recommencer (pas tout heureusement, c'est à ça que sert la conception objet)
Par contre j'ai des questions par rapport à ton code...
Dans les paramètres (std::ostream & out,unsigned x)
Que peut être out sinon std::cout ? Quel est le type de x ?
Et ensuite 1 << (8*sizeof(x) - i - 1) apparemment c'est un bool mais que signifie l'opérateur << ?
Et x & 1, x & 0 ça fait quoi ?
Désolé, j'ai une soif d'apprendre immense, mais mes cours ne suffisent plus ^^
KX
Messages postés
16755
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
12 février 2025
3 020
23 mai 2009 à 12:30
23 mai 2009 à 12:30
Après une petite recherche je crois avoir compris le traitement des bits...
Mais je vais partir sur des bases plus simples avec bitset plutôt que bool
Comme ça je devrais pouvoir faire mes calculs bits à bits sans ces opérateurs de bits que je ne connais pas
Mais je vais partir sur des bases plus simples avec bitset plutôt que bool
Comme ça je devrais pouvoir faire mes calculs bits à bits sans ces opérateurs de bits que je ne connais pas
#include <bitset> using namespace std; template <int nbBit=1> class gdentier { private: bitset<nbBit> N; public : inline bool get(const int i) { return N[i]; } inline void set(const int i, const bool b) { N[i]=b; } };Par contre je me demande toujours ce qu'on peut utiliser comme ostream à part cout...
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
KX
Messages postés
16755
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
12 février 2025
3 020
23 mai 2009 à 15:37
23 mai 2009 à 15:37
Bon j'ai un peu avancé, mais je me retrouve bloqué quand même...
j'ai réussi à implémenter les fonctions de conversions en adaptant le code que tu m'as donné hier.
Mais je n'arrive pas à faire l'opérateur <<
Si là encore tu pouvais m'aider... Merci !
j'ai réussi à implémenter les fonctions de conversions en adaptant le code que tu m'as donné hier.
Mais je n'arrive pas à faire l'opérateur <<
// Dans mon .hpp inline void convert_2(std::ostream &); // OK inline void convert_16(std::ostream &); // OK inline void convert_256(std::ostream &); //OK friend std::ostream &operator<<(std::ostream &, const gdentier &); [Warning] friend declaration `std::ostream& operator<<(std::ostream &, const gdentier<nbBit> &)' declares a non-template function [Warning] (if this not way you intended, make sure the function template has already been declared and add <> after the function name here)-Wno-non-template-friend disables this warning // Dans Mon .cpp template <unsigned nbBit> std::ostream &operator<<(std::ostream & out, const gdentier<nbBit> & g) { if (out==std::cout) g.convert_16(out); else if (out==std::cerr) g.convert_2(out); // pour cerr on détaille else g.convert_256(out); // en particulier pour les fichiers return out; } // Dans mon main() gdentier<8> a(72); cerr << a << endl; // 01001000 cout << a << endl; // 4B [Linker error] undefined reference to `operator<<(std::ostream &, gdentier<8u> const&)' [Linker error] undefined reference to `operator<<(std::ostream &, gdentier<8u> const&)' Id returned 1 exit statusPS. L'erreur revient quelque soit l'implémentation de l'opérateur, mais je ne sais pas si on peut choisir un flux comme je l'ai fait avec mes if(out==)
Si là encore tu pouvais m'aider... Merci !
mamiemando
Messages postés
33566
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
11 mars 2025
7 833
23 mai 2009 à 16:33
23 mai 2009 à 16:33
Pour ton opérateur << vu qu'il est template, il doit être implémenté dans le .hpp
Personnellement, je trouverais mieux en terme de design que la manière dont g est écrit dépende d'un paramètre autre que le flux de sortie (par exemple un membre de la classe). En fait je ne pensais même pas que c'était possible tellement l'approche est peu commune :-).
En ce qui me concerne je ferais plutôt une méthode write qui prend en paramètre la base en paramètre et un opérateur << inline qui appelle cette méthode.
Pour plus d'informations sur les templates :
http://www.commentcamarche.net/faq/sujet 11194 les templates en c
Bonne chance
template <unsigned nbBit> std::ostream & operator << (std::ostream & out,const gdentier<nbBit> & g){ if (out == std::cout) g.convert_16(out); else if(out == std::cerr) g.convert_2(out); // pour cerr on détaille else g.convert_256(out); // en particulier pour les fichiers return out; }
Personnellement, je trouverais mieux en terme de design que la manière dont g est écrit dépende d'un paramètre autre que le flux de sortie (par exemple un membre de la classe). En fait je ne pensais même pas que c'était possible tellement l'approche est peu commune :-).
En ce qui me concerne je ferais plutôt une méthode write qui prend en paramètre la base en paramètre et un opérateur << inline qui appelle cette méthode.
Pour plus d'informations sur les templates :
http://www.commentcamarche.net/faq/sujet 11194 les templates en c
Bonne chance