kzen.dev
  • Questions
  • Tags
  • Utilisateurs
Notifications
Récompenses
Inscription
Une fois inscrit, vous serez informé des réponses et des commentaires à vos questions.
Connectez-vous
Si vous avez déjà un compte, connectez-vous pour vérifier les nouvelles notifications.
Il y aura des récompenses pour les questions, réponses et commentaires ajoutés.
Détails
Source
Editer
 TheDarkIn1978
TheDarkIn1978
Question

printf avec std::string ?

Si j'ai bien compris, string est un membre de l'espace de noms std, alors pourquoi la situation suivante se produit-elle ?

#include <iostream>

int main()
{
    using namespace std;

    string myString = "Press ENTER to quit program!";
    cout << "Come up and C++ me some time." << endl;
    printf("Follow this command: %s", myString);
    cin.get();

    return 0;
}

![entrer la description de l'image ici][2]

Chaque fois que le programme s'exécute, myString imprime une chaîne de 3 caractères apparemment aléatoire, comme dans la sortie ci-dessus.

[2] : http://i.stack.imgur.com/W1w68.png

142 2012-06-02T21:07:06+00:00 3
Micha Wiedenmann
Micha Wiedenmann
Question modifiée 14 mars 2019 в 4:20
Programmation
namespaces
c++
string
printf
std
Cette question a 1 réponse en anglais, pour les lire connectez-vous à votre compte.
Solution / Réponse
 chris
chris
2 juin 2012 в 9:09
2012-06-02T21:09:02+00:00
Détails
Source
Editer
#16341672

Il compile parce que printf n'est pas sûr au niveau du type, puisqu'il utilise des arguments variables au sens du C1. printf n'a pas d'option pour std::string, seulement une chaîne de style C. Utiliser quelque chose d'autre à la place de ce qu'il attend ne vous donnera certainement pas les résultats que vous souhaitez. Il s'agit en fait d'un comportement indéfini, donc tout peut arriver.

La façon la plus simple de résoudre ce problème, puisque vous utilisez le C++, est d'imprimer la chaîne normalement avec std::cout, puisque std::string le supporte grâce à la surcharge des opérateurs :

std::cout << "Follow this command: " << myString;

Si, pour une raison quelconque, vous avez besoin d'extraire la chaîne de style C, vous pouvez utiliser la méthode c_str() de std::string pour obtenir un const char * qui est terminé par un caractère nul. En utilisant votre exemple :

#include <iostream>
#include <string>
#include <stdio.h>

int main()
{
    using namespace std;

    string myString = "Press ENTER to quit program!";
    cout << "Come up and C++ me some time." << endl;
    printf("Follow this command: %s", myString.c_str()); //note the use of c_str
    cin.get();

    return 0;
}

Si vous voulez une fonction qui ressemble à printf, mais sans danger pour le type, regardez dans les modèles variadiques (C++11, supporté par tous les compilateurs majeurs à partir de MSVC12). Vous pouvez en trouver un exemple [ici] (https://web.archive.org/web/20131018185034/http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html). A ma connaissance, il n'y a pas d'implémentation de ce type dans la bibliothèque standard, mais il pourrait y en avoir une dans Boost, spécifiquement boost::format.


[1] : Cela signifie que vous pouvez passer n'importe quel nombre d'arguments, mais la fonction compte sur vous pour lui indiquer le nombre et les types de ces arguments. Dans le cas de printf, cela signifie une chaîne de caractères avec des informations de type codées comme %d qui signifie int. Si vous mentez sur le type ou le nombre, la fonction n'a aucun moyen standard de le savoir, bien que certains compilateurs aient la capacité de vérifier et de donner des avertissements lorsque vous mentez.

Wayne Dawson
Wayne Dawson
Réponse modifiée 5 avril 2018 в 8:21
217
0
Jerry Coffin
Jerry Coffin
2 juin 2012 в 9:36
2012-06-02T21:36:08+00:00
Détails
Source
Editer
#16341673

N'utilisez pas printf("%s&quot ;, your_string.c_str());.

Utilisez plutôt cout << your_string;. C'est court, simple et sûr. En fait, lorsque vous écrivez en C++, vous voulez généralement éviter complètement printf - c'est un vestige du C qui est rarement nécessaire ou utile en C++.

Quant à savoir pourquoi vous devriez utiliser cout au lieu de printf, les raisons sont nombreuses. Voici un échantillon de quelques-unes des plus évidentes :

  1. Comme le montre la question, printf n'est pas sûr du type. Si le type que vous passez diffère de celui donné dans le spécificateur de conversion, printf essaiera d'utiliser ce qu'il trouve sur la pile comme si c'était le type spécifié, donnant un comportement non défini. Certains compilateurs peuvent avertir de ce problème dans certaines circonstances, mais certains compilateurs ne le peuvent pas/ne le veulent pas du tout, et aucun ne le peut dans toutes les circonstances.

  2. `printf' n'est pas extensible. Vous ne pouvez lui passer que des types primitifs. L'ensemble des spécificateurs de conversion qu'il comprend est codé en dur dans son implémentation, et il n'y a aucun moyen pour vous d'en ajouter d'autres. La plupart des C++ bien écrits devraient utiliser ces types principalement pour implémenter des types orientés vers le problème à résoudre.

  3. Il rend le formatage décent beaucoup plus difficile. Pour prendre un exemple évident, lorsque vous imprimez des chiffres pour que les gens les lisent, vous voulez généralement insérer des séparateurs de milliers tous les quelques chiffres. Le nombre exact de chiffres et les caractères utilisés comme séparateurs varient, mais cout s'en charge également. Par exemple :

     std::locale loc("&quot ;);
     std::cout.imbue(loc) ;
    
     std::cout << 123456.78 ;

    La locale sans nom (le "&quot ;) choisit une locale en fonction de la configuration de l'utilisateur. Par conséquent, sur ma machine (configurée pour l'anglais américain), cela s'imprime comme 123,456.78. Pour quelqu'un dont l'ordinateur est configuré pour (disons) l'Allemagne, cela s'imprimera comme 123.456,78. Pour quelqu'un dont l'ordinateur est configuré pour l'Inde, il s'agirait de 1,23,456.78 (et bien sûr, il y en a beaucoup d'autres). Avec printf, j'obtiens exactement un seul résultat : 123456.78. C'est cohérent, mais c'est constamment faux pour tout le monde et partout. La seule façon de contourner ce problème est de faire le formatage séparément, puis de passer le résultat sous forme de chaîne à printf, parce que printf lui-même ne fera tout simplement pas le travail correctement.

  4. Bien qu'elles soient assez compactes, les chaînes au format printf peuvent être assez illisibles. Même parmi les programmeurs C qui utilisent printf pratiquement tous les jours, je suppose qu'au moins 99% d'entre eux ont besoin de vérifier pour être sûrs de ce que signifie le # de %#x, et en quoi cela diffère de ce que signifie le # de %#f (et oui, ils signifient des choses complètement différentes).

Jerry Coffin
Jerry Coffin
Réponse modifiée 31 août 2014 в 3:22
40
0
Alessandro Pezzato
Alessandro Pezzato
2 juin 2012 в 9:08
2012-06-02T21:08:56+00:00
Détails
Source
Editer
#16341671

Utilisez myString.c_str() si vous voulez une chaîne de caractères de type c (const char*) à utiliser avec printf.

Merci

Karsten Koop
Karsten Koop
Réponse modifiée 5 juillet 2019 в 11:23
27
0
Ajouter une question
Catégories
Toutes
Technologie
Culture / Loisirs
Vie / Arts
Science
Professionnel
Entreprises
Utilisateurs
Tous
Nouveau
Populaire
1
Ilya Smirnov
Enregistré il y a 5 jours
2
Денис Васьков
Enregistré il y a 1 semaine
3
Dima Patrushev
Enregistré il y a 1 semaine
4
sirojidddin otaboyev
Enregistré il y a 2 semaines
5
Елена Гайдамамакинат
Enregistré il y a 2 semaines
DE
EL
ES
FR
ID
IT
JA
KO
NL
PT
RO
RU
TR
ZH
© kzen.dev 2023
Source
stackoverflow.com
sous licence cc by-sa 3.0 avec l'attribution