Des chaines en C++ (Urgent!) [Résolu]

Signaler
Messages postés
44
Date d'inscription
vendredi 21 janvier 2005
Statut
Membre
Dernière intervention
22 mai 2006
-
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
-
ce bout de code est censé servir à supprimer tous les espaces superflus à gauche et à droite d'une chaîne. Exemple :
" Bon jour " devient "Bon jour"

mais ça ne marche pas. Je reçois un message d'erreur au sujet de remove. no matching function for call to basic_string<etc...

int epurer_chaine(const string&s){
int a=0,i;
while(s[0]==' ')s.remove(0,1);
while(s[i=s.size()-1]==' '){
s.remove(i,1);
a=1;
}
return a;
}

16 réponses

Messages postés
6535
Date d'inscription
lundi 16 décembre 2002
Statut
Modérateur
Dernière intervention
22 août 2010
7
-erase n'est pas membre de la classe string;

-si tu passes ta chaine en const, tu auras du mal à la modifier sans faire raler le compilateur

-à quoi sert a?



Voila une solution qui ressemble a ce que tu avais écrit au début:



int epurer_chaine(string&s){

int a=0,i;

while(s[0]==' ')s.erase(s.begin());

while(s[i=s.size()-1]==' '){

s.erase(s.end() - 1);

a=1;

}

return a;

}
Messages postés
1403
Date d'inscription
lundi 23 février 2004
Statut
Membre
Dernière intervention
11 janvier 2009
3
Voilà ce que tu cherches :
/*Enlève les espaces du début*/
char * LTrim(char * Chaine)
{
unsigned int i = 0;
unsigned int j = 0;
unsigned int Longueur = strlen(Chaine);


if (Longueur > 0)
{
while (Chaine[i] == ' ') i++;
if (i > 0)
{
for (j = 0;j <= (Longueur - i);j++) Chaine[j] = Chaine[(i + j)];
Chaine[j] = 0;
}
}
return Chaine;
}/*Enlève les espaces de la fin*/
char * RTrim(char * Chaine)
{
unsigned int i = 0;
unsigned int Longueur = strlen(Chaine);


if (Longueur > 0)
{
i = Longueur;
while (Chaine[i - 1] == ' ') i--; if (i <Longueur) Chaine[i] 0;
}
return Chaine;
}/*Enlève les espaces du début et de la fin*/
char * Trim(char * Chaine)
{
LTrim(Chaine);
RTrim(Chaine);
return Chaine;
}

YOYO, @+.
YOYO
Messages postés
44
Date d'inscription
vendredi 21 janvier 2005
Statut
Membre
Dernière intervention
22 mai 2006

merci, mais j'essai de résoudre le probleme avec la classe string.
j'ai d'ailleurs recopier un exemple d'un livre, et on m'affiche le même message d'erreur.
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
allez plaisanterie du soir... si on veut coder alors:

__declspec(naked) int __fastcall bntrim(char* psrc) // retour nombre char
{ // ECX = psrc
__asm {
mov [esp-4], ecx
mov eax, ecx
Ltrm1:
mov dl, [ecx]
inc ecx
cmp dl, 32
je short Ltrm1
dec ecx ; // 1er char != 32
dec eax
Ltrm2:
mov dl, [ecx]
inc eax
inc ecx
mov [eax], dl
test dl, dl
jnz short Ltrm2
mov ecx, [esp-4] ; // eax est zero final
Ltrm3:
mov byte ptr[eax], 0
cmp eax, ecx
jna short Ltrm4
dec eax
cmp byte ptr[eax], 32
je short Ltrm3
inc eax
Ltrm4:
sub eax, ecx
ret 0
}
}

servirait à quoi de retourner le pointeur char* qu'on reçoit, l'appelant l'a déjà puisqu'il le passe à la func.

ciao...
BruNews, MVP VC++
Messages postés
44
Date d'inscription
vendredi 21 janvier 2005
Statut
Membre
Dernière intervention
22 mai 2006

Ton message ne m'est d'aucune aide. Si tu peux m'aider, merci de me répondre.
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
:)

j'adore la réponse de brunews...



Pour ta réponse, cherche un peu en utilisant

find_first_not_of de la classe std::string par exemple.




Ma participation à la saturation du net:
http://hylvenir.free.fr
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
Si on veut pas coder ( ou si on travaille sur un PA-RISC :) )



string ltrim( const string& s, const char* c = " " )

{

string::size_type found = s.find_first_not_of( c );

if ( found == string::npos )

found = s.size();

return string( s, found );

}



// j'ai viré le a pour l'occasion.

Vechio56, quand tu écris erase, faut lire remove ;)




Ma participation à la saturation du net:
http://hylvenir.free.fr
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
si la chaine est " ";


s.size() vaut 0 à la fin de la première boucle, donc

accès à s[-1]....





int epurer_chaine(string&s){

int a=0,i;

while(s[0]==' ')s.erase(s.begin());

while(s[i=s.size()-1]=='
'){
/// <-------- bug

s.erase(s.end() - 1);

a=1;

}

return a;

}

Ma participation à la saturation du net:
http://hylvenir.free.fr
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
Voila qu'il a enfin sa réponse et, cerise sur le gateau, y a même toutes chances que ce soit plus lent qu'un 'Trim' VB.
Il en faut pour tous les gouts...

ciao...
BruNews, MVP VC++
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
Entre une réponse asm

et une réponses bugguée, mon coeur balance...



Il est vraiment aussi mauvais que ça cl ?


Ma participation à la saturation du net:
http://hylvenir.free.fr
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
while(s[0]==' ')s.erase(s.begin());
tu imagines combien de fois ça parcourt la chaine au complet et autant d'alloc desalloc, un vrai poème...
Dans tous les cas, Hylvenir, je ne vois pas tellement d'autre soluce avec des 'string'.

Je te rassure sur ma func ASM, aucun bug depuis des années qu'elle tourne. Niveau perf, sera dur à battre.

ciao...
BruNews, MVP VC++
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
argh... c'est bien ce qu'il me semblait.

C'est pas ma solution ça, c'est la solution de vecchio. (j'indiquais juste la ligne

de son bug). je te confirme que c'est assez moyen comme méthode.

(je suis étonné que ce soit la solution acceptée d'ailleurs).



En fait voici (IHMO) deux autres solutions selon le besoin.

La première trimp_cpp va allouer une nouvelle chaîne (ce que ne fait pas ta fonction

asm et qui prend pas mal de temps) donc plus lente ( +-20 % qu'une

fonction C avec un strdup ). Mais pratique car on a directement une nouvelle chaine.

La deuxième se contente de dire où sont les bornes valides de la chaine.

Il n'y a pas d'allocation mais juste qun parcours de chaine. Elle ressemble plus

à la function asm mais en fait un peu moins (ne touche pas la chaîne d'origine).

La première pourrait être codée avec la deuxième (un truc de l'exemple 3)



// exemple 1 : equivaudrait à un C avec strdup / free sans la sécurité du C++

string trim_cpp( const string& str, const char* trim = " " )

{

string::size_type debut = str.find_first_not_of( trim );

if ( debut == string::npos ) return "";

return string( str, debut, str.find_last_not_of( trim ) - debut + 1 );

}



// exemple 2 : se contente de déplacer 2 pointeurs aux bons endroits

pair< string::size_type,string::size_type>

trim_cpp_light( const string& str, const char* trim = " " )

{

return std::make_pair( str.find_first_not_of( trim ), str.find_last_not_of( trim ) );

}



// non testée mais c'est l'idée. Utiliser le 2 pour faire le 1 - facilite les tests.

string trim_cpp( const string& str, const char* trim = " " )

{

pair< string::size_type,string::size_type> tmp = trim_cpp_light( str, trim );

if ( tmp.first == tmp.second ) return "";

return string( s, tmp.first, tmp.second-tmp.first + 1 );

}


Pour ta func asm je ne doute pas que tu l'ai testé mais je ne peux pas m'empêcher

de penser au temps qu'il t'a fallu pour l'écrire, la tester et le temps qu'il faudrait pour quequ'un

d'autre de la comprendre, la vérifier, la faire évoluer etc... (puis elle voudra pas

compiler sous hppa ;), alors qu'un équivalent C le ferait).

Globalement, je ne suis pas assez riche pour programmer en assembleur.

Sans compter que je ne suis même pas sûr qu'un compilo ne donne pas une

version plus rapide du même algo à partir du C (à voir l'asm n'est pas ma

spécialité mais j'ai déjà vu des cas, '-s' est mon ami). Faudrait me dire ce qu'elle

fait exactement pour faire le test sur ce cas.



//Ma participation à la saturation du net:
//http://hylvenir.free.fr
Messages postés
6535
Date d'inscription
lundi 16 décembre 2002
Statut
Modérateur
Dernière intervention
22 août 2010
7
Je sais que ma solution est mauvaise puisqu'a chaque fois il décale
toute la chaine à gauche. Je donnais ca pour dire de remplacer remove
(qui n'existe pas) par erase.
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
Pour le fun... une version C (presque aussi rapide -10% que la version asm mais portable)

doit pouvoir s'optimiser (j'ai pas beaucoup réfléchit surtout testé)



int trim( char* str )

{

char* begin = str;

char* curBegin = str;

for( ;*str && *str == ' '; ++str ); // 1er != ' '



char* curEnd curBegin, *end str;

for( ; *curBegin *end *str; ++curBegin, ++end, ++str )

if ( *str !' ' ) curEnd curBegin; // dernier != ' '



if ( *curEnd ) *++curEnd = '\0';



return curEnd - begin; // taille de la chaine

}
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
for( ;*str && *str == ' '; ++str ); // 1er != ' '
pourrait faire en + simplement écrit:
while(*str == 32) str++;

ciao...
BruNews, MVP VC++
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
oui c'est clair.

j'ai vu ça dans la soirée.



C'est surtout le if final dont j'aimerais bien me

passer mais j'ai pas eu le temps de trouver.

// Ma participation à la saturation du net:
// http://hylvenir.free.fr