11
votes

Comment imprimer la chaîne que __File__ se développe correctement?

Considérez ce programme:

struct LogFile {
    // Write message to file. The file should contain the UTF-8 encoded data!
    void writeMessage( const std::string &msg );
};

// Global function which returns a pointer to the 'active' log file.
LogFile *activeLogFile();

#define TRACE_BEACON activeLogFile()->write( __FILE__ );


2 commentaires

@RODDY: J'utilise MSVC9, mais je suis également intéressé par une solution pour g ++ 4.x


Ceci est également totalement absorbé par MSVC 2015. Pourquoi Microsoft ne peut-il pas simplement créer un compilateur qui ne baise pas?


5 Réponses :


-1
votes

Quant au codage, je vais deviner que c'est ce qui est utilisé par le système de fichiers, probablement unicode.

comme pour traiter avec cela, comment changer votre code le code comme: p>

#define TRACE_BEACON activeLogFile()->write( FixThisString(__FILE__ )); 

std::string FixThisString(wchar_t* bad_string) { .....}


2 commentaires

__ Fichier __ est un Char String pas un wchar_t chaîne. Vous devrez utiliser le préprocesseur pour préfixer l si vous voulez le faire. Et puis vous pouvez utiliser le bon printf -Family pour l'imprimer.


@R: L'erreur qu'il obtient est cette chaîne qu'il est d'impression contient un '\ u043f' qui serait un 13 bits, unicode wchar_t.



-1
votes

La meilleure solution consiste à utiliser des noms de fichiers source dans l'ensemble de caractères de nom de fichier portable [A-ZA-Z0-9 ._-] . Puisque Windows ne prend pas en charge UTF-8, il n'y a aucun moyen de représenter des caractères arbitraires non ascii dans des chaînes ordinaires sans dépendance à votre langue locale configurée.

GCC ne s'en soucie probablement pas; Il traite tous les noms de fichiers sous forme de chaînes de 8 bits et donc si le nom de fichier est accessible à GCC, son nom sera représentable. (Je sais que Cygwin fournit un environnement UTF-8 par défaut et moderne * NIX sera normalement UTF-8.) Pour MSVC, vous pourrez peut-être utiliser le préprocesseur pour préparer l à l'expansion de < Code> __ fichier __ et utiliser % ls pour le formater.


0 commentaires

10
votes

Utilisation peut utiliser l'opérateur de colle de jeton, comme celui-ci:

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define WFILE WIDEN(__FILE__)

int main() {
    wprintf("%s\n", WFILE);
    return 0;
}


8 commentaires

Cela semble très intéressant! Cependant, cela déclenche une question de suivi: quel codage l'utilisation de la chaîne de caractère large utilise-t-elle? UTF-16? Ou est-ce une chaîne plaine, sans-accoode, UCS-2? À l'heure actuelle, il me semble que cela ne fait que «retarder» la question. Cependant, c'est beaucoup mieux que mon code actuel de moi.


Malheureusement, cela ne semble pas fonctionner comme prévu: il imprime juste '???????' au cas où le fichier a un nom russe. C'est la même chose que je vois lors de la liste du fichier avec 'dir'. Peut-être que __ fichier __ est vraiment lié au codage du système de fichiers, mais il n'honore pas quel que soit l'explorateur Windows utilise pour montrer les caractères russes?


Fonctionne sur ma machine. Utilisez-vous un programme en mode console? Avez-vous changé la console à une page de code cyrillique avec une police qui supporte les glyphes? SetConsolecP (1251) Par exemple, par exemple, la police de Consolas. Le codage de la console par défaut est OEM, il n'a pas les glyphes.


J'utilise un programme de console (no / Subsystème: Windows transmis sur la liaison) mais je imprime en fait la chaîne via de sortieDebugstringw . Cela semble vraiment être une question de police; imprimer les octets individuels des rendements de la chaîne par ex. 0x043F 0x0440 0x043e qui n'est certainement pas le code Unicode pour '?'. Accepter cette réponse, merci beaucoup!


Hans, j'aimerais juste remarquer que définir __ wfile __ est un comportement techniquement indéfini, car il s'agit d'un symbole réservé (il commence par deux soulignes). Cela pourrait facilement être résolu en définissant la macro avec tout autre nom (peut-être simplement wfile ).


HM, visiter cette réponse après un certain temps, cela ne fonctionne pas du tout pour moi. Par exemple, le format doit être l "% ls \ n" pour wPrintf : il attend une chaîne de caractères large en tant que format et puisque le retour de la macro est une chaîne de caractères large. aussi, il doit y avoir le % ls et non % s . Mais même si je le fais, je ne fais qu'un? pour un caractère spécial.


WPRINTF () est la version large de printf (), elle attend déjà une large chaîne comme argument pour% s. Cela me semble que vous devez cliquer sur le bouton Posez une question et documenter réellement ce que ce "caractère spécial" est.


Juste pour la complétude Voici la référence complète aux macros prédéfinies dans vs.



-1
votes

Dans MSVC, vous pouvez activer UNICODE et obtenir des chaînes codées UTF-16. C'est dans les propriétés du projet quelque part. De plus, vous devriez simplement utiliser WCOUT / COUT NON PRINTF / WPRINTF. Windows avait besoin d'unicode avant d'exister Unicode, il y a donc un codage de caractères multi-octets personnalisé, qui est la valeur par défaut. Cependant, Windows prend en charge UTF16- c'est par exemple, C #.

#include <iostream>

int main() {
    std::wcout << __WFILE__;
}


0 commentaires

1
votes

__ __ FILE sera toujours étendre à chaîne de caractères littérale , ainsi en substance, il sera compatible avec char const * . Cela signifie qu'une mise en œuvre du compilateur n'a pas beaucoup d'autre choix que d'utiliser le cru représentation des octets du nom du fichier source telle qu'elle se présente au moment de la compilation.

Si oui ou non c'est quelque chose de sensible dans les paramètres régionaux en cours ou ne pas pas d'importance, vous pourriez avoir un nom de fichier source qui contient essentiellement des déchets, aussi longtemps que votre système de temps d'exécution et le compilateur accepter comme un nom de fichier valide.

Si vous, en tant qu'utilisateur, vous avez un lieu différent avec codage différent que celui utilisé dans le système de fichiers, vous verrez beaucoup de ???? ou similaire.

si vos deux lieux sont d'accord sur l'encodage, une plaine printf devrait suffire et votre terminal (ou tout ce que vous utilisez pour regarder la sortie) devrait pouvoir imprimer correctement les caractères.

Donc, la réponse courte est, il ne fonctionnera que si votre système est le codage w.r.t cohérent. Sinon, votre pas de chance, puisque deviner encodages est une tâche assez difficile.


0 commentaires