C++ doubler les anti slash

Hello

il sagis de double un \ en \ évidemment c’est pas faute d’avoir essayer.
pour les quote j’y suis arriver:

/*
ce code a pour but de doubler une quote, ce code fonctionne, je voudrai faire la meme chose pour les \ mai la évidament sa marche pas 
j'ai bien tenter en doublant les \\ sans succès 
*/
#include <iostream>
#include <string>

int main()
{
        size_t found;
	string str ("/'home/'user4/'Téléchargements/'tmp/'mon fichier");
	string str2 ("'");
	int N = 0;
	while(found!=string::npos){

		if (N==0)
		{
			found=str.find(str2);
			str.replace(found,str2.length(),"''");
			found=str.find("'",found + 2,1);
			N++;
		}
		else
		{

			str.replace(found,str2.length(),"''");
			found=str.find("'",found + 2,1);
		}
	}
	cout << str << endl;
}

si j’essaye avec des \ ou \\ sa par en vrille
Merci d’avance

Tu pourrais préciser ?

La seule chose que je vois n’a strictement rien à voir avec les antislash : quand tu fais tourner l’algo avec n’importe quel caractère qui n’existe pas dans ta chaîne, ça plante car ton algo est buggé :

terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::replace Abandon
C’est un bête problème d’initialisation de ta boucle, que tu as essayé de contourner en doublant le corps de la boucle alors qu’il n’y en a pas besoin en réalité. Je te laisse chercher un peu, tu devrais avoir suffisamment d’indices avec ça pour refaire ton algo. Demande si tu veux la solution.

Étape suivante une fois que ça fonctionnera : la même chose, mais avec une seule allocation mémoire quel que soit le nombre d’occurrences à remplacer. :mrgreen:

[quote=“syam”]
C’est un bête problème d’initialisation de ta boucle, que tu as essayé de contourner en doublant le corps de la boucle alors qu’il n’y en a pas besoin en réalité. Je te laisse chercher un peu, tu devrais avoir suffisamment d’indices avec ça pour refaire ton algo. Demande si tu veux la solution.

Étape suivante une fois que ça fonctionnera : la même chose, mais avec une seule allocation mémoire quel que soit le nombre d’occurrences à remplacer. :mrgreen:[/quote]

Bon finalement j’ai trouver un moyen mai même en modifiant le teste de la boucle, pas moyen de ce passé du if ,donc je donne ma langue aux chat :laughing:

int main()
{

size_t found;
	string str = "/home\\user4/Téléchargements\\tmp\\mon fichier";
	//string str = "/home/user4/Téléchargements/tmp/mon fichier";
	string str2 = "\\";
	int N = 0;
	while((found=str.find(str2,found))!=string::npos){

		if (N==0)
		{
			found=str.find(str2);
			str.replace(found,str2.length(),"\\\\");
			found=str.find("\\",found + 2,1);
			N++;
		}
		else
		{

			str.replace(found,str2.length(),"\\\\");
			found=str.find("\\",found + 2,1);
		}
	}
	cout << str << endl;

}

une idée du mieux que sa pourrait être ?

Rooh je t’ai dit pourtant. :stuck_out_tongue: C’est juste un souci d’initialisation de la boucle. :wink:

[code]#include
#include

using namespace std;

int main()
{
string str = “/home/user4/Téléchargements/tmp/mon fichier”;

// chaînes de recherche / remplacement (const car ça ne changera pas)
// ça évite d’avoir à changer la valeur partout dans le code
const string search_str = “quelque chose”;
const string replace_str = “autre chose”;

// ça c’est juste pour éviter de recalculer les longueurs des chaînes à chaque itération
const size_t search_len = search_str.length();
const size_t replace_len = replace_str.length();

// on cherche la première occurrence
size_t found = str.find(search_str);
// on n’exécute le corps de la boucle que s’il y a quelque chose à remplacer
while (found != string::npos)
{
// on a trouvé une occurrence à remplacer, on effectue le remplacement
str.replace(found, search_len, replace_str);
// on cherche l’éventuelle occurrence suivante
found = str.find(search_str, found + replace_len);
}
cout << str << endl;
return 0;
}[/code]

[quote=“syam”]Rooh je t’ai dit pourtant. :stuck_out_tongue: C’est juste un souci d’initialisation de la boucle. :wink:

[code]#include
#include

using namespace std;

int main()
{
string str = “/home/user4/Téléchargements/tmp/mon fichier”;

// chaînes de recherche / remplacement (const car ça ne changera pas)
// ça évite d’avoir à changer la valeur partout dans le code
const string search_str = “quelque chose”;
const string replace_str = “autre chose”;

// ça c’est juste pour éviter de recalculer les longueurs des chaînes à chaque itération
const size_t search_len = search_str.length();
const size_t replace_len = replace_str.length();

// on cherche la première occurrence
size_t found = str.find(search_str);
// on n’exécute le corps de la boucle que s’il y a quelque chose à remplacer
while (found != string::npos)
{
// on a trouvé une occurrence à remplacer, on effectue le remplacement
str.replace(found, search_len, replace_str);
// on cherche l’éventuelle occurrence suivante
found = str.find(search_str, found + replace_len);
}
cout << str << endl;
return 0;
}[/code][/quote]

l’idée de metre la longueur de la chaine est bonne j’y avais pas penser :023

par contre ton code marche pour les caractère autre que celui la --> \

essaye avec:

string str = "/home/user4/Télécha\\rgemen\\ts/tmp/mon fichier";

  // chaînes de recherche / remplacement (const car ça ne changera pas)
  // ça évite d'avoir à changer la valeur partout dans le code
  const string search_str = "//";
  const string replace_str = "////";

  // ça c'est juste pour éviter de recalculer les longueurs des chaînes à chaque itération
  const size_t search_len = search_str.length();
  const size_t replace_len = replace_str.length();

  // on cherche la première occurrence
  size_t found = str.find(search_str);
  // on n'exécute le corps de la boucle que s'il y a quelque chose à remplacer
  while (found != string::npos)
  {
    // on a trouvé une occurrence à remplacer, on effectue le remplacement
    str.replace(found, search_len, replace_str);
    // on cherche l'éventuelle occurrence suivante
    found = str.find(search_str, found + replace_len);
  }
  cout << str << endl;

Pourquoi veux-tu qu’il te remplace la séquence // dans ta chaîne alors qu’elle n’est pas présente ? :mrgreen:
Essaye avec juste / tu verras que ça marche très bien (pas besoin de le doubler comme un antislash, y’a rien à échapper là…). :wink:

Personnellement quand j’ai initialisation - test de sortie - mise à jour de l’initialisation, j’utilise systématiquement un for.
J’ai eu un peu de temps libre cet après midi du coup je l’ai fait comme ça :

void duplique(const char car, std::string & chaine)
{
   using namespace std;

   for(size_t found = chaine.find(car, 0); string::npos != found; found = chaine.find(car, found + 2)){
      chaine.insert(found, 1, car);
   }
}

Mais mon code ne répond qu’au doublement d’un caractère.

Ensuite pour éviter d’avoir plus d’une ré-allocation :

[code]void duplique(const char car, std::string & chaine)
{
using namespace std;

size_t count = 0;
for(size_t found = chaine.find(car, 0); string::npos != found; found = chaine.find(car, found + 2)){
count++;
}

chaine.resize(chaine.size() + count);

for(size_t found = chaine.find(car, 0); string::npos != found; found = chaine.find(car, found + 2)){
chaine.insert(found, 1, car);
}
}[/code]
La l’évitement de la ré-allocation engendre un surcoût (on passe de O(N) à O(2N), mais ça ne change pas la complexité de l’algorithme (il reste en O(N). On pourrait faire mumuse et se contenter d’un std:string::reserve() de la 1.5 fois la taille de la chaîne ce qu’on peut penser être une bonne médiane entre éviter le déplacement de la chaîne en mémoire, mais ça n’a pas d’intérêt et la fiabilité est fortement dépendante du code.

Remarque : Stocker la taille des std::string c’est de la microoptimisation, si je me souviens bien ça permet juste d’éviter un appel de méthode car std::string stocke elle même la taille de la chaîne et la place réservée.

Du coup si j’avais à faire un remplacement, l’adaptation est triviale on remplace insert par replace :

[code]void replace(std::string & chaine, const std::string motif, const std::string dest)
{
using namespace std;

size_t count = 0;
for(size_t found = chaine.find(motif, 0); string::npos != found; found = chaine.find(motif, found + dest.size())){
count++;
}

chaine.resize(chaine.size() + count * motif.size());

for(size_t found = chaine.find(motif, 0); string::npos != found; found = chaine.find(motif, found + dest.size())){
chaine.replace(found, motif.size(), dest);
}
}[/code]

Il n’y a aucune garantie que la taille de la chaîne soit stockée, c’est dépendant de l’implémentation STL que tu utilises.
Héritage : string (21.2) -> basic_string (21.3) -> Sequence (23.1.1) -> Container (23.1)
Dans tout ça, le seul endroit où il est fait référence à size() (dont length() n’est qu’un alias) c’est dans la spécification des Containers :

[quote=“C++ ISO/IEC 14882:2003”]23.1 table 65expression return_type operational semantics complexity ... a.size() size_type a.end()-a.begin() (Note A) ...
Those entries marked ‘‘(Note A)’’ should have constant complexity. [et non pas must][/quote]
Et en l’absence de garantie, hein… :016

Mauvaise implémentation, changer d’implémentation :005

Plus franchement, je n’ai aucune idée de la thread-safe-itude de std::string qui pourrait ralentir l’appel à string::size.

Bon ben je vai dormir moins C… :laughing:
Merci pour vos réponse :023
le problème de ‘’ et \ viend de postgresql qui ne supporte pas ce type de donnée.

mai sa ce complique encore parce que il va faloir que je place [quote]E’mavaleur’[/quote] avec en plus [quote]E’le c++ est d’or’[/quote]
c’est compliquer juste pour insérer des donnée pff :confusion-confused:
Mai je comprend pas pourquoi il ne ce sont pas baser sur la longueur de la string…

Je n’ai pas compris ton problème. :question:

Si je lis correctement entre les lignes, tu fais du remplacement de chaîne dans une requête SQL, et en plus tu essayes de gérer manuellement l’encodage de la chaîne pour qu’il soit compatible avec PostgreSQL, c’est ça ?

Bon je connais pas l’API C/C++ de PostgreSQL, mais toutes les bases de données un tant soit peu fonctionnelles ont une API pour remplacer les paramètres dans la requête sans avoir à faire ça soi-même, et sans avoir à s’occuper de l’encodage / échappement. Quelque chose du genre :

requete = db.Query("SELECT * FROM table WHERE champ1=%1 AND champ2!=%2"); requete.Param(1).AsString("valeur1"); requete.Param(2).AsInt32(372); if (requete.Execute()) ...
Je ne doute pas qu’en cherchant un peu dans la doc, tu trouveras une fonctionnalité équivalente pour PostgreSQL. Même SQLite a ça !

Si seulement c’était aussi simple… Je vais pas détailler le pourquoi du comment (ça risquerait de raviver mes envies de meurtre*) mais le fait est qu’on se coltine 4 compilos / environnements différents pour un même produit, selon l’époque à laquelle a été initialement écrit tel ou tel exécutable. Dont une monstruosité 16 bits qui date des années 90, à l’époque de Windows 3.1 (et après on se demande pourquoi je hais** Windows…).

(*) Très lent, le meurtre. D’aucuns appelleraient ça de la torture sadique, si je pouvais m’y adonner (et si je retrouvais le(s) coupable(s)).
(**) Le mot est très faible.

Forcément dans ces conditions, t’imagines bien que quand j’entends « changer d’implémentation » ça a tendance à me faire bondir. :wink:

[quote=“syam”]Si je lis correctement entre les lignes, tu fais du remplacement de chaîne dans une requête SQL, et en plus tu essayes de gérer manuellement l’encodage de la chaîne pour qu’il soit compatible avec PostgreSQL, c’est ça ?
[/quote]
oui

[code]
Bon je connais pas l’API C/C++ de PostgreSQL, mais toutes les bases de données un tant soit peu fonctionnelles ont une API pour remplacer les paramètres dans la requête sans avoir à faire ça soi-même, et sans avoir à s’occuper de l’encodage / échappement. Quelque chose du genre :

requete = db.Query("SELECT * FROM table WHERE champ1=%1 AND champ2!=%2"); requete.Param(1).AsString("valeur1"); requete.Param(2).AsInt32(372); if (requete.Execute()) ...

j’ai fouiner dans la doc , mai j’ai rien trouver.
pqxx.org/devprojects/libpqxx/doc … Reference/

je vai voir si j’arrive a résoudre le souci dans la journée :stuck_out_tongue:

alors pour les simple quote il y a *.esc(mavaleur) ,ce qui fait que le souci est resolu. pour les \ il faut modifier la configuration ou s’assurer que

standard_conforming_strings = ON

a partir de la le \ deviens un caractère comme les autres. Mai bon la fonction reste utile car il faut que l’utilisateur puisse saisir cette valeur :think:

En cherchant un peu, j’ai trouvé ça : sqlapi.com/ Ça permet de faire des requêtes paramétriques.

@syam > Je n’ai pas le courage de regarder plus en détail, mais il ne serait pas possible de dériver std::string ?

[quote=“panthere”]j’ai fouiner dans la doc , mai j’ai rien trouver.
pqxx.org/devprojects/libpqxx/doc … Reference/[/quote]
pqxx.org/devprojects/libpqxx/doc … 00193.html

On est deux alors, je n’ai absolument aucun courage pour quoi que ce soit aujourd’hui. :mrgreen:

On est deux alors, je n’ai absolument aucun courage pour quoi que ce soit aujourd’hui. :mrgreen:[/quote]
Moi j’ai une bonne raison, je suis en bépo sur un clavier typematrix :wink:

Et sinon, en utilisant directement le code ASCII (qui est le même en UTF) -> 0x5C?

ou ‘\x5C’ en C