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

Visual C++ Discussion :

Copier et découper un WCHAR


Sujet :

Visual C++

  1. #1
    Membre confirmé
    Inscrit en
    Juin 2005
    Messages
    110
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 110
    Par défaut Copier et découper un WCHAR
    Bonjour à tous,

    C'est sûrement une erreur de débutant, mais je coince sur un truc: j'essaie de copier un WCHAR dans une autre avec wcscpy et de le découper avec substr. C'est pour la méthode IsVolumeSupported (VSS SDK) qui revoie un BOOL pour savoir si un volume supporte les shadow copy ou pas. ça donne à peu près ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    void SaveAfile(WCHAR SourceFile[], WCHAR DestFile[])
    {
           .......
            VSS_PWSZ pSourceVolumeName;
    	WCHAR tempstr;
    	wcscpy(tempstr, SourceFile);
    	pSourceVolumeName = tempstr.substr(1, 3);
           pBackupComponent->IsVolumeSupported(
                                  GUID_NULL, 
                                  pSourceVolumeName, 
                                  &pIsShadowCopySupported
                                                                   );
           .......
    }
    et je me retrouve avec deux erreurs:
    error C2664: 'wcscpy'*: impossible de convertir le paramètre 1 de 'WCHAR' en 'wchar_t *'
    et le deuxième:
    error C2228: la partie gauche de '.substr' doit avoir un class/struct/union
    1> le type est 'WCHAR'
    Pour la première, je suis un peu coincé car il semble que VSS_PWSZ soit un WCHAR, et pas un wchar_t, et pour la deuxième, substr ne fonctionne pas sur un WCHAR, mais sur un char.

    Si quelqu'un à une suggestion, merci par avance...

  2. #2
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    Tu essayes de copier un tableau de WCHARs dans un seul WCHAR.
    Il faut que tu déclares tempstr en tant que tableau ou pointeur (je préfère le premier ).

  3. #3
    Membre confirmé
    Inscrit en
    Juin 2005
    Messages
    110
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 110
    Par défaut
    Bonjour Spout,

    Merci de ta réponse.

    J'ai essayé de remplacer WCHAR tempstr par WCHAR tempstr[]. Le soucis, c'est qu'il me dit que je n'ai pas le droit de ne pas spécifier de taille.

    Alors j'ai fait ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int WcharLength = (SourceFile->Length);
    WCHAR tempstr[WcharLength];
    wcscpy(tempstr, SourceFile);
    et je me retrouve avec une erreur
    C2227: la partie gauche de '->Length' doit pointer vers un type class/struct/union/générique
    Alors j'ai fait ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int WcharLength = sizeof(SourceFile);
    WCHAR tempstr[WcharLength];
    wcscpy(tempstr, SourceFile);
    Et là, je recoince

    error C2057: expression constante attendue
    error C2466: impossible d'allouer un tableau de taille constante 0
    error C2133: 'tempstr'*: taille inconnue
    D'après mes recherches, on crée un tableau en lui donnant en argument un entier.

    Y'a pas une astuces pour lui donner une variable? D'avance merci pour toute pistes

  4. #4
    Membre confirmé
    Inscrit en
    Juin 2005
    Messages
    110
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 110
    Par défaut
    Et en plus d'être mauvais, j'ai surement fais n'importe quoi et je ne pose pas les bonnes questions...

    Je reprends. La methode IVssBackupComponents::IsVolumeSupported prends (entre autre) un VSS_PWSZ, et pas un tableau VSS_PWSZ[].

    Donc, est-ce que je dois prendre un WCHAR[], un WCHAR, ou encore autre chose que je ne connais pas? Je reconnais être carrément perdu

    En fait j'ai besoin que ma classe prenne en argument une chaine de caractère du genre c:\mon\chemin\vers\mon\fichier. J'ai pensé à un WCHAR, puisqu'il semble qu'un VSS_PWSZ en soit un:

    http://msdn.microsoft.com/en-us/libr...41(VS.85).aspx

    Je me suis tourné vers un WCHAR[] suite à une erreur de compilation...

    Il me faut les trois premiers caractères du WCHAR (ou autre) pour en faire le VSS_PWSZ.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void SaveAfile(WCHAR SourceFile, WCHAR DestFile)
    {
    VSS_PWSZ pSourceVolumeName;
     
    	WCHAR tempstr;
    	wcscpy(tempstr, SourceFile);
    	pSourceVolumeName = tempstr.substr(1, 3);
    	BOOL pIsShadowCopySupported;
    	pBackupComponent->IsVolumeSupported(GUID_NULL, pSourceVolumeName, &pIsShadowCopySupported);
    }
    Et ça me génère les erreurs suivantes:
    error C2664: 'wcscpy'*: impossible de convertir le paramètre 1 de 'WCHAR' en 'wchar_t *'
    La conversion d'un type intégral en type pointeur nécessite reinterpret_cast, un cast de style C ou un cast de style fonction.
    Est-ce que je peux faire autrement pour éviter une convertion, ou bien j'ai pas le choix?

    D'avance merci, et encore désolé de ne pas avoir posé correctement le problème

  5. #5
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    Tu ne peux pas déclarer un tableau avec une taille qui n'est pas connue à la compilation (allocation statique de mémoire). Mais tu peux le faire via un malloc() (allocation dynamique de mémoire).
    Je te laisse consulter la doc de cette fonction, n'hésite pas à poser des questions si tu ne comprends pas.

  6. #6
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    La fonction malloc() te renverras un wchar_t*, que tu pourras utiliser dans ton wcscpy().

  7. #7
    Membre confirmé
    Inscrit en
    Juin 2005
    Messages
    110
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 110
    Par défaut
    Me revoila avec malloc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    void SaveAFile(WCHAR SourceFile[], WCHAR DestFile[])
    {
    VSS_ID pSnapShotSetId, pSnapShotId;
    	VSS_PWSZ pSourceVolumeName;
    	wchar_t *tempstr;
    	tempstr = (wchar_t *)malloc(_MAX_PATH);
    	wcscpy_s(tempstr, 2, SourceFile);
    	pSourceVolumeName = tempstr.substr(1, 3);
    	BOOL pIsShadowCopySupported;
    	pBackupComponent->StartSnapshotSet(&pSnapShotSetId);
    	pBackupComponent->IsVolumeSupported(GUID_NULL, pSourceVolumeName, &pIsShadowCopySupported);
    }
    Ben en fait, ça a déplacé le problème. C'est au niveau du substr que ça coince:

    error C2228: la partie gauche de '.substr' doit avoir un class/struct/union
    le type est 'wchar_t *'
    Et après ça risque d'être encore une autre histoire, puisque de toute façon tempstr est un wchar_t * et que pSourceVolumeName est un VSS_PWSZ.
    Je dois mal m'y prendre à la base, mais je ne vois pas où.

    Est-ce que reinterpret_cast pourrais me sortir de là sans tout péter?

    D'avance merci...

  8. #8
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    1. Ne pas faire de '=' avec des pointeurs sur des chaînes de caractère: tu copies le pointeur, pas l'objet pointé
    2. tempstr est un pointeur et une chaîne de caractères en wchar_t* n'est pas une classe --> pas de .substr()
    3. En utilisant wcscpy_s(), tu te restreints (encore) à Microsoft, car cette fonction n'est pas du tout standard. D'ailleurs tempstr ne fera jamais plus de 2 caractères, car tu n'en copies, via cette fonction, que 2

    Autant prendre directement les 3 premiers caractères de ta chaîne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    wcscpy(pSourceVolumeName, tempstr);
    if(wcslen(tempstr) > 3)
       pSourceVolumeName[3] = 0;

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Pourquoi ne pas essayer d'utiliser une std::wstring ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre confirmé
    Inscrit en
    Juin 2005
    Messages
    110
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 110
    Par défaut
    Merci beaucoup de tes conseils, pour le coup du = avec un pointeur, je me suis fait avoir

    Pour wcscpy_s, je pensais bien faire, car les VSS sont spécifique à Microsoft.

    J'ai juste une petite question au sujet du code que tu m'a donné. J'ai compris que wcslen renvoyait la longueur de la chaîne, et que la boucle mettait les trois premier caractère dans un tableau.

    Mais pourquoi le = 0?

    Encore merci du coup de main en tout cas, le code compile sans erreur

  11. #11
    Membre confirmé
    Inscrit en
    Juin 2005
    Messages
    110
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 110
    Par défaut
    Salut Medinoc,

    Désolé, je n'avais pas vu ton post

    Pourquoi pas une std::wstring? Parceque c'est la première fois que j'en entend parler, je ne suis jamais tombé dessus...

    Pour que ça ne paraisse pas trop débile à vos yeux, je suis administrateur système (MMicrosoft, Unix), pas du tout développeur, juste un peu en java ou en python, que j'utilise uniquement là ou des scripts ne me permettent pas de faire les choses simplement, proprement et rapidement. Mais de toutes façon, ce sont toujours des choses simples et basiques.

    Autant dire que j'utilise java 2 à 3 fois par an, pas beaucoup plus.

    Pour le C++, je n'ai vraiment pas le choix, et c'est super laborieux. De toute façon, quand j'aurais pondu une version béta, je le mettrais sous licence BSD, que chacun puisse en profiter et le faire évoluer.

    Tout ça pour vous dire merci de votre patience à mon égard, car malgrès mes recherches, je me rends bien compte de la débilité de mes questions pour des developpeurs chevronnés.

  12. #12
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    Citation Envoyé par scolyo Voir le message
    Mais pourquoi le = 0?
    C'est pour marquer la fin de ta chaîne de caractère. Une fonction comme wcslen() s'arrêtera au 0 pour compter les caractères.
    C'est une notion de base en C/C++, tout chaîne de caractère en mémoire se termine par un 0, ou le caractère '\0'. Cela permet de marquer la fin de ces chaînes et d'éviter les lectures avec dépassement sans fin.

  13. #13
    Membre confirmé
    Inscrit en
    Juin 2005
    Messages
    110
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 110
    Par défaut
    Salut Spout,

    Merci de la précision, je connaissait cette notion, mais je ne savait pas qu'il fallait le préciser à wcslen.

    Encore merci

  14. #14
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    Citation Envoyé par scolyo Voir le message
    Merci de la précision, je connaissait cette notion, mais je ne savait pas qu'il fallait le préciser à wcslen.
    Je n'ai pas dit ça. En aucun cas tu ne dis à wcslen() s'il y a un zéro, ou encore où il est.
    J'ai juste dit que si jamais tu n'as pas de 0 à la fin de ta chaîne de caractères, wcslen() va continuer à chercher jusqu'à ce qu'il en trouve un. Ce qui engendrera à coup sûr une erreur, car tu vas taper dans de la mémoire qui n'est pas la tienne.
    C'est cette histoire de 0 qui est à l'origine des fonctions xxxx_s() de Microsoft, où la tu spécifies la taille de ta chaîne. Ça part d'une bonne intention, mais c'est bien du Microsoft de pondre quelque chose de trop spécifique...

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

Discussions similaires

  1. trier, découper et copier un fichier txt
    Par triaguae dans le forum VBScript
    Réponses: 2
    Dernier message: 19/01/2009, 11h09
  2. Copier un .com sur le 1er secteur d'une disquette
    Par zdra dans le forum Assembleur
    Réponses: 5
    Dernier message: 23/08/2002, 18h03
  3. Copier le texte d'un ListBox dans le clipboard.
    Par Clément[Delphi] dans le forum Composants VCL
    Réponses: 3
    Dernier message: 18/08/2002, 08h20
  4. Copier et afficher une copie d'ecran
    Par Bobx dans le forum Langage
    Réponses: 6
    Dernier message: 02/08/2002, 22h20
  5. Copier une image (jpeg) dans le presse papier
    Par benj63 dans le forum C++Builder
    Réponses: 2
    Dernier message: 29/07/2002, 14h51

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