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

Affichage des résultats du sondage: Pourquoi C et C++ auraient-ils encore de nombreuses années devant eux ?

Votants
75. Vous ne pouvez pas participer à ce sondage.
  • C et C++ permettent d'avoir plus de contrôle sur le matériel

    41 54,67%
  • C et C++ vous permettent d'écrire du code très efficace

    38 50,67%
  • Les langages C et C++ sont portables

    35 46,67%
  • C et C++ sont des langages qui évoluent

    19 25,33%
  • C et C++ sont largement utilisés

    48 64,00%
  • C++ a peut-être de l'avenir, mais je doute que ça soit le cas de C

    8 10,67%
  • C a peut-être de l'avenir, mais je doute que ça soit le cas de C++

    3 4,00%
  • Je pense qu'ils n'ont plus beaucoup d'années devant eux

    6 8,00%
  • Autre (à préciser)

    3 4,00%
  • Pas d'avis

    3 4,00%
Sondage à choix multiple
Langages de programmation Discussion :

Pourquoi les langages C et C++ auraient-ils encore de nombreuses années devant eux ?


Sujet :

Langages de programmation

  1. #341
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 107
    Points
    6 107
    Par défaut
    Citation Envoyé par zecreator Voir le message
    Peut-être que l'avenir de la programmation passera aussi par des système de développement à la portée de n'importe qui, et des langages simplifiés au maximum, tout en étant performants.
    Parmi les langages au sommet du classement TIOBE, le plus accessible pour les débutants est le Python. Avec une connaissance très rudimentaire du langage, on peut facilement automatiser certaines tâches simples comme renommer des fichiers d'un dossier en suivant une certaine règle.

    D'ailleurs, le langage n'a pas réellement besoin d'être simple pour être accessible pour les débutants. Dans Python, si on prend en compte les hooks qui permettent de modifier la sémantique du langage comme __getattr__, __getattribute__, les descripteurs et surtout les métaclasses, on constate que le Python n'est pas simple. Mais, heureusement, les débutants n'ont pas besoin de connaître ces subtilités pour faire des choses simples. Le langage C, par contre, bien qu'il soit vraisemblablement plus simple que Python, est moins accessible pour les débutants, entre autres parce qu'il faut maîtriser la sémantique de pointeurs même pour faire des choses très basiques comme des manipulations de chaînes.

    Par contre, je ne crois pas en un avenir où tout le monde pourrait programmer des droïdes comme dans Star Wars. Paramétrer, à la limite, mais pas programmer.

    De plus, même dans un avenir où tout le monde saurait programmer, il y aura toujours un écart entre les débutants et les experts, car seuls les experts peuvent concevoir un système à la fois complexe et maintenable. Quand un débutant programme, il a tendance à mettre en place une structure dans laquelle tout dépend de tout, dont on perd la maîtrise dès qu'elle a trop grossi.

  2. #342
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    Par contre, je ne crois pas en un avenir où tout le monde pourrait programmer des droïdes comme dans Star Wars. Paramétrer, à la limite, mais pas programmer.

    De plus, même dans un avenir où tout le monde saurait programmer, il y aura toujours un écart entre les débutants et les experts, car seuls les experts peuvent concevoir un système à la fois complexe et maintenable. Quand un débutant programme, il a tendance à mettre en place une structure dans laquelle tout dépend de tout, dont on perd la maîtrise dès qu'elle a trop grossi.
    Pareil.

    Dis autrement, logique et génie logiciel, ça ne s'invente pas. Il suffit pas que le langage soit simple, il faut savoir organiser nos idées pour arriver à un résultat, même si une partie venait à être prémâchée avec des MDA ou autres idées dans le genre.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  3. #343
    Membre expert

    Homme Profil pro
    Consultant
    Inscrit en
    Janvier 2006
    Messages
    1 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Consultant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 376
    Points : 3 583
    Points
    3 583
    Par défaut
    C'est peut-être là que l'AI interviendra. Comprendre la formulation du besoin, et structurer le code en fonction. Si l'on prend un outil comme GDevelop, n'importe qui peut créer un petit jeu sans coder une seule ligne. Il faut avoir une certaine logique, pour placer les événements aux bon endroit, mais ça reste tout de même accessible, même à des néophites.

    Pourquoi ne pas imaginer le même principe pour des applications plus complexes ?
    "La révolution informatique fait gagner un temps fou aux hommes, mais ils le passent avec leur ordinateur !"

  4. #344
    Membre expert

    Homme Profil pro
    Consultant
    Inscrit en
    Janvier 2006
    Messages
    1 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Consultant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 376
    Points : 3 583
    Points
    3 583
    Par défaut
    Si j'arrive à retrouver l'article, il existe un projet qui se nomme : "Dev Instant Killer" ou quelque chose comme ça. L'idée est de regrouper toutes les manières de produire une application en utilisant le développeur le moins possible. En utilisant des auto-générateurs de code, des templates configurables... Avec pour objectif d'alléger les coûts de développement et garder une maîtrise de l'évolution du programme, sans faire appel au développeur. C'était assez intéressant

    Faut que je retrouve ce truc.
    "La révolution informatique fait gagner un temps fou aux hommes, mais ils le passent avec leur ordinateur !"

  5. #345
    Membre éprouvé
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Mai 2016
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2016
    Messages : 313
    Points : 1 237
    Points
    1 237
    Par défaut
    L'idéal serait que l'IA puisse générer le logiciel directement à partir du compte rendu de réunion de la direction avec le service marketing.
    Plus besoin de s'emm... avec ces développeurs tout le temps en train de râler et de réclamer des augmentations

    Plus sérieusement :
    Il y a déjà des générateurs de code, ça doit servir à faire des sites webs, IHM, certains jeux. C'est un premier pas

  6. #346
    Membre expert

    Homme Profil pro
    Consultant
    Inscrit en
    Janvier 2006
    Messages
    1 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Consultant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 376
    Points : 3 583
    Points
    3 583
    Par défaut
    Citation Envoyé par wolinn Voir le message
    Plus sérieusement :
    Il y a déjà des générateurs de code, ça doit servir à faire des sites webs, IHM, certains jeux. C'est un premier pas
    Quand on voit comment a évoluer la manière de développer les logiciels en 10-15 ans, on peut imaginer que cela aura évoluer encore dans 10-15 ans, pour arriver à quelque chose approchant l'automatisation.

    Pourquoi pas ?

    P.S. : Tous mes clients fantasme d'un bouton permettant la création de leur site ou application. Il y a une demande lol
    "La révolution informatique fait gagner un temps fou aux hommes, mais ils le passent avec leur ordinateur !"

  7. #347
    Membre régulier
    Inscrit en
    Décembre 2004
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 123
    Points : 97
    Points
    97
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    En C++, pour les interfaces graphiques, on a Qt, qui est un bon framework.
    En Delphi, je ne connais pas tous les frameworks pour les interfaces graphiques. Je ne connais que la VCL, que j'utilise au boulot via C++ Builder, et qui est moins bien conçue que Qt.
    Je reconnais qu'utiliser la VCL en C++, c'est pas sympa. En Pascal natif, la VCL, et la FireMonkey, additionnés de composants comme Lohninger et TeeChartPro, cela explose Qt. En qualité et en productivité. Vous avez tout à fait raison, la méthode de développement l'IHM avec ces frameworks compte également beaucoup.

    Citation Envoyé par Pyramidev Voir le message
    Parmi les langages au sommet du classement TIOBE, mon préféré est le C++, surtout pour les raisons suivantes :
    • Il est multi-paradigme. Il supporte le procédural et l'objet. Il supporte aussi moins mal la programmation générique que les autres langages au sommet.
    • Il est statiquement typé.
    • Il a beaucoup de fonctionnalités et continue d'évoluer.
    • Il est performant. Cela implique que, quand on a besoin d'augmenter les performances, on a moins besoin de faire des sales bidouilles que dans les langages moins performants.
    J'ai déjà traité l'argument de popularité: si vous souhaitez rouler en twingo, libre à vous. Quant aux autres points de votre liste, Pascal et Ada les ont tous, et en mieux. De plus, Pascal possède le paradigme composant, que ne possède pas le C++. La notion de paquetage y est formidablement bien mieux (que la notion affreuse de namespace). Et les deux langages sont lisibles. Encore une fois, libre à vous de préférer le MacDo au 3 étoiles Michelin. Mais le nombre ne fait pas la qualité...

    Citation Envoyé par Pyramidev Voir le message
    Je recherche un langage qui permet d'écrire du code très modulaire, concis et tel que, quand ça compile, en général, ça marche. Le Haskell me semble être un bon candidat. Je ne connais pas encore tout son potentiel. Je continue de l'apprendre.

    Je recherche aussi un langage impératif qui offre les mêmes performances que le C++ et supporte mieux la programmation générique et la métaprogrammation que le C++. Le meilleur candidat me semble être le langage D qui, d'ailleurs, supporte aussi l'objet. Je l'approfondirai plus tard.
    [/QUOTE] Je supporte complétement votre démarche de trouver une meilleure alternative à C++.

    Je n'adhère pas à votre exigence de concision qui n'a aucun intérêt à l'heure actuelle avec les environnements modernes et la génération de sources. Sur mes gros projets, 90% du source est généré, peut importe la concision... En revanche, quand il faut lire le source et comprendre les interactions entre le source généré et le source écrit à la main, souvent pour trouver un défaut, la lisibilité compte et la concision est un problème.

    Par ailleurs, je ne vous vois pas tenter de reproduire le composant exemple que j'ai fourni...

  8. #348
    Membre expert

    Homme Profil pro
    Consultant
    Inscrit en
    Janvier 2006
    Messages
    1 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Consultant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 376
    Points : 3 583
    Points
    3 583
    Par défaut
    Citation Envoyé par thierryc Voir le message
    Sur mes gros projets, 90% du source est généré...
    Peux-tu préciser ? Qu'appelles-tu "généré" ? Quel langage ? Quels outils ? Quelles méthodes ? Quels avantages ?
    "La révolution informatique fait gagner un temps fou aux hommes, mais ils le passent avec leur ordinateur !"

  9. #349
    Membre expert

    Homme Profil pro
    Consultant
    Inscrit en
    Janvier 2006
    Messages
    1 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Consultant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 376
    Points : 3 583
    Points
    3 583
    Par défaut
    De mon coté, sur mes projets clients, le code est automatiquement généré par l'IDE. je le retouche un peu lorsqu'il y a une comportement spécifique, mais dans 80% des cas, j'ai pas vraiment besoin de toucher au code.

    Bien sûr, c'est une solution adaptée au budget que le client accepte de mettre sur la table. Si l'on devait développer "à la main", cela lui coûtera sans doute 2 à 3 fois plus cher.

    Et au final, pour le client c'est totalement transparent. Il a le produit qu'il a payé, avec les fonctions demandées.

    Du coup, la question se pose : dans 10-15 ans, sera t-il encore rentable de faire appel à des développeurs pour du Service client. Pour du back peut-être, mais pour le front, j'en doute.
    "La révolution informatique fait gagner un temps fou aux hommes, mais ils le passent avec leur ordinateur !"

  10. #350
    Membre régulier
    Inscrit en
    Décembre 2004
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 123
    Points : 97
    Points
    97
    Par défaut
    Citation Envoyé par zecreator Voir le message
    Peux-tu préciser ? Qu'appelles-tu "généré" ? Quel langage ? Quels outils ? Quelles méthodes ? Quels avantages ?
    En Pascal, C++, Ada ou Fortran 95, à partir d'UML ou d'autres choses dont je n'ai pas le droit de parler, avec des méthodes orientées composants inspirées de Coad, Booch, Ellis et Rumbaugh (UML n'étant pas une méthode), et comme avantage principal une claire séparation du source généré du source écrit à la main. Par ailleurs, cela génère également le CdCF, le dossier de conception, un squelette des tests unitaires, une IHM générique et la persistance...

    J'écris mes propres générateurs, ceux du commerce étant très insuffisants pour une approche composant, et surtout ils travaillent à un niveau d'abstraction assez bas. En effet, je considère que chaque classe du domaine métier doit être générée comme un composant logiciel, avec une interface et une implémentation. Les associations aussi en général sont très mal générées.

    J'appelle ma méthode "UCF" : Unified Component Factory, et mon générateur : UCFGenerator. Il est capable d'importer de l'UML d'à peu près tous les outils existants, pourvus que ceux-ci aient un export en XML. Mon outil actuel est ModelMaker car il supporte bien UML, et il supporte également la méthode "UML in Colors" de Peter Coad. C'est en Pascal que les avantages sont les plus évidents car ce langage supporte nativement le paradigme composant et c'est là que la génération de sources est la plus complète. En ce moment, mes outils subissent une refonte (refactoring), car je prépare le passage à Delphi Architect.

    J'envisage d'ajouter la génération de documentation en DocBook5, cet outil me paraissant très puissant, notamment pour générer les manuels utilisateur, développeur et l'aide en ligne au format HtmlHelp.

    Dans le commerce, Objecteering me semble être l'un des outils les plus puissants du marché.
    Et bien sûr, RAD Studio Architect dispose également de bonnes capacités de génération à partir d'UML pour viser Pascal ou C++. Et ses capacités de génération de code IHM sont sans pareil.

  11. #351
    Membre expert

    Homme Profil pro
    Consultant
    Inscrit en
    Janvier 2006
    Messages
    1 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Consultant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 376
    Points : 3 583
    Points
    3 583
    Par défaut
    Citation Envoyé par thierryc Voir le message
    En Pascal, C++, Ada ou Fortran 95, à partir d'UML ou d'autres choses dont je n'ai pas le droit de parler, avec des méthodes orientées composants inspirées de Coad, Booch, Ellis et Rumbaugh (UML n'étant pas une méthode), et comme avantage principal une claire séparation du source généré du source écrit à la main. Par ailleurs, cela génère également le CdCF, le dossier de conception, un squelette des tests unitaires, une IHM générique et la persistance...
    Quand tu parles de 90% de code généré, cela veut dire que tu ne codes quasiment plus à la main (10%) ? Est-ce qu'en terme de temps de développement tu y gagnes beaucoup ? Cela a t-il un impact sur le budget final du projet ?
    "La révolution informatique fait gagner un temps fou aux hommes, mais ils le passent avec leur ordinateur !"

  12. #352
    Membre régulier
    Inscrit en
    Décembre 2004
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 123
    Points : 97
    Points
    97
    Par défaut
    Citation Envoyé par zecreator Voir le message
    Quand tu parles de 90% de code généré, cela veut dire que tu ne codes quasiment plus à la main (10%) ? Est-ce qu'en terme de temps de développement tu y gagnes beaucoup ? Cela a t-il un impact sur le budget final du projet ?
    Il y a également beaucoup de réutilisation. L'essentiel du source est réutilisé ou généré. Il y a très peu de source écrit à la main, mais il en reste. Le ratio est de l'ordre de 50% de réutilisation, 40% de généré, et 10% à la main, hors IHM compliquées. Il reste aussi pas mal de sources de tests à écrire. Mais dans mes projets, la phase d'écriture n'est pas la plus coûteuse. En fait, cela change la structure budget du projet : le cahier des charges, le ou les prototypes ont davantage de budget, la conception en a beaucoup, l'écriture bcp mois, le débogage également, le cahier de recette davantage de budget. Les gains les plus importants sont en maintenance : la maintenance corrective est quasiment éliminée et la maintenance évolutive beaucoup facilitée.
    Au final, suivant les projets, on gagne entre 20% et 50% lors de la première phase de développement et de l'ordre de 70% à 95% en phase de maintenance.
    En fait l'avantage déterminant, c'est qu'on sait donner un budget fixe, au forfait, que l'on va tenir, y compris avec les 3 ans de garantie... c'est un argument auxquels les clients ne peuvent que rarement résister et qui leur font oublier le C++, java et autres saletés.

    En revanche, il y a un <gros> effort et invistissement à la mise en place, pour la mise en place d'une architecture logicielle qui peut être générée (c'est plutôt bien, cela force les bonnes pratiques d'architecture, mais il y a un gros travail sur l'existant...), écrire les processus adaptés, former les équipes, y compris le marketing et l'avant-vente, et adapter le générateur au type de logiciel à écrire, et à la documentation support à générer également. Il y a également de nombreux autres outils et méthodes qui contribuent à la productivité, comme par exemple l'outil qui mesure la dette technique (que je préfère appeler l'entropie logicielle), les outils de couverture des tests, l'outil de gestion de la bibliothèque des composants réutilisables, etc... J'appelle l'ensemble la "Chaîne de Fabrication Logicielle". Par exemple, j'ai investi plus de 25 000 € dans ma propre chaîne.

    Et il y a toujours des applications qui ne se prêtent pas bien à la génération de sources, c'est au cas par cas qu'il faut voir si c'est possible.

  13. #353
    Membre régulier
    Inscrit en
    Décembre 2004
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 123
    Points : 97
    Points
    97
    Par défaut Pas de volontaires pour faire l'équivalent du composant NumberToLetter?
    Alors,
    pas de volontaires? Personne ne se sent capable de relever le gant?
    J'ai tout donné dans les composants que j'ai fournis, les exigences, la conception, les sources, les tests, l'aide-en-ligne, le temps passé, les différentes tâches. Qui va être capable de faire mieux, à la fois en rapidité de mise au point, en vitesse de compilation, en qualité logicielle, en lisibilité, en documentation, en sûreté de fonctionnement?

    Personne pour trouver mes erreurs? Elles doivent être nombreuses, je n'utilise pas cet acmé de l'informatique, le fameux langage C++ créé par le non-moins fameux Stroustrup, qu'il soit loué ;-)

    Le C++, c'est à la mode, mais quand on vous propose un défi ...

    Cdt
    ThierryC

  14. #354
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Bonjour,

    J'avoue que faute de temps et ayant d'autres choses avec lesquelles jouer en ce moment, je passe mon tour pour ce qui est de chercher à comprendre ce que fait/doit-faire le programme pour en faire une version C++. J'avoue aussi que si le code avait été directement navigable sur une plateforme type github plutôt qu'une archive, j'aurai plus facilement jeté un oeil. ^^'
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  15. #355
    Expert confirmé Avatar de AoCannaille
    Inscrit en
    Juin 2009
    Messages
    1 413
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 1 413
    Points : 4 734
    Points
    4 734
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    J'avoue aussi que si le code avait été directement navigable sur une plateforme type github plutôt qu'une archive, j'aurai plus facilement jeté un oeil. ^^'
    +1, ton site d’hébergement est bloqué par le proxy de ma boite...

  16. #356
    Membre régulier
    Inscrit en
    Décembre 2004
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 123
    Points : 97
    Points
    97
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Bonjour,

    J'avoue que faute de temps et ayant d'autres choses avec lesquelles jouer en ce moment, je passe mon tour pour ce qui est de chercher à comprendre ce que fait/doit-faire le programme pour en faire une version C++. J'avoue aussi que si le code avait été directement navigable sur une plateforme type github plutôt qu'une archive, j'aurai plus facilement jeté un oeil. ^^'
    Moi, j'ai bien passé le temps nécessaire pour comprendre le C++ d'origine du premier défi. Et réaliser de bien meilleurs composants. L'argument du manque de temps est bien pauvre. Par ailleurs, j'ai bien indiqué que l'ensemble des exigences étaient déjà documentées. Donc aucune difficulté de ce côté là, Prétexte. Difficulté d'extraire une archive, Prétexte.

    Ceci dit, je comprends bien que les différentes obligations IRL peuvent prendre tout votre temps. Et je respecte votre décision. Mais je trouve regrettable qu'il n'y ait aucun autre valeureux défenseur du C++ qui vienne mettre en œuvre ce qu'il préconise ...

  17. #357
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Juste autre chose à faire que batailler après un truc peu ergonomique à manipuler: 19Mo de tarball après compression et des répertoires dans tous les sens et même pas un README pour dire clairement d'où on part et où on va -- le truc après lequel je râle sur beaucoup trop de projets libres: l'absence d'une présentation succincte et facile d'accès qui donne envie de regarder plus en détails.

    Ce que je suis prêt à faire professionnellement, je ne le fais pas juste pour le plaisir ou le défi ou que sais-je encore.

    Certes j'ai survolé la discussion dernièrement, mais un code C++ avait déjà été fourni, non? Qu'est-ce qui change ? L'ajout de langues ? Des TU ?
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  18. #358
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 107
    Points
    6 107
    Par défaut
    Je n'ai pas non plus le temps de refaire la même chose en C++.
    Par contre, j'ai le temps de publier ici une adaptation d'un code que j'avais écrit en fin 2017.

    ScripteurNombreFrancais.h :
    Code cpp : 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
    47
    48
    49
    50
    51
    52
    #ifndef INCLUDE__PYRAMIDEV__SCRIPTEUR_NOMBRE_FRANCAIS__H
    #define INCLUDE__PYRAMIDEV__SCRIPTEUR_NOMBRE_FRANCAIS__H
     
    #include <string>
     
    namespace pyramidev {
     
    //! \brief  Scripteur de nombres en lettres en français en UTF8.
    //! \author Pyramidev
    //!
    //! Par exemple, pyramidev::ScripteurNombreFrancais{}(42) retourne la chaîne u8"quarante-deux".
    //! \n\n
    //! Références :
    //! - http://www.academie-francaise.fr/questions-de-langue#57_strong-em-nombres-criture-lecture-accord-em-strong
    //! - http://www.alsace.iufm.fr/espace.personnel.dominique.pernoux/web/ressource_1/page_ecriture.htm
    //!
    class ScripteurNombreFrancais final {
    public:
    	constexpr ScripteurNombreFrancais() noexcept :
    		m_adjNumOrdinal{false},
    		m_tiretsPartout{false},
    		m_septanteHuitanteNonante{false}
    	{}
    	//! Explication : En français, on écrit "huit cents ans" mais "l'an huit cent".
    	//! Dans le deuxième cas, il s'agit d'un adjectif numéral ordinal.
    	constexpr ScripteurNombreFrancais& modeAdjectifNumeralOrdinal() noexcept {
    		m_adjNumOrdinal = true;
    		return *this;
    	}
    	constexpr ScripteurNombreFrancais& appliquerRectifications1990() noexcept {
    		m_tiretsPartout = true;
    		return *this;
    	}
    	constexpr ScripteurNombreFrancais& autoriserSeptanteHuitanteEtNonante() noexcept {
    		m_septanteHuitanteNonante = true;
    		return *this;
    	}
    	std::string operator()(int                nombre) const;
    	std::string operator()(unsigned           nombre) const;
    	std::string operator()(long               nombre) const;
    	std::string operator()(unsigned long      nombre) const;
    	std::string operator()(long long          nombre) const;
    	std::string operator()(unsigned long long nombre) const;
    private:
    	bool m_adjNumOrdinal;           //!< Ex : u8"huit cent" au lieu de u8"huit cents".
    	bool m_tiretsPartout;           //!< Ex : u8"moins-cent-vingt-trois" au lieu de u8"moins cent vingt-trois".
    	bool m_septanteHuitanteNonante; //!< Ex : u8"septante" au lieu de u8"soixante-dix".
    };
     
    } // namespace pyramidev
     
    #endif

    ScripteurNombreFrancais.cpp :
    Code cpp : 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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    #include "pyramidev/ScripteurNombreFrancais.h"
     
    #include <algorithm>
    #include <cassert>
    #include <limits>
    #include <stdexcept>
    #include <string>
     
    namespace pyramidev {
     
    namespace {
     
    	constexpr unsigned cEXPOSANT_MAXIMAL_DE_PUISSANCE_DE_MILLE = 6;
     
    	constexpr unsigned partieEntiereLog1000(uintmax_t nombre)
    	{
    		unsigned resultat = 0;
    		while(nombre >= 1000) {
    			nombre /= 1000;
    			++resultat;
    		}
    		return resultat;
    	}
     
    	constexpr uintmax_t puissance(uintmax_t nombre, unsigned exposant)
    	{
    		assert(nombre != 0 || exposant != 0);
    		uintmax_t resultat = 1;
    		for(unsigned k = 0; k < exposant; ++k)
    			resultat *= nombre;
    		return resultat;
    	}
     
    	template<class TypeEntier>
    	std::string versUtf8(
    		TypeEntier nombre, bool adjNumOrdinal, bool tiretsPartout, bool septanteHuitanteNonante);
     
    	std::string convertirNombrePositifEnChaineFrancaiseUtf8(
    		uintmax_t nombre, bool adjNumOrdinal, bool septanteHuitanteNonante);
     
    	std::string chaineNombreEntre1Et999Fois1000Puissance(
    		unsigned nombre, unsigned exposant, bool adjNumOrdinal, bool septanteHuitanteNonante);
     
    	std::string chaineNombreEntre1Et999(unsigned nombre, bool adjNumOrdinal, bool septanteHuitanteNonante);
    	std::string chaineNombreEntre1Et99 (unsigned nombre, bool adjNumOrdinal, bool septanteHuitanteNonante);
    	constexpr char const* motDe1000Puissance(unsigned exposant);
    	constexpr char const* motDe10FoisFacteurEntre1Et9(unsigned facteur);
    	constexpr char const* chaineNombreEntre1Et19(unsigned nombre);
    	constexpr char const* motDeChiffre(unsigned chiffre);
    }
     
    std::string ScripteurNombreFrancais::operator()(int nombre) const {
    	return versUtf8(nombre, m_adjNumOrdinal, m_tiretsPartout, m_septanteHuitanteNonante);
    }
    std::string ScripteurNombreFrancais::operator()(unsigned nombre) const {
    	return versUtf8(nombre, m_adjNumOrdinal, m_tiretsPartout, m_septanteHuitanteNonante);
    }
    std::string ScripteurNombreFrancais::operator()(long nombre) const {
    	return versUtf8(nombre, m_adjNumOrdinal, m_tiretsPartout, m_septanteHuitanteNonante);
    }
    std::string ScripteurNombreFrancais::operator()(unsigned long nombre) const {
    	return versUtf8(nombre, m_adjNumOrdinal, m_tiretsPartout, m_septanteHuitanteNonante);
    }
    std::string ScripteurNombreFrancais::operator()(long long nombre) const {
    	return versUtf8(nombre, m_adjNumOrdinal, m_tiretsPartout, m_septanteHuitanteNonante);
    }
    std::string ScripteurNombreFrancais::operator()(unsigned long long nombre) const {
    	return versUtf8(nombre, m_adjNumOrdinal, m_tiretsPartout, m_septanteHuitanteNonante);
    }
     
    namespace {
     
    	template<class TypeEntier>
    	std::string versUtf8(
    		TypeEntier nombre, bool adjNumOrdinal, bool tiretsPartout, bool septanteHuitanteNonante)
    	{
    		static_assert(std::numeric_limits<TypeEntier>::is_integer);
    		std::string resultat{};
    		if(nombre >= 0) {
    			resultat = convertirNombrePositifEnChaineFrancaiseUtf8(nombre, adjNumOrdinal, septanteHuitanteNonante);
    		} else {
    			auto const nombrePlusUn = nombre + 1; // pour pouvoir calculer l'opposé sans overflow
    			auto const nombreOppose = static_cast<uintmax_t>(-nombrePlusUn) + UINTMAX_C(1);
    			resultat = u8"moins " +
    				convertirNombrePositifEnChaineFrancaiseUtf8(nombreOppose, adjNumOrdinal, septanteHuitanteNonante);
    		}
    		if(tiretsPartout)
    			std::replace(resultat.begin(), resultat.end(), u8' ', u8'-');
    		assert(!resultat.empty());
    		return resultat;
    	}
     
    	std::string convertirNombrePositifEnChaineFrancaiseUtf8(
    		uintmax_t nombre, bool adjNumOrdinal, bool septanteHuitanteNonante)
    	{
    		if(nombre == 0)
    			return motDeChiffre(0);
     
    		unsigned const exposantMaximal = partieEntiereLog1000(nombre);
    			// Ex : exposantMaximal == 2 ssi nombre >= 1'000'000 && nombre < 1'000'000'000.
     
    		{
    			constexpr unsigned exposantMaximalMaximal =
    				partieEntiereLog1000(std::numeric_limits<uintmax_t>::max());
    			static_assert(exposantMaximalMaximal <= cEXPOSANT_MAXIMAL_DE_PUISSANCE_DE_MILLE);
    				// pour assurer la précondition de chaineNombreEntre1Et999Fois1000Puissance
    		}
     
    		std::string resultat{};
     
    		for(unsigned offset = 0; offset <= exposantMaximal; ++offset)
    		{
    			unsigned const exposant = exposantMaximal - offset;
     
    			auto const centainesDizainesEtUnites = static_cast<unsigned>(
    				(nombre / puissance(1000, exposant)) % 1000
    			);
     
    			// Exemple avec nombre == 12'003'450 :
    			// - Si exposant == 2, alors centainesDizainesEtUnites == 12
    			//   et on ajoute u8"douze millions" dans le résultat.
    			// - Si exposant == 1, alors centainesDizainesEtUnites == 3
    			//   et on ajoute u8" trois mille" dans le résultat.
    			// - Si exposant == 0, alors centainesDizainesEtUnites == 450
    			//   et on ajoute u8" quatre cent cinquante" dans le résultat.
     
    			if(centainesDizainesEtUnites >= 1)
    			{
    				if(!resultat.empty())
    					resultat += u8' ';
    				resultat += chaineNombreEntre1Et999Fois1000Puissance(
    					centainesDizainesEtUnites, exposant, adjNumOrdinal, septanteHuitanteNonante
    				);
    			}
    		}
     
    		assert(!resultat.empty());
    		return resultat;
    	}
     
    	//! Exemple avec nombre == 300 :
    	//! - Si exposant == 0, alors on retourne u8"trois cents" ou u8"trois cent".
    	//! - Si exposant == 1, alors on retourne u8"trois cent mille".
    	//! - Si exposant == 2, alors on retourne u8"trois cents millions".
    	//!
    	std::string chaineNombreEntre1Et999Fois1000Puissance(
    		unsigned nombre, unsigned exposant, bool adjNumOrdinal, bool septanteHuitanteNonante)
    	{
    		assert(nombre >= 1);
    		assert(nombre <= 999);
    		assert(exposant <= cEXPOSANT_MAXIMAL_DE_PUISSANCE_DE_MILLE);
    			// car précondition de motDe1000Puissance
    		std::string resultat{};
    		switch(exposant) {
    			case 0:
    				resultat = chaineNombreEntre1Et999(nombre, adjNumOrdinal, septanteHuitanteNonante);
    				break;
    			case 1:
    				if(nombre >= 2) {
    					adjNumOrdinal = true;
    					resultat = chaineNombreEntre1Et999(nombre, adjNumOrdinal, septanteHuitanteNonante);
    					resultat += u8' ';
    				}
    				resultat += motDe1000Puissance(1);
    				break;
    			default:
    				adjNumOrdinal = false;
    				resultat = chaineNombreEntre1Et999(nombre, adjNumOrdinal, septanteHuitanteNonante);
    				resultat += u8' ';
    				resultat += motDe1000Puissance(exposant);
    				if(nombre >= 2)
    					resultat += u8's';
    		}
    		assert(!resultat.empty());
    		return resultat;
    	}
     
    	std::string chaineNombreEntre1Et999(unsigned nombre, bool adjNumOrdinal, bool septanteHuitanteNonante)
    	{
    		assert(nombre >= 1);
    		assert(nombre <= 999);
    		unsigned const centaines        = nombre / 100;
    		unsigned const dizainesEtUnites = nombre % 100;
    		std::string resultat{};
    		if(centaines >= 1) {
    			if(centaines == 1) {
    				resultat = u8"cent";
    			} else {
    				resultat = motDeChiffre(centaines);
    				resultat += u8" cent";
    				if(!adjNumOrdinal && dizainesEtUnites == 0)
    					resultat += u8's';
    			}
    		}
    		if(dizainesEtUnites >= 1) {
    			if(!resultat.empty())
    				resultat += u8' ';
    			resultat += chaineNombreEntre1Et99(dizainesEtUnites, adjNumOrdinal, septanteHuitanteNonante);
    		}
    		assert(!resultat.empty());
    		return resultat;
    	}
     
    	std::string chaineNombreEntre1Et99(unsigned nombre, bool adjNumOrdinal, bool septanteHuitanteNonante)
    	{
    		assert(nombre >= 1);
    		assert(nombre <= 99);
    		std::string resultat{};
    		if(nombre <= 19) {
    			resultat = chaineNombreEntre1Et19(nombre);
    		} else if(nombre <= 69 || septanteHuitanteNonante) {
    			unsigned const dizaines = nombre / 10;
    			unsigned const unites   = nombre % 10;
    			resultat = motDe10FoisFacteurEntre1Et9(dizaines);
    			if(unites >= 1) {
    				if(unites == 1) {
    					resultat += u8" et un";
    				} else {
    					resultat += u8'-';
    					resultat += motDeChiffre(unites);
    				}
    			}
    		} else if(nombre <= 79) {
    			resultat = motDe10FoisFacteurEntre1Et9(6);
    			resultat += (nombre == 71) ? u8" et " : u8"-";
    			resultat += chaineNombreEntre1Et19(nombre - 60);
    		} else {
    			resultat = u8"quatre-vingt";
    			if(nombre == 80) {
    				if(!adjNumOrdinal)
    					resultat += u8's';
    			} else {
    				resultat += u8'-';
    				resultat += chaineNombreEntre1Et19(nombre - 80);
    			}
    		}
    		assert(!resultat.empty());
    		return resultat;
    	}
     
    	constexpr char const* motDe1000Puissance(unsigned exposant)
    	{
    		assert(exposant >= 1);
    		assert(exposant <= cEXPOSANT_MAXIMAL_DE_PUISSANCE_DE_MILLE);
    		static_assert(6 >= cEXPOSANT_MAXIMAL_DE_PUISSANCE_DE_MILLE);
    		switch(exposant) {
    			case 1: return u8"mille";
    			case 2: return u8"million";
    			case 3: return u8"milliard";
    			case 4: return u8"billion";
    			case 5: return u8"billiard";
    			case 6: return u8"trillion";
    			default:
    				throw std::logic_error(u8"unreachable code");
    		}
    	}
     
    	constexpr char const* motDe10FoisFacteurEntre1Et9(unsigned facteur)
    	{
    		assert(facteur >= 1);
    		assert(facteur <= 9);
    		switch(facteur) {
    			case 1: return chaineNombreEntre1Et19(10);
    			case 2: return u8"vingt";
    			case 3: return u8"trente";
    			case 4: return u8"quarante";
    			case 5: return u8"cinquante";
    			case 6: return u8"soixante";
    			case 7: return u8"septante";
    			case 8: return u8"huitante";
    			case 9: return u8"nonante";
    			default:
    				throw std::logic_error(u8"unreachable code");
    		}
    	}
     
    	constexpr char const* chaineNombreEntre1Et19(unsigned nombre)
    	{
    		assert(nombre >= 1);
    		assert(nombre <= 19);
    		if(nombre >= 1 && nombre <= 9)
    			return motDeChiffre(nombre);
    		switch(nombre) {
    			case 10: return u8"dix";
    			case 11: return u8"onze";
    			case 12: return u8"douze";
    			case 13: return u8"treize";
    			case 14: return u8"quatorze";
    			case 15: return u8"quinze";
    			case 16: return u8"seize";
    			case 17: return u8"dix-sept";
    			case 18: return u8"dix-huit";
    			case 19: return u8"dix-neuf";
    			default:
    				throw std::logic_error(u8"unreachable code");
    		}
    	}
     
    	constexpr char const* motDeChiffre(unsigned chiffre)
    	{
    		assert(chiffre <= 9);
    		switch(chiffre) {
    			case 0: return u8"zéro";
    			case 1: return u8"un";
    			case 2: return u8"deux";
    			case 3: return u8"trois";
    			case 4: return u8"quatre";
    			case 5: return u8"cinq";
    			case 6: return u8"six";
    			case 7: return u8"sept";
    			case 8: return u8"huit";
    			case 9: return u8"neuf";
    			default:
    				throw std::logic_error(u8"unreachable code");
    		}
    	}
    }
     
    } // namespace pyramidev

    ScripteurNombreFrancaisTest.cpp :
    Code cpp : 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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Weffc++"
    #pragma GCC diagnostic ignored "-Wold-style-cast"
    #pragma GCC diagnostic ignored "-Woverloaded-virtual"
    #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
    # include <boost/test/unit_test.hpp>
    #pragma GCC diagnostic pop
     
    #include "pyramidev/ScripteurNombreFrancais.h"
     
    #include <cstdint>
     
    BOOST_AUTO_TEST_SUITE(ScripteurNombreFrancaisTest_testSuite)
     
    BOOST_AUTO_TEST_CASE(Test_signeVariable_tiretsVariables)
    {
    	for(bool adjNumOrdinal : {true, false}) {
    	for(bool tiretsPartout : {true, false}) {
    	for(bool septanteHuitanteNonante : {true, false}) {
    	BOOST_TEST_CONTEXT("adjNumOrdinal == " << (adjNumOrdinal ? "true" : "false")) {
    	BOOST_TEST_CONTEXT("tiretsPartout == " << (tiretsPartout ? "true" : "false")) {
    	BOOST_TEST_CONTEXT("septanteHuitanteNonante == " << (septanteHuitanteNonante ? "true" : "false")) {
     
    		pyramidev::ScripteurNombreFrancais convert{};
    		if(adjNumOrdinal)
    			convert.modeAdjectifNumeralOrdinal();
    		if(tiretsPartout)
    			convert.appliquerRectifications1990();
    		if(septanteHuitanteNonante)
    			convert.autoriserSeptanteHuitanteEtNonante();
     
    		BOOST_TEST(convert(0)  == u8"zéro");
    		BOOST_TEST(convert(0U) == u8"zéro");
    		BOOST_TEST(convert(1)  == u8"un");
    		BOOST_TEST(convert(1U) == u8"un");
    		if(tiretsPartout) {
    			BOOST_TEST(convert(-1)     == u8"moins-un");
    			BOOST_TEST(convert(54321)  == u8"cinquante-quatre-mille-trois-cent-vingt-et-un");
    			BOOST_TEST(convert(54321U) == u8"cinquante-quatre-mille-trois-cent-vingt-et-un");
    			BOOST_TEST(convert(-54321) == u8"moins-cinquante-quatre-mille-trois-cent-vingt-et-un");
    		} else {
    			BOOST_TEST(convert(-1)     == u8"moins un");
    			BOOST_TEST(convert(54321)  == u8"cinquante-quatre mille trois cent vingt et un");
    			BOOST_TEST(convert(54321)  == u8"cinquante-quatre mille trois cent vingt et un");
    			BOOST_TEST(convert(-54321) == u8"moins cinquante-quatre mille trois cent vingt et un");
    		}
    	}
    	}
    	}
    	}
    	}
    	}
    }
     
    BOOST_AUTO_TEST_CASE(Test_nombresPositifs_tiretsNormaux)
    {
    	for(bool adjNumOrdinal           : {true, false}) {
    	for(bool septanteHuitanteNonante : {true, false}) {
    	BOOST_TEST_CONTEXT("adjNumOrdinal == " << (adjNumOrdinal ? "true" : "false")) {
    	BOOST_TEST_CONTEXT("septanteHuitanteNonante == " << (septanteHuitanteNonante ? "true" : "false")) {
     
    		pyramidev::ScripteurNombreFrancais convert{};
    		if(adjNumOrdinal)
    			convert.modeAdjectifNumeralOrdinal();
    		if(septanteHuitanteNonante)
    			convert.autoriserSeptanteHuitanteEtNonante();
     
    		BOOST_TEST(convert(0)  == u8"zéro");
    		BOOST_TEST(convert(1)  == u8"un");
    		BOOST_TEST(convert(2)  == u8"deux");
    		BOOST_TEST(convert(3)  == u8"trois");
    		BOOST_TEST(convert(4)  == u8"quatre");
    		BOOST_TEST(convert(5)  == u8"cinq");
    		BOOST_TEST(convert(6)  == u8"six");
    		BOOST_TEST(convert(7)  == u8"sept");
    		BOOST_TEST(convert(8)  == u8"huit");
    		BOOST_TEST(convert(9)  == u8"neuf");
    		BOOST_TEST(convert(10) == u8"dix");
    		BOOST_TEST(convert(11) == u8"onze");
    		BOOST_TEST(convert(12) == u8"douze");
    		BOOST_TEST(convert(13) == u8"treize");
    		BOOST_TEST(convert(14) == u8"quatorze");
    		BOOST_TEST(convert(15) == u8"quinze");
    		BOOST_TEST(convert(16) == u8"seize");
    		BOOST_TEST(convert(17) == u8"dix-sept");
    		BOOST_TEST(convert(18) == u8"dix-huit");
    		BOOST_TEST(convert(19) == u8"dix-neuf");
    		BOOST_TEST(convert(20) == u8"vingt");
    		BOOST_TEST(convert(21) == u8"vingt et un");
    		BOOST_TEST(convert(22) == u8"vingt-deux");
    		BOOST_TEST(convert(29) == u8"vingt-neuf");
    		BOOST_TEST(convert(30) == u8"trente");
    		BOOST_TEST(convert(31) == u8"trente et un");
    		BOOST_TEST(convert(32) == u8"trente-deux");
    		BOOST_TEST(convert(39) == u8"trente-neuf");
    		BOOST_TEST(convert(40) == u8"quarante");
    		BOOST_TEST(convert(41) == u8"quarante et un");
    		BOOST_TEST(convert(42) == u8"quarante-deux");
    		BOOST_TEST(convert(49) == u8"quarante-neuf");
    		BOOST_TEST(convert(50) == u8"cinquante");
    		BOOST_TEST(convert(51) == u8"cinquante et un");
    		BOOST_TEST(convert(52) == u8"cinquante-deux");
    		BOOST_TEST(convert(59) == u8"cinquante-neuf");
    		BOOST_TEST(convert(60) == u8"soixante");
    		BOOST_TEST(convert(61) == u8"soixante et un");
    		BOOST_TEST(convert(62) == u8"soixante-deux");
    		BOOST_TEST(convert(69) == u8"soixante-neuf");
    		if(septanteHuitanteNonante) {
    			BOOST_TEST(convert(70) == u8"septante");
    			BOOST_TEST(convert(71) == u8"septante et un");
    			BOOST_TEST(convert(72) == u8"septante-deux");
    			BOOST_TEST(convert(79) == u8"septante-neuf");
    			BOOST_TEST(convert(80) == u8"huitante");
    			BOOST_TEST(convert(81) == u8"huitante et un");
    			BOOST_TEST(convert(82) == u8"huitante-deux");
    			BOOST_TEST(convert(89) == u8"huitante-neuf");
    			BOOST_TEST(convert(90) == u8"nonante");
    			BOOST_TEST(convert(91) == u8"nonante et un");
    			BOOST_TEST(convert(92) == u8"nonante-deux");
    			BOOST_TEST(convert(99) == u8"nonante-neuf");
    		} else {
    			BOOST_TEST(convert(70) == u8"soixante-dix");
    			BOOST_TEST(convert(71) == u8"soixante et onze");
    			BOOST_TEST(convert(72) == u8"soixante-douze");
    			BOOST_TEST(convert(79) == u8"soixante-dix-neuf");
    			BOOST_TEST(convert(80) == (adjNumOrdinal ? u8"quatre-vingt" : u8"quatre-vingts"));
    			BOOST_TEST(convert(81) == u8"quatre-vingt-un");
    			BOOST_TEST(convert(82) == u8"quatre-vingt-deux");
    			BOOST_TEST(convert(89) == u8"quatre-vingt-neuf");
    			BOOST_TEST(convert(90) == u8"quatre-vingt-dix");
    			BOOST_TEST(convert(91) == u8"quatre-vingt-onze");
    			BOOST_TEST(convert(92) == u8"quatre-vingt-douze");
    			BOOST_TEST(convert(99) == u8"quatre-vingt-dix-neuf");
    		}
    		BOOST_TEST(convert(100) == u8"cent");
    		BOOST_TEST(convert(101) == u8"cent un");
    		BOOST_TEST(convert(199) == (septanteHuitanteNonante ? u8"cent nonante-neuf"
    		                                          : u8"cent quatre-vingt-dix-neuf"));
    		BOOST_TEST(convert(200) == (adjNumOrdinal ? u8"deux cent" : u8"deux cents"));
    		BOOST_TEST(convert(201) == u8"deux cent un");
    		BOOST_TEST(convert(900) == (adjNumOrdinal ? u8"neuf cent" : u8"neuf cents"));
    		BOOST_TEST(convert(980) == (septanteHuitanteNonante ? u8"neuf cent huitante" :
    		                            adjNumOrdinal ?           u8"neuf cent quatre-vingt" :
    		                                                      u8"neuf cent quatre-vingts"));
    		BOOST_TEST(convert(999) == (septanteHuitanteNonante ? u8"neuf cent nonante-neuf" :
    		                                                      u8"neuf cent quatre-vingt-dix-neuf"));
    		BOOST_TEST(convert(1000) == u8"mille");
    		BOOST_TEST(convert(1001) == u8"mille un");
    		BOOST_TEST(convert(1999) == (septanteHuitanteNonante ? u8"mille neuf cent nonante-neuf" :
    		                                                       u8"mille neuf cent quatre-vingt-dix-neuf"));
    		BOOST_TEST(convert(2000) == u8"deux mille");
    		BOOST_TEST(convert(2001) == u8"deux mille un");
    		BOOST_TEST(convert(900'900L) == (adjNumOrdinal ? u8"neuf cent mille neuf cent" :
    		                                                 u8"neuf cent mille neuf cents"));
    		BOOST_TEST(convert(1'000'000L) == u8"un million");
    		BOOST_TEST(convert(1'000'001L) == u8"un million un");
    		BOOST_TEST(convert(1'001'000L) == u8"un million mille");
    		BOOST_TEST(convert(1'001'001L) == u8"un million mille un");
    		BOOST_TEST(convert(2'000'000L) == u8"deux millions");
    		BOOST_TEST(convert(2'000'001L) == u8"deux millions un");
    		BOOST_TEST(convert(200'200'200L) == (
    			adjNumOrdinal ? u8"deux cents millions deux cent mille deux cent" :
    			                u8"deux cents millions deux cent mille deux cents"
    		));
    		BOOST_TEST(convert(1'000'000'000L) == u8"un milliard");
    		BOOST_TEST(convert(1'000'000'001L) == u8"un milliard un");
    		BOOST_TEST(convert(1'000'001'000L) == u8"un milliard mille");
    		BOOST_TEST(convert(1'001'000'000L) == u8"un milliard un million");
    		BOOST_TEST(convert(2'000'000'000L) == u8"deux milliards");
    		BOOST_TEST(convert(2'000'000'001L) == u8"deux milliards un");
    		BOOST_TEST(convert(1'000'000'000'000UL) == u8"un billion");
    		BOOST_TEST(convert(1'000'000'000'000'000UL) == u8"un billiard");
    		BOOST_TEST(convert(1'000'000'000'000'000'000UL) == u8"un trillion");
    	}
    	}
    	}
    	}
    }
     
    BOOST_AUTO_TEST_CASE(Test_nombresLimites)
    {
    	for(bool adjNumOrdinal : {true, false}) {
    	BOOST_TEST_CONTEXT("adjNumOrdinal == " << (adjNumOrdinal ? "true" : "false")) {
     
    		pyramidev::ScripteurNombreFrancais convert{};
    		if(adjNumOrdinal)
    			convert.modeAdjectifNumeralOrdinal();
     
    // Si un type entier de 32 bits existe...
    #if INT_LEAST32_MAX == INTMAX_C(2'147'483'647)
     
    		static_assert(std::numeric_limits<int32_t>::min() == INT32_C(-2'147'483'648));
    		BOOST_TEST(convert(std::numeric_limits<int32_t>::min()) ==
    			u8"moins deux milliards cent quarante-sept millions "
    			u8"quatre cent quatre-vingt-trois mille six cent quarante-huit");
     
    		static_assert(std::numeric_limits<int32_t>::max() == INT32_C(2'147'483'647));
    		BOOST_TEST(convert(std::numeric_limits<int32_t>::max()) ==
    			u8"deux milliards cent quarante-sept millions "
    			u8"quatre cent quatre-vingt-trois mille six cent quarante-sept");
     
    		static_assert(std::numeric_limits<uint32_t>::max() == UINT32_C(4'294'967'295));
    		BOOST_TEST(convert(std::numeric_limits<uint32_t>::max()) ==
    			u8"quatre milliards deux cent quatre-vingt-quatorze millions "
    			u8"neuf cent soixante-sept mille deux cent quatre-vingt-quinze");
     
    #endif
     
    // Si un type entier de 64 bits existe...
    #if INT_LEAST64_MAX == INTMAX_C(9'223'372'036'854'775'807)
     
    //		static_assert(std::numeric_limits<int64_t>::min() == INT64_C(-9'223'372'036'854'775'808));
    			// Erreur de GCC 7.1.0 : "integer constant is so large that it is unsigned"
     
    		BOOST_TEST(convert(std::numeric_limits<int64_t>::min()) ==
    			u8"moins neuf trillions "
    			u8"deux cent vingt-trois billiards trois cent soixante-douze billions "
    			u8"trente-six milliards huit cent cinquante-quatre millions "
    			u8"sept cent soixante-quinze mille huit cent huit");
     
    		static_assert(std::numeric_limits<int64_t>::max() == INT64_C(9'223'372'036'854'775'807));
    		BOOST_TEST(convert(std::numeric_limits<int64_t>::max()) ==
    			u8"neuf trillions "
    			u8"deux cent vingt-trois billiards trois cent soixante-douze billions "
    			u8"trente-six milliards huit cent cinquante-quatre millions "
    			u8"sept cent soixante-quinze mille huit cent sept");
     
     
    		static_assert(std::numeric_limits<uint64_t>::max() == UINT64_C(18'446'744'073'709'551'615));
    		BOOST_TEST(convert(std::numeric_limits<uint64_t>::max()) ==
    			u8"dix-huit trillions "
    			u8"quatre cent quarante-six billiards sept cent quarante-quatre billions "
    			u8"soixante-treize milliards sept cent neuf millions "
    			u8"cinq cent cinquante et un mille six cent quinze");
     
    #endif
     
    	}
    	}
    }
     
    BOOST_AUTO_TEST_SUITE_END()

    Remarques :
    • Pour convertir un nombre en chaîne, les objets de type ScripteurNombreFrancais s'utilisent avec la même syntaxe que s'ils étaient des fonctions. On peut voir cela comme une interface standard : l'interface des fonctions à un paramètre de type entier qui retournent une chaîne. Passer par une interface standard facilite la réutilisabilité de la classe : si le code appelant attend la même interface, on n'a pas besoin de coder un wrapper pour passer d'une interface à l'autre.
    • L'utilisateur de la classe ScripteurNombreFrancais peut entrer n'importe quel nombre de type int, unsigned, long, unsigned long, long long ou unsigned long long, sans précondition. Bien que les bornes de ces types d'entier dépendent du compilateur et des options de compilation, on vérifie à la compilation que l'implémentation est capable de supporter n'importe lequel de ces nombres, même s'il est aux limites supportées par le type d'entier. Dans le code, ce contrôle est effectué par la ligne :
      Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
      static_assert(exposantMaximalMaximal <= cEXPOSANT_MAXIMAL_DE_PUISSANCE_DE_MILLE);
    • À l'exception du point précédent, dans l'implémentation, les bornes ne sont pas contrôlées à la compilation, mais à l'exécution. En jouant avec les templates, il serait possible de réécrire le code pour que toutes les bornes soient contrôlées à la compilation, mais ce serait au prix de la lisibilité.

  19. #359
    Membre régulier
    Inscrit en
    Décembre 2004
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 123
    Points : 97
    Points
    97
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Juste autre chose à faire que batailler après un truc peu ergonomique à manipuler: 19Mo de tarball après compression et des répertoires dans tous les sens et même pas un README pour dire clairement d'où on part et où on va -- le truc après lequel je râle sur beaucoup trop de projets libres: l'absence d'une présentation succincte et facile d'accès qui donne envie de regarder plus en détails.

    Ce que je suis prêt à faire professionnellement, je ne le fais pas juste pour le plaisir ou le défi ou que sais-je encore.

    Certes j'ai survolé la discussion dernièrement, mais un code C++ avait déjà été fourni, non? Qu'est-ce qui change ? L'ajout de langues ? Des TU ?
    Structure des répertoires:
    1-Summary
    2-Requirements
    3-Design
    4-Sources
    5-Tests
    6-Bin
    7-QA
    8-ProjectMgt
    9-Diary

    Tu as du mal à lire l'anglais?
    As-tu seulement ouvert la fiche résumé qui te donnes tout ce que tu demandes?

    Par rapport au C++:
    - approche composant,
    - un composant métier, et un composant IHM, (ces composants s'installent dans l'IDE automatiquement),
    - type intervalle borné et vérifié statiquement et dynamiquement,
    - nombreuses langues,
    - DSL pour les options : un même chiffre peut être traduit différemment suivant la langue: (genre, declinaison, ordinal, cardinal, etc)
    - tests unitaires,
    - dossier de conception,
    - recueil de toutes les exigences sur le sujet,
    - aide en ligne,
    - assurance qualité, vérification de l'absence de défauts qualité et de dette technique
    - gestion de projet avec toutes les heures et à quoi elles sont passées.

    Un vrai projet, quoi. Quand on ne perd pas de temps sur le source, on a le temps de réaliser ce qui est nécessaire à un projet...

  20. #360
    Membre régulier
    Inscrit en
    Décembre 2004
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 123
    Points : 97
    Points
    97
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    Je n'ai pas non plus le temps de refaire la même chose en C++.
    [...]En jouant avec les templates, il serait possible de réécrire le code pour que toutes les bornes soient contrôlées à la compilation, mais ce serait au prix de la lisibilité.[/LIST]
    Il y a bien une langue, et en plus, l'outil traduit les nombres bien au-delà de 100. Intéressant. Les tests unitaires sont présents, c'est bien.

    Manque le reste, toutes les autres langues, la capacité d'adaptation aux langues variées, l'IHM. Pas de vérification statique, et s'il y en avait, ce serait au prix de la lisibilité, d'après l'auteur. pas d'assurance qualité. pas de conception ou d'aide en ligne. pas de documentation. Surtout, pas d'approche composant. En tant qu'auditeur, j'aurais recalé ce code, qui ne mérite pas le beau nom de sources...

    Ce n'est donc pas au même niveau.

    Cordialement,
    ThierryC

Discussions similaires

  1. Pourquoi les langages interprétés sont-ils préférés pour l'analyse de données ?
    Par User23 dans le forum Statistiques, Data Mining et Data Science
    Réponses: 1
    Dernier message: 12/05/2016, 21h18
  2. Les langages statiques sont-ils trop sophistiqués et complexes ?
    Par Katleen Erna dans le forum Actualités
    Réponses: 53
    Dernier message: 20/01/2013, 10h06
  3. Réponses: 2
    Dernier message: 11/05/2010, 19h36
  4. Réponses: 2
    Dernier message: 06/05/2007, 22h37
  5. Pourquoi les mails ne sont ils pas envoyés?
    Par Sunsawe dans le forum Développement
    Réponses: 3
    Dernier message: 12/04/2007, 23h49

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