GESTION DE CHAINE DE CARACTÉRE EN C++ AVEC NSTRING

soso62fr Messages postés 59 Date d'inscription mardi 28 novembre 2006 Statut Membre Dernière intervention 28 avril 2010 - 11 nov. 2009 à 23:36
sboli Messages postés 10 Date d'inscription vendredi 14 août 2009 Statut Membre Dernière intervention 31 mai 2010 - 16 nov. 2009 à 10:50
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/50841-gestion-de-chaine-de-caractere-en-c-avec-nstring

sboli Messages postés 10 Date d'inscription vendredi 14 août 2009 Statut Membre Dernière intervention 31 mai 2010
16 nov. 2009 à 10:50
On remplace le Z par un N ...

L'opérateur + en tant que fonction libre à deux arguments:
NString operator+(const NString& lhs, const NString& rhs);
Pour t'en convaincre essaie ceci:
NString str(" ca marche pas");
str = "coucou," + str;

La fonction c_str() devrait renvoyer un const char* pour éviter que l'user foute le bordel en modifiant la chaine à l'extérieur.

A qui revient la responsabilité de StrCopy dans copy() ? -> boost::shared_ptr dans l'idéal.
Sinon je trouve que c'est une implémentation naïve de string, donc à ne pas utiliser.

Désolé si j'ai dit des choses qui on déjà été dites, je n'ai pas lu les autres commentaires.
uaip Messages postés 1466 Date d'inscription mardi 20 février 2007 Statut Membre Dernière intervention 7 février 2011
14 nov. 2009 à 12:56
Ah oui, return (!nbr) est "évidemment" un booléen, mais je voyais plutôt return (nbr) comme une récupération de valeur, et non comme un test pour savoir si la variable valait zéro.
Ma solution est en effet pas tellement bonne non plus. Mais je voulais apporter cette précision parce-que certains compilos sont chiants avec les booléens.
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
14 nov. 2009 à 10:37
> C'est en effet faux, mais ça aussi : bool NString::IsEmpty() { return m_Count; }
> comme tu le dis, CptPingu.

Petit inattention de ma part ça aurait du être bool NString::IsEmpty() { return !m_Count; }, au temps pour moi.

> La fonction doit retourner true si la chaine est vide, donc si m_Count = 0, or true != 0 en C++, et puis m_Count n'est pas un booléen.

Si son code avait été bien géré, alors m_Count aurait du être un unsigned int ou être conçu de manière à ne pas descendre en dessous de 0, et là plus de problème.
De plus, j'ai aussi donné une méthode plus robuste: "return m_Count <= 0", qui ne se base pas sur une conversion de m_Count, mais bien sur un résultat (une comparaison EST une expression booléenne).
A noter que "!m_Count" est aussi une expression booléenne.

> Pour moi : bool NString::IsEmpty() { return (m_Count)?false:true; } me semble correct.

Et c'est là que ce que tu dis est étrange. Tu critiques le fait que se baser sur la transformation en booléen de m_Count est bancale (ce qui peut être vrai), mais cette technique se base aussi dessus. Si m_Count vaut -1, tu retourneras "false" aussi !
Techniquement, cette solution fonctionne, mais est extrêmement inélégante, car elle fait un double travail inutile.

D'une manière générale on préfère toujours écrire:

return a < b;

Plutôt que (j'exagère un peu):

if ((a < b) == true)
{
return true;
}
else
{
return false;
}
uaip Messages postés 1466 Date d'inscription mardi 20 février 2007 Statut Membre Dernière intervention 7 février 2011
14 nov. 2009 à 02:02
Salut,
Je suis d'accord quant à l'utilité de ce code... Il aurait pu être intéressant pour des gens curieux d'apprendre par exemple, s'il avait été un minimum commenté.
Idem pour les fonctions strlen, etc.
Mais pour ceci : bool NString::IsEmpty() { return m_Count ? true : false; }

C'est en effet faux, mais ça aussi : bool NString::IsEmpty() { return m_Count; }
comme tu le dis, CptPingu.
La fonction doit retourner true si la chaine est vide, donc si m_Count = 0, or true != 0 en C++, et puis m_Count n'est pas un booléen.
Pour moi : bool NString::IsEmpty() { return (m_Count)?false:true; }
me semble correct.

Cordialement, uaip.
cs_xmustapha Messages postés 44 Date d'inscription mardi 1 août 2006 Statut Membre Dernière intervention 15 juillet 2011 24
12 nov. 2009 à 21:08
Merci de vos coms
soso62fr Messages postés 59 Date d'inscription mardi 28 novembre 2006 Statut Membre Dernière intervention 28 avril 2010 8
12 nov. 2009 à 17:33
Euh .... D'accord, je m'avoue vaincu ! :p Car je vois que ton raisonnement est correct !

Donc je retire ce que j'ai dis sur les conditions ternaires ...

Ciao CptPingu ;)
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
12 nov. 2009 à 13:38
> ?? C'est peut être parce que j'ai écrit ça à minuit ou que je n'avais pas fait attention au type retourné, bref !
:p

> Les conditions ternaires sont très utiles pour les "GROS" programmes,
Ca ne change rien. Un bon programme est découpé en modules, et en petite fonction. Une fonction ne devrait pas excéder 50 lignes en moyennes.
Le seul cas ou le ternaire est pertinent, c'est dans le cas d'une répétition successive de conditions quasis identiques.

>Merci pour cette correction CptPingu mais cependant je suis pas d'accord avec ça :
> >Gagner des lignes dans un code ne fait pas aller celui-ci plus vite.
Bien différencier: gain de ligne et clarté du code. Les deux ne sont pas liés, et je pense que tu voulais plus parlé de clarté de code que de véritable gain de ligne.
soso62fr Messages postés 59 Date d'inscription mardi 28 novembre 2006 Statut Membre Dernière intervention 28 avril 2010 8
12 nov. 2009 à 13:22
Ahhhhh !! Quelle erreur ! Je sais pas pourquoi j'ai écrit ça :
>m_Count ? true : false;

?? C'est peut être parce que j'ai écrit ça à minuit ou que je n'avais pas fait attention au type retourné, bref !

Merci pour cette correction CptPingu mais cependant je suis pas d'accord avec ça :

>Gagner des lignes dans un code ne fait pas aller celui-ci plus vite.

Les conditions ternaires sont très utiles pour les "GROS" programmes, ils agissent bien sûr sur le code source lui même et non pas au rendu final, c'est-à-dire le fichier exécutable, mais j'avoue qu'ici ils sont quand même inutiles et rende le code moins lisible.
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
12 nov. 2009 à 10:17
> Tu optimises pas trop ton code, tu peux gagner des lignes, par exemple avec les conditions ternaires.
Non. Les opérateurs ternaires n'optimise pas le code. Gagner des lignes dans un code ne fait pas aller celui-ci plus vite. De plus, l'opérateur ternaire est moins lisible, donc est souvent à éviter.

> bool NString::IsEmpty()
> {
> return m_Count ? true : false;
> }
Beurk, mauvais exemple. Dans le cas d'un booléen, on ne renvoit jamais si celui-ci est vrai ou faux, mais directement celui-ci:

bool NString::IsEmpty()
{
return m_Count;
}

Ou à la limite:

bool NString::IsEmpty()
{
return m_Count <= 0;
}

Sinon, je suis assez d'accord avec ce qui est dit. Ce genre de code existe déjà sur code-source. C'est une énième ré-implémentation de la classe String, sans grande originalité (une classe string utilisant un flyweight ou une lazy copy à la QString aurait été plus intéressant...).
soso62fr Messages postés 59 Date d'inscription mardi 28 novembre 2006 Statut Membre Dernière intervention 28 avril 2010 8
11 nov. 2009 à 23:36
Elle* (une class pas un class lol)
soso62fr Messages postés 59 Date d'inscription mardi 28 novembre 2006 Statut Membre Dernière intervention 28 avril 2010 8
11 nov. 2009 à 23:36
Salut!
Ta classe est une classe de base mais cependant il est loin d'être optimisée :

1 : Dans le corps de operator+( const NString &Str ), les instructions sont en trop et inutiles car ils sont déjà écris dans operator+( const NString * Str ) donc tu peux te servir de cette dernière, en gros tu pouvais écrire ça :

operator+( const NString &Str ) {
operator+ ( Str->m_str );
}

Ceci est notamment valable pour operator=, operator+ et le constructeur !

2 : Tu réinvente la roue, et ça... c'est parfaitement inutile ! Tu réimplante strlen, strcat (pour l'opérateur +) pour aucune cause apparente !

3 : Dans l'opérateur +, tu dés-alloues la mémoire et tu alloues ensuite la mémoire avec la bonne taille... Une curieuse façon de faire, tu pouvais très bien agrandir ou réduire la mémoire sans pour autant la dés-allouer, par exemple avec la fonction realloc (pour le C mais marche parfaitement pour le C++).

4 : Tu optimises pas trop ton code, tu peux gagner des lignes, par exemple avec les conditions ternaires. Ex avec bool NString::IsEmpty() :

bool NString::IsEmpty() {
return m_Count ? true : false;
}

Tu peux aussi optimiser la vitesse avec quelques conditions en plus, exemple tu peux éviter de ré-allouer la mémoire si la taille de la chaine à concaténer est à 0, exemple : chaine + ""