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

 C++ Discussion :

convertir char* en référence sur string


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Espagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 145
    Par défaut convertir char* en référence sur string
    Bonjour. Je cherche à convertir un char* en référence sur un string. En gros faire quelque chose comme ça...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char* c = "church";
    string &s = c;
    Mais le compilateur veux pas. Existe-t-il un autre moyen?

    Le but de l'opération est le suivant:
    • je reçois une base de données sous la forme d'un char*
    • une entrée correspond à une clé de 16 charactères plus 32 charactères de données.
    • du coup la base est un char* vers des entrées de 48 chars qui se suivent


    J'ai un algo qui trie ma base sur la clé. Sauf que j'ai écrit l'algo avec des clés qui sont des string...
    Du coup, je veux crée des string à partir des clé... Pour être plus précis, je veux des références vers des string.
    La base va contenir un million d'entrée du coup, je veux pas tout recopié... Existe-t-il une solution pour mon problème?

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Là, tu essaye en fait de créer une référence sur une std::sting qui devrait faire référence à un pointeur sur char...

    Or, une référence doit faire référence à un objet (du type adéquat) existant, et un char* n'est pas un std::string

    Par contre, tu peux créer une std::string (non référence ) au départ d'un char*, soit en utilisant l'une des surcharges du constructeur, soit en utilisant l'opérateur = :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char * c="coucou";
    std::string ok1(c);
    std::string ok2=c;
    A partir de là, rien ne t'empêche de créer une référence sur ta std::string, si tu le souhaites:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    std::string & ref1 =ok1;
    std::string & ref2 =ok2;
    Ceci dit: lorsqu'il s'agit de déclarer une variable en vue de l'utiliser dans la fonction, il ne sert pas à grand chose d'en créer une référence par la suite, pour la simple raison que l'on risque d'appliquer des modifications à la référence sans se rendre compte que l'on modifie en réalité la chaine originale (ou inversément), et que, la distraction aidant, on peut facilement en arriver à se demander pourquoi l'une a été modifiée alors que l'on modifiait l'autre

    Il est généralement "de bon ton" de réserver l'usage des références (constantes ou non) au passage d'arguments, à quelques exceptions près
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Espagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 145
    Par défaut Problème
    Hmmm. Merci pour la réponse mais je crois pas que ça ne résoud pas mon problème. Le truc c'est que je vais recevoir un char* pointant sur plus de 48 000 000 de chars... Ca fait dans les 90mega...

    Je dois trier tout ça. Grosso modo, la chaine comporte des entrées les unes à la suite de l'autre, les 16 premiers chars sont une clé pour le tri, les 32 une adresse web...

    Mais j'ai écrit mon algo pour traiter les clés comme stockées dans un
    objet: std::vector <string> &s...
    Du coup, j'ai pensé utiliser mon vector pour contenir des références vers les strings qui sont contenu dans 1 grand char... j'espere que tu me suis...

    Est-ce que c'est possible?
    Mon autre alternative est de modifié mon algo pour trier sur des char* au lieu de string mais bon....

  4. #4
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Bonjour,


    Si et seulement si tes clés sont immutables (pas de modification sur les clés) alors il existe une solution très pratique qui consiste à créer une classe représentant un wrapper extrêmement léger sur une chaine en mémoire (un char* + une taille) mais qui propose l'interface familière de std::string

    Sauf qu'il n'y a pas besoin de le coder soit-même, vu que des gros projets C++ open-source l'ont déjà fait (mais bizarrement pas boost. Pourtant ce genre de classe extrêmement utile me semble pile-poil dans le scope de boost mais bon...)

    Par exemple :

    StringPiece du projet google Chrome :
    http://code.google.com/p/re2/source/.../stringpiece.h

    ou StringRef du projet LLVM :
    http://llvm.org/svn/llvm-project/llv...DT/StringRef.h
    http://llvm.org/svn/llvm-project/llv.../StringRef.cpp

    Très pratique car :
    - License BSD
    - Pas de dépendance (pour StringRef il faut quand même virer deux trois fonctions qui induisent des dépendances vers d'autres parties de LLVM)

    Donc si tout se passe bien, dans ton cas, il devrait suffire de rajouter un constructeur StringPiece(char*, size_t) pour limiter aux 16 premiers char de la clé, puis dans ton algo de tri faire un chercher/remplacer de std::string par StringPiece/StringRef, et ça devrait suffire.

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par Arzar Voir le message
    puis dans ton algo de tri faire un chercher/remplacer de std::string par StringPiece/StringRef, et ça devrait suffire.
    Voire de templatiser l'algorithme de tri pour qu'il marche avec des std::string, des StringPiece, des StringRef...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  6. #6
    Membre éclairé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Voire de templatiser l'algorithme de tri pour qu'il marche avec des std::string, des StringPiece, des StringRef...
    Voire même aller jusqu'à prendre une paire d'itérateurs en paramètres (pour pouvoir prendre char *, std::string, des StringPiece, des StringRef ... ).


    Mais l'intérêt de ces classes (StringPiece, StringRef) semble justement être d'encapsuler cette paire d'itérateurs (en conservant la taille en plutôt qu'un iterateur "past to end") pour une utilisation plus intuitive.

    Toutes ces solutions supposent néanmoins d'avoir accès à la taille / fin de la chaîne. Si tu ne la possèdes pas, cela peut aussi avoir un coup de la calculer.

  7. #7
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Espagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 145
    Par défaut merci
    Citation Envoyé par Arzar Voir le message
    Bonjour,


    Si et seulement si tes clés sont immutables (pas de modification sur les clés) alors il existe une solution très pratique qui consiste à créer une classe représentant un wrapper extrêmement léger sur une chaine en mémoire (un char* + une taille) mais qui propose l'interface familière de std::string

    Sauf qu'il n'y a pas besoin de le coder soit-même, vu que des gros projets C++ open-source l'ont déjà fait (mais bizarrement pas boost. Pourtant ce genre de classe extrêmement utile me semble pile-poil dans le scope de boost mais bon...)

    Par exemple :

    StringPiece du projet google Chrome :
    http://code.google.com/p/re2/source/.../stringpiece.h

    ou StringRef du projet LLVM :
    http://llvm.org/svn/llvm-project/llv...DT/StringRef.h
    http://llvm.org/svn/llvm-project/llv.../StringRef.cpp

    Très pratique car :
    - License BSD
    - Pas de dépendance (pour StringRef il faut quand même virer deux trois fonctions qui induisent des dépendances vers d'autres parties de LLVM)

    Donc si tout se passe bien, dans ton cas, il devrait suffire de rajouter un constructeur StringPiece(char*, size_t) pour limiter aux 16 premiers char de la clé, puis dans ton algo de tri faire un chercher/remplacer de std::string par StringPiece/StringRef, et ça devrait suffire.
    Merci, je jette un coup d'oeil à tout ça et je vous tiens rapidement au courant. Par contre, je sais pas trop si je vais pouvoir me servir, mon prof est assez chiant là dessus et il voulait qu'on utilise uniquement les librairies "classiques"... Le problème c'est qu'à la base, le devoir était prévu pour du C mais il a autorisé à ce qu'on utilise C++. Du coup, j'ai écrit mon algo en utilisant des strings... bref, je vais voir tout ça et au pire des cas, ben je changerai mes strings en char*...

  8. #8
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Espagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 145
    Par défaut question
    Dans tous les cas, si j'utilise un wrapper, je vais quand même créer des objets en plus? Si je manipule les char* directement je prends moins de place non? Bien sur c'est plus galère à gérer que les string mais bon...

    Mon objectif avec les références c'était de ne rien créer en plus....

  9. #9
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Citation Envoyé par Arzar Voir le message
    (mais bizarrement pas boost. Pourtant ce genre de classe extrêmement utile me semble pile-poil dans le scope de boost mais bon...)
    Si, si, ça existe, ce sont les iterator_range qui font bien plus que les strings. Aucun intérêt d'avoir plus que ces bêtes-là

    il rajoute la chaine situé après la clé, si c'est la première clé, il rajoutera toute la database et non pas les 48 premiers char....
    strncat ?

  10. #10
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Espagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 145
    Par défaut presque résolu
    Citation Envoyé par Matthieu Brucher Voir le message
    strncat ?
    Nikel. Voila ce que j'ai fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    char* temp_db = (char*)malloc(sizeof(database));
    *temp_db = '\0'; //initialiser à chaine vide, si je fais pas ça, la chaine contient des trucs bizarre avant
    cout << "length: " << strlen(temp_db) << endl;
    cout << "size of keys: " << keys.size() << endl;
    for(std::vector<char*>::iterator pKey = keys.begin(); pKey != keys.end(); ++pKey)
    {
    	strncat(temp_db, *pKey, 48);
    }
    database = strdup(temp_db);
    cout << "after sort: " << endl << temp_db << endl;
    cout << "size of temp_db" << strlen(temp_db) << endl;
    free(temp_db);
    J'execute en pas à pas sous VS et je vois que ça m'a mit les entrées dans l'ordre voulu. Par contre, quand j'arrive à la fin de la fonction, VS me lance une belle erreur:

    Windows a déclenché un point d'arret dans abc.exe.
    Cela peut etre due à une défaillance du tas qui indique un bogue dans abc.exe ou l'une des DLL chargées.
    Cela peut également être du à l'appui sur F12...

    Bref, un truc qui me dit pas grand chose sur d'où vient l'erreur...
    Si j'execute sans débogage (Ctrl+F5 sous VS), j'ai une autre erreur(en anglais cette fois):
    HEAP CORRUPTION DETECTED: after Normal block (#356) at 0x002B78B8.
    CRT detected that application wrote to memory after end of heap buffer.

    Bon du coup, je me doute que j'ai un problème avec la mémoire... Le truc c'est que je sais pas lequel...
    La fonction strncat écrit les charactères voulus, plus '\0' (selon la doc)... Du coup, est-ce que c'est pas lié à ça? C'est bizarre parce que juste avant de faire le free j'arrive à imprimer database avec un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    cout << database << endl;

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/12/2010, 17h27
  2. Convertir char ou String en Int
    Par Invité(e) dans le forum ASP
    Réponses: 2
    Dernier message: 10/06/2008, 16h17
  3. Réponses: 6
    Dernier message: 25/07/2007, 14h31
  4. Convertir Char* en String
    Par Blunt dans le forum C++/CLI
    Réponses: 1
    Dernier message: 01/07/2007, 16h46
  5. Convertir char* en string
    Par KorTeX22 dans le forum C++
    Réponses: 5
    Dernier message: 13/03/2007, 11h54

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