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++Builder Discussion :

perdre une partie de donnee avec la conversion


Sujet :

C++Builder

  1. #1
    Débutant
    Inscrit en
    Février 2010
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Février 2010
    Messages : 105
    Points : 20
    Points
    20
    Par défaut perdre une partie de donnee avec la conversion
    bjour , j'ai converti une variable string en char*
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    arr=Table1->FieldByName("Nomm")->AsString.c_str() ;
    puis j'ai converti arr en String pour afficher :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AnsiString txt = VarToStr(arr);
    alors quand j'ai afficher :
    il m'afficher une partie de la variable initiale de champ nomm de la table 1
    exp : 17.10.1.22 => 17.10.1
    je cherche pourquoi ????
    merci d'avance
    Je réponds à toutes vos questions claires et bien expliquées, si je sais bien sûr.Merci d'avoir pris quelques minutes pour faire bien.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Moi je ferais comme ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      char *arr;  // pour mémoire
      strcpy(arr,Table1->FieldByName("Nomm")->AsString.c_str() );
      AnsiString txt = AnsiString(arr);
      ShowMessage(txt);
    Je crois que la raison est le nombre de caractères alloués par défaut à un char*, mais sans garantie.
    De toute façon arr est un pointeur. Si vous écrivez arr=un autre pointeur, ce que renvoie c_str(), vous écrivez qu'un pointeur est égal à un autre, mais pas du tout une copie de chaine. Il est bien probable que cette ligne qui donne un résultat donne dans le cas général une énorme erreur.
    Essayez par exemple printf("%s\n",arr); je suis sûr que ça plante.
    Le AnsiString met une fin de chaine (sans vous demander votre avis), donc ça plante pas, mais c'est faux.

  3. #3
    Responsable Magazine

    Avatar de pottiez
    Homme Profil pro
    Développeur C++
    Inscrit en
    Novembre 2005
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur C++
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2005
    Messages : 7 152
    Points : 22 087
    Points
    22 087
    Par défaut
    Salut,
    j'ai une question qui est peut être con, mais la propriété AsString renvoie un AnsiString, alors pourquoi le convertir en char* pour le reconvertir en AnsiString juste après ? N'est-ce pas se compliquer la tache pour rien ?
    Quand une réponse vous a été utile, pensez à utiliser le nouveau système de notation

    Lisez le magazine de developpez.com.
    Mes tutos : http://pottiez.developpez.com

    La FAQ BCB -> 642 Questions/Réponses, si vous voulez participer, contactez moi. Aide de BCB6 en français

    N'oubliez pas que l'aide existe et est affichée sous simple pression de la touche F1 , une touche c'est plus rapide que tout un message .

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Personnellement, je comprend la démarche de Menoran, il cherche à comprendre et fait des essais.
    Il a constaté une réaction qui génère une erreur, il décompose le bout de code jusqu'au plus petit détail.

  5. #5
    Responsable Magazine

    Avatar de pottiez
    Homme Profil pro
    Développeur C++
    Inscrit en
    Novembre 2005
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur C++
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2005
    Messages : 7 152
    Points : 22 087
    Points
    22 087
    Par défaut
    Effectivement vu comme cela, ca peut se comprendre

    Mais pourquoi passer par des fonctions C alors que tu fait du C++, as-tu besoin absolument d'un char* ? Est-ce que le std::string de la stl ne peut pas convenir ?
    Quand une réponse vous a été utile, pensez à utiliser le nouveau système de notation

    Lisez le magazine de developpez.com.
    Mes tutos : http://pottiez.developpez.com

    La FAQ BCB -> 642 Questions/Réponses, si vous voulez participer, contactez moi. Aide de BCB6 en français

    N'oubliez pas que l'aide existe et est affichée sous simple pression de la touche F1 , une touche c'est plus rapide que tout un message .

  6. #6
    Invité
    Invité(e)
    Par défaut
    re-bonjour,
    Menoran programme en C++Builder.
    Dans cet environnement, les bibliothèques std:: ne sont pas utilisées par le programmeur.
    Par contre, Borland ne semble pas avoir cru bon de rayer d'un coup de crayon les fonctions de base telles que strcpy, strcat, printf et Cie etc.
    C'est assez inattendu comme expression "passez par des fonctions C alors que tu fais du C++". Moi je vous poserais la question "pourquoi utiliser la sur-couche du C++ alors que pour telle opération les fonctions du C conviennent parfaitement?"

    Il y a eu 2 discussions dernièrement pourtant sur ce type de sujet.
    Cordialement.

  7. #7
    Responsable Magazine

    Avatar de pottiez
    Homme Profil pro
    Développeur C++
    Inscrit en
    Novembre 2005
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur C++
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2005
    Messages : 7 152
    Points : 22 087
    Points
    22 087
    Par défaut
    Je trouve bizarre que tu me dises que Borland a implémenté les fonctions C et que c'est donc pour les utiliser et que tu me dise en même temps que la stl ne doit pas être utilisée dans Borland Borland a implémenté dans son compilateur la stl, je ne vois pas pourquoi ne pas l'utiliser, surtout que c'est bien pratique et beaucoup plus facile à utiliser.
    Je n'utilise pas les fonctions C car cela est sources de bug, j'ai déjà rencontré des codes ou l'on alloué la mémoire avec des méthodes C et ou on dés alloué avec un delete de C++, or la gestion mémoire n'est pas la même d'un côté et de l'autre et fatalement cela planté toute l'application , voila pourquoi je fait du C++ et non du C
    Quand une réponse vous a été utile, pensez à utiliser le nouveau système de notation

    Lisez le magazine de developpez.com.
    Mes tutos : http://pottiez.developpez.com

    La FAQ BCB -> 642 Questions/Réponses, si vous voulez participer, contactez moi. Aide de BCB6 en français

    N'oubliez pas que l'aide existe et est affichée sous simple pression de la touche F1 , une touche c'est plus rapide que tout un message .

  8. #8
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    Les données du tableau qui est renvoyé par c_str() sont temporaires.
    Le traitement doit être immédiat !!!
    Donc ne jamais se servir d'un pointeur tiers pour y mémoriser l'adresse renvoyée par c_str().

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    AnsiString Filename = "Blabla";
    FILE *File = fopen(Filename.c_str(), // << usage immédiat 
                       ...);
    Et non pas (même si parfois ça peut fonctionner) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    AnsiString Filename = "Blabla";
    char *f = Filename.c_str(); // << usage immédiat ... mais stérile !
    // ... 
    // ...
    Plus le traitement sera différé et plus le risque d'altération sera grand !

    A plus !

  9. #9
    Invité
    Invité(e)
    Par défaut
    Bonjour Henderson,
    Le tableau renvoyé par c_str() est un char*.
    Ce tableau sera temporaire si le tableau du type char* est temporaire.
    C'est à dire que la durée de vie de ce tableau n'a rien à voir avec le fait qu'il a été créé par un c_str().
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      AnsiString Filename = "Blabla";
      char *f = Filename.c_str(); // << usage immédiat ... mais stérile !
      // ...
    N'est pas bon ( mais pas faux), il faut écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
      AnsiString Filename = "Blabla";
      char *f; 
      strcpy(f, Filename.c_str()); // mais attention à la dimension
                                           // le zéro terminal est présent
    // voir aussi la fonction data() qui renvoie NULL si FileName est vide.
      // ...
    Si on a écrit ces deux ou trois lignes, c'est parce qu'on a envie de travailler sur f en tant que chaine, et sans toucher à FileName.

  10. #10
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    C'est à dire que la durée de vie de ce tableau n'a rien à voir avec le fait qu'il a été créé par un c_str().
    Justement si !
    Il n'est pas créé (au sens conventionnel du terme) mais juste renvoyé sous forme d'adresse !
    Il peut se situer n'importe où en mémoire mais pas sous forme d'objet tel qu'on peut l'imaginer (comme avec new par exemple).
    Et ce qui compte n'est pas l'objet "tableau" en soi mais son adresse pour exploiter la donnée "chaîne" immédiatement.
    Si l'objet était persistant on aurait pas besoin de le copier (avec strcpy par exemple).

    A plus !

  11. #11
    Invité
    Invité(e)
    Par défaut
    Il y peut-être un problème de compréhension
    dans le code suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      char UnTexte[32];
      strcpy(UnTexte,"C'est un texte");
      char *txt="abc";
    Les variables UnTexte et txt sont locales au bloc, c'est à dire que leur durée de vie est limité à la fin de ce bloc.
    dans le code suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      AnsiString ut="C'est un texte";
      char UnTexte[32];
      strcpy(UnTexte,ut.c_str());
      AnsiString t=AnsiString("abc");
      char *txt=t.c_str();
    Donc ma question UnTexte et txt ont-elle une durée de vie différente de la première description ? Je répondrai NON.
    Je peux faire un exemple, mais pour prouver le contraire, il faudrait un exemple contraire

  12. #12
    Membre confirmé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Points : 523
    Points
    523
    Par défaut
    Bonsoir,

    La réponse est dans la FAQ C++Builder.

    La durée de vie de la variable est limitée à l'instruction en cours.

    Quant à passer aux fonctions C juste pour faire des lignes de plus, je n'en vois pas l'intérêt puisque tout ce qu'il y a après le "=" manipule des objets.

    Voici une réponse courte qui devrait fonctionner parfaitement dans tous les cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AnsiString txt = Table1->FieldByName("Nomm")->AsString;

  13. #13
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    Notons au passage que c_str() pourrait très bien, dans certains cas, ne pas passer par l'usage d'un buffer (ce fameux tableau).
    En effet, comment expliquer l'utilité de copier le contenu de l'AnsiString dans un tableau (c_str()) pour ensuite copier le contenu de ce tableau dans le tableau de destination (strcpy) !
    Autant faire la copie du contenu directement (AnsiString[] -> Destination[]) ! Non ?
    A mon avis, c'est ce que donnerait une optimisation du code (pour une exécution plus rapide) !

    A plus !

  14. #14
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    J'ai l'impression qu'il y a une certaine incompréhension quant à l'utilisation d'AnsiString, c_str() et les chaines.
    @gandf La réponse à quelle question? est dans le FAQ. Toutes les explications oui.
    @henderson, la fonction c_str() a été fait pour utiliser le contenu d'un AnsiString comme chaine de caractère. Ce serait presque équivalent à un transtypage. Mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      AnsiString msg="Un texte";
      char *T= (char*)msg;  // ne marche pas
    // il faut écrire
      char *T=msg.c_str();
    // ou mieux
      char *T;
      strcpy(T,msg); 
    // encore mieux
      char T[128]; // on est sur que le texte sera de longueur inférieure à 128
      strcpy(T,msg.c_str);
    // etc. d'autres écritures possibles avec malloc et new
    Mais, je ne vais pas refaire le FAQ cité par gandf

  15. #15
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    Ce serait presque équivalent à un transtypage
    En fait non puisqu'il y a une différence entre une chaîne qui hérite du PASCAL, il me semble, ( T[0] = length) et les chaînes à 0 terminal ( T[length] = NUL ).

    Il faut éviter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char *T = A.c_str(); // << opération complètement stérile !!!
    // << à partir de là ... le contenu du tableau pointé par T n'est plus garanti
    Par contre est possible :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    AnsiString A = "Hello !";
    char *T = &A[1]; // pointe sur 'H' mais pas de NUL au bout !!!
    Donc on sait faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    AnsiString A = "Hello !";
    char Tableau[256];
     
    //...
     
    int j;
    char *S = &A[1];
    char *D = &Tableau[0]; 
    for(j=0; j <= A.Length(); j++) D[j] = S[j];
    // NUL terminal
    D[j]=0;
    On peut faire également :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int j;
    char *D = &Tableau[0];
    D = D--; // pour éviter de surtraiter l'index dans la boucle
    for(j=1; j <= A.Length(); j++) D[j] = A[j];
    // NUL terminal
    D[j]=0;
    En arrière plan la méthode c_str() apparaît comme un ensemble d'opérations inutiles lorsqu'elle est utilisée avec strcpy !!!
    Autant copier directement plutôt que laisser le compilateur passer par un buffer (tel que c'est annoncé) !

    Par contre, c'est forcément efficace avec fopen (etc ...) !

    A plus !

  16. #16
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Ci dessous un extrait du FAQ C++Builder
    Pour résoudre ce problème, il faut utiliser la fonction strcpy :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    AnsiString Src = "Source.txt";
    AnsiString Dest = "Destination.txt";
    char * pSrc = new char[Src.Length()+1]; // +1 pour le 0 terminal
    char * pDest = new char[Dest.Length()+1];
    strcpy(pSrc,Src.c_str());
    strcpy(pDest,Dest.c_str());
    // instructions
    CopyFile(pSrc,pDest,true);
    delete[] pSrc;
    delete[] pDest;
    La fonction c_str() a été faite pour traiter une chaine comme un tableau, tel que prévu en C.
    Un bout de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
      AnsiString A = "Hello !";
      char *T = A.c_str(); 
      A="Bonjour";
      fprintf(espion,"A= %s  T=%s\n",A,T); //A= Bonjour  T=Hell
      A="Au revoir";
      strcpy(T,A.c_str());
      fprintf(espion,"A= %s  T=%s\n",A,T); //A= Au revoir  T=Au revoir
    Explication, dans le premier cas on a attribué à T le pointeur renvoyé par c_str(), puis on a modifié l'AnsiString. Si on imprime T on obtient "Hell", c'est à dire le résultat de c_str, limité à 4 caractère, ensuite c'est n'importe quoi, donc faux.
    On modifie A et on copie A.c_str() dans le tableau pointé par T. A l'impression, on a bien A = T ="Au revoir".
    CQFD

  17. #17
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Salut a tous
    Je ne pense pas qu'il soit necessaire de polemiquer sur les Char* et autres AnsiString de toute facon le C++ est une extension du C, de plus menoran ne donne aucune reponse, son code est minimaliste on ne sait pas comment sont declare les champs de sa base comment sont declarees ses variables, commenty il ecrit dans ses champs, ni s'il a verifie le contenu des champs, son code ne sort peut etre que ce qu'il a entre dans le champ "Nomm"
    --
    Plutot que d'essayer de réinventer la roue, apprenons à nous en servir

  18. #18
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2005
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 401
    Points : 578
    Points
    578
    Par défaut
    Hello,

    D'accord avec Blondelle pour l'inutilité de la polémique...
    Mais quand même, en regardant les bouts de code qui sont passés sur ce thread, et les "démonstrations" présentées, j'ai peur...

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      AnsiString msg="Un texte";
      char *T= (char*)msg;  // ne marche pas
    // il faut écrire
      char *T=msg.c_str();
    // ou mieux
      char *T;
      strcpy(T,msg); 
    // encore mieux
      char T[128]; // on est sur que le texte sera de longueur inférieure à 128
      strcpy(T,msg.c_str);
    // etc. d'autres écritures possibles avec malloc et new
    Concernant la partie en rouge: Comment peut-on dire "ou mieux" quand on fait un strcpy sur une zone paumée dans le néant ???

    Autre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      AnsiString A = "Hello !";
      char *T = A.c_str(); 
      A="Bonjour";
      fprintf(espion,"A= %s  T=%s\n",A,T); //A= Bonjour  T=Hell
      A="Au revoir";
      strcpy(T,A.c_str());
      fprintf(espion,"A= %s  T=%s\n",A,T); //A= Au revoir  T=Au revoir
    Le dernier fprintf a l'air de marcher, super, bravo....
    Mais quand j'exécute ce bout de code sous BCB 2010, avec Codeguard activé, j'ai le droit à un joli rapport d'erreur de Codeguard sur la ligne en rouge ("Accès à la mémoire libérée en cours de traitement"). Et pour cause !!! Le pointeur renvoyé par AnsiString::c_str n'est valide que pendant la durée de vie de la chaîne stockée dans l'AnsiString.... Si l'AnsiString change, la zone mémoire qui contenait l'ancienne valeur peut être libérée. (Elle n'est pas forcément libérée tout de suite, because AnsiString gère un compteur de références... Faire AnsiString B = A; ne fait qu'incrémenter un compteur. A méditer...).

    Moralité: faisez gaffe au c_str(). Même quand on croit l'avoir compris, on peut encore se prendre les pieds dedans.

  19. #19
    Débutant
    Inscrit en
    Février 2010
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Février 2010
    Messages : 105
    Points : 20
    Points
    20
    Par défaut
    merci pour la reponse ,
    est que vous connaisser ADO,
    car je veux executer des commandes. merci d'avance
    Je réponds à toutes vos questions claires et bien expliquées, si je sais bien sûr.Merci d'avoir pris quelques minutes pour faire bien.

  20. #20
    Membre confirmé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Points : 523
    Points
    523
    Par défaut
    Il faut créer une nouvelle discussion. C'est plus simple pour ceux qui font des recherches et les personnes qui pourront te répondre trouveront ta question plus facilement.

Discussions similaires

  1. Comment extraire une partie d'URL avec REGEX?
    Par STB_Fk dans le forum Langage
    Réponses: 2
    Dernier message: 24/01/2007, 12h59
  2. Supression d'une base de données avec checkbox
    Par sirine dans le forum Dreamweaver
    Réponses: 1
    Dernier message: 02/12/2006, 09h28
  3. [MFC]Ouverture d'une base de donnee avec DAO
    Par Wyatt dans le forum MFC
    Réponses: 7
    Dernier message: 24/01/2005, 10h06
  4. Exporter seulement une partie des données avec pg_dump ?
    Par Philhz dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 31/07/2004, 09h50
  5. [VB6] [ODBC] Référencer une base de données avec vb
    Par af.balog dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 13/09/2002, 09h51

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