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 :

[Transtypage] Types, casts et autres joyeusetés.


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 57
    Points : 53
    Points
    53
    Par défaut [Transtypage] Types, casts et autres joyeusetés.
    1- Par exemple, les fonctions toupper et tolower prennent un int et retournent pareil.

    Quand je fais ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    string s="";
    s += toupper('a');
    VC++9 avec /W4 me rembarre que je fais une conversion de int vers a alors que g++ (3.4.4) avec -Wall -std=c++98 ne trouve rien a redire. Est-ce les implementations de string qui different ou quoi ? En tout cas, c'est un peu contre-productif de devoir faire un static_cast ici pour faire taire le compilateur. Est-ce meme recommande ?

    2- En C, pour parcourir un tableau, la recommendation est d'utiliser size_t. Y-a-t-il un type prepose similaire (et generique) en C++ ? Je serais tente de faire long par exemple. Pour les string, en fouillant dans l'aide, j'ai trouve un type ad hoc (std::string::size_type i=0; ) mais il doit bien y avoir mieux/plus general (ici, on pourrait peut-etre penser aux iterateurs en considerant les string comme des vector<char> mais est-ce le cas ?) ?

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 620
    Points
    23 620
    Par défaut
    Citation Envoyé par mailaka Voir le message
    VC++9 avec /W4 me rembarre que je fais une conversion de int vers a alors que g++ (3.4.4) avec -Wall -std=c++98 ne trouve rien a redire. Est-ce les implementations de string qui different ou quoi ? En tout cas, c'est un peu contre-productif de devoir faire un static_cast ici pour faire taire le compilateur. Est-ce meme recommande ?
    Merci de ne pas oublier « Bonjour » et « Merci » aux extrémités de ton post.

    toupper() existe en C (dans ctype.h) et en C++ (dans cctype).

    Extrait du GNU cctype :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    //
    // ISO C++ 14882: <ccytpe>
    //
     
    #ifndef _GLIBCXX_CCTYPE
    #define _GLIBCXX_CCTYPE 1
     
    #pragma GCC system_header
     
    #include <bits/c++config.h>
    #include <ctype.h>
     
    // Get rid of those macros defined in <ctype.h> in lieu of real functions.
    #undef isalnum
    #undef isalpha
    #undef iscntrl
    #undef isdigit
    #undef isgraph
    #undef islower
    #undef isprint
    #undef ispunct
    #undef isspace
    #undef isupper
    #undef isxdigit
    #undef tolower
    #undef toupper
     
    _GLIBCXX_BEGIN_NAMESPACE(std)
     
      using ::isalnum;
      using ::isalpha;
      using ::iscntrl;
      using ::isdigit;
      using ::isgraph;
      using ::islower;
      using ::isprint;
      using ::ispunct;
      using ::isspace;
      using ::isupper;
      using ::isxdigit;
      using ::tolower;
      using ::toupper;
     
    _GLIBCXX_END_NAMESPACE
     
    #endif

    Donc, les fonctions à la mode C++ de GNU s'appuient sur les fonctions C standard, tout en déconstruisant les macros préjudiciables et en spécifiant un namespace explicite pour chacune d'elles.

    Pour le reste, toupper() et tolower() attendent des int car d'autres fonctions telles que fgetc() renvoient elles-aussi des int, pour pouvoir balancer EOF, par exemple, le cas échéant. Et elles renvoient également un int car si le caractère n'a pas pu être converti, il est renvoyé tel quel. Extrait de la man page :

    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
    16
    17
    18
    SYNOPSIS
           #include <ctype.h>
     
           int toupper(int c);
           int tolower(int c);
     
    DESCRIPTION
           toupper() converts the letter c to upper case, if possible.
     
           tolower() converts the letter c to lower case, if possible.
     
           If c is not an unsigned char value, or EOF, the behavior of these functions is undefined.
     
    RETURN VALUE
           The value returned is that of the converted letter, or c if the conversion was not possible.
     
    CONFORMING TO
           C89, C99, 4.3BSD

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    VC++9 avec /W4 me rembarre que je fais une conversion de int vers a
    Ça ne veut rien dire.
    Il te dit pas plutôt qu'une conversion de int en char est susceptible de perdre des données ?
    Boost ftw

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    De prime abord, je dirais que c'est l'implémentation de VC8 qui part "en vrille" sur ce coup là...

    En effet, si le prototype de toupper est int toupper(int), il n'en reste pas moins que:
    • la conversion de char en int est implicite et ne pose aucun problème (car char <= int)
    • la conversion de inte en char pourrait poser des problèmes de pertes de données, mais, comme l'idée est quand même de récupérer une valeur entière dont les limites sont identiques à la valeur entière que l'on demande de convertir (un char), nous avons la certitude qu'il n'y aura pas de perte d'information pertinente

    En outre, l'opérateur += offre suffisemment de surcharges pour s'adapter à l'ajout d'un simplet et unique caractère

    Pour la deuxième question, size_t est un alias de type d'un entier non signé dont le nombre de bits est suffisant pour permettre d'accéder à l'ensemble des éléments potentiellement visés (en gros, suffisant pour représenter l'ensemble des adresses mémoire disponibles)

    De mémoire, la norme ne fournit pas de taille précise pour ce type (comme la plupart des types primitifs, leur taille en bit est laissée à l'appréciation de l'implémentation), mais assure ce que j'ai indiqué plus haut.

    Lorsque tu regarde attentivement les prototypes de toutes les fonctions et méthodes qui utilisent size_t, et que tu prend en compte les lignes qui précèdent, tu te rend compte que l'utilisation de ce type particulier en lieu et place de l'entier non signé (d'office, car on ne devrais pas vouloir accéder à l'index -10 d'un tableau ) équivalent est de nature à t'assurer un maximum de compatibilité du code en cas de passage à un autre compilateur.

    En effet, si size_t est défini comme étant un unsigned int dans une implémentation de compilateur donné, et que tu utilise l'unsigned long, tu ne cours pas de risque de perte de donnée.

    Par contre, dans le cas contraire (en gros: tous les cas dans lesquels tu serais parti du principe que size_t correspond à un type plus petit que celui auquel il correspond réellement), le risque de perte de donnée est bel et bien réel

    Quand à la présence d'un alias size_t dans la std::string, c'est parce que cette classe est en réalité une spécialisation de std::basic_string, et que, pour assurer la compatibilité, il y a déclaration d'un alias de type avec le trait correspondant
    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

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 57
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,

    De prime abord, je dirais que c'est l'implémentation de VC8 qui part "en vrille" sur ce coup là...
    [...]
    la conversion de int en char pourrait poser des problèmes de pertes de données, mais, comme l'idée est quand même de récupérer une valeur entière dont les limites sont identiques à la valeur entière que l'on demande de convertir (un char), nous avons la certitude qu'il n'y aura pas de perte d'information pertinente
    Je suis d'accord avec toi et l'idee est bien celle-la. Je sais que dans ce contexte particulier, je n'aurai a priori 'jamais' de perte d'info. Sauf que le compilo lui il n'en sait rien de ce contexte. Donc il n'a pas tort a priori mais cela est quand meme chiant (je mets aussi /Wx).

    En outre, l'opérateur += offre suffisemment de surcharges pour s'adapter à l'ajout d'un simplet et unique caractère
    C'est peut-etre cette surcharge qui donne le contexte pour g++. Mais j'aurais pu mettre aussi s[0]= toupper('a'); VC++9 rale et toujours pas g++ (peut-etre la meme raison, un contexte donne par une des surcharges de operator[] dans le cas de g++ ?)

    Pour la deuxième question, size_t est un alias de type d'un entier non signé dont le nombre de bits est suffisant pour permettre d'accéder à l'ensemble des éléments potentiellement visés (en gros, suffisant pour représenter l'ensemble des adresses mémoire disponibles)
    Ok, pour resumer, size_t reste mon ami. string peu-il etre considere comme un conteneur de caracteres ?

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par mailaka Voir le message
    Ok, pour resumer, size_t reste mon ami. string peu-il etre considere comme un conteneur de caracteres ?
    A titre personnel, je n'utilise plus que le size_t dés le moment où je travaille sur les méthodes des différents conteneurs... Maintenant, c'est un aspect qui n'engage que moi .

    Mais, oui, size_t est ton ami, et oui, dans une certaine mesure, std::string pourrait être considéré comme un conteneur de caractères, car, à bien y réfléchir:
    • Il s'agit d'une spécialisation (de base_string< > en l'occurrence)
    • elle dispose d'un grand nombre de méthodes que l'on pourrait parfaitement retrouver dans un conteneur


    Mais ce ne sont là que considérations purement rhétoriques, car, il n'y a rien à faire, le nom indiquant l'usage, on s'attend d'abord et avant tout à ce que cette classe permette de... représenter des chaines de caractères utilisables par l'homme
    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

  7. #7
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Tu n'as toujours pas fourni le vrai message d'erreur de MSVC.
    L'idéal serait aussi d'avoir le testcase qui va avec.
    Boost ftw

Discussions similaires

  1. [FocusTraversalPolicy] et autres joyeusetés
    Par Ofunk dans le forum Interfaces Graphiques en Java
    Réponses: 2
    Dernier message: 17/06/2010, 13h35
  2. Réponses: 5
    Dernier message: 18/10/2006, 20h30
  3. Réponses: 1
    Dernier message: 30/05/2006, 23h34
  4. lancer un application de type nero ou autre...
    Par doudou1 dans le forum VBScript
    Réponses: 1
    Dernier message: 30/12/2005, 18h46
  5. CAST ou autre ?
    Par 74160 dans le forum Requêtes
    Réponses: 2
    Dernier message: 10/07/2003, 15h00

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