Comment ssortingngifier une expression en C

Existe-t-il un moyen d’évaluer une expression avant la chaîne de caractères en c?

Exemple:

#define ssortingngify(x) #x ... const char * thessortingng = ssortingngify( 10 * 50 ); 

Le problème est que je veux obtenir

 const char * thessortingng = "500"; 

Et pas :

 const char * thessortingng = "10 * 50"; 

Cela peut-il être fait?

Le préprocesseur C ne peut pas faire cela, donc utilisez plutôt snprintf :

 char *ssortingngify(int n) { char *res = malloc(12); snprintf(res, 12, "%d", n); return res; } 

Usage

 const char *thessortingng = ssortingngify(10 * 50); 

NB

Par souci de simplicité, j’ai omis le contrôle des erreurs et free .

Vous n’allez probablement pas aimer le format dans lequel l’expression va être présentée, oui , c’est possible, mais d’une manière très éclectique – vous auriez besoin de créer un langage fonctionnel séparé qui est “exécuté” par le pré-processeur. . La preuve:

 $ cvs -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp login $ cvs -z3 -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp co -P chaos-pp $ cvs -z3 -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp co -P order-pp $ cd order-pp/example $ grep -A 6 'int main' fibonacci.c int main(void) { printf ("The 500th Fibonacci number is " ORDER_PP(8ssortingngize(8to_lit(8fib(8nat(5,0,0))))) ".\n"); return 0; } $ cpp -I../inc fibonacci.c 2>/dev/null | grep -A 6 'int main' int main(void) { printf ("The 500th Fibonacci number is " "139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125" ".\n"); return 0; } 

Dans cet exemple, nous avons un langage purement fonctionnel exécuté par préprocesseur et récemment utilisé, qui est utilisé pour calculer le 500ème nombre de Fibonacci, puis le hiérarchiser pour le donner au compilateur C.

Bien sûr, je doute fort que ce soit quelque chose que vous utiliseriez jamais dans la pratique, et qu’il s’agisse d’un abus très étendu du pré-processeur, mais je considère que c’est un bidouillage qui provoque beaucoup de reflection. (Et oui, sans les rebondissements théoriques exotiques comme celui-ci, ce n’est pas possible).

Je suppose que vous avez plus d’expérience dans les langages de script qu’en C.

Vous devez connaître plusieurs phases avec un langage purement compilé, tel que C: pré-traitement, compilation, création de liens et exécution.

Le préprocesseur est d’abord exécuté. C’est là que votre macro est étendue. À ce stade, son contenu est “10 * 50”. Pas grand chose à faire pour ça.

Une fois le pré-processeur de macro terminé, le compilateur convertit le programme en fichier object.

Une fois que le compilateur a terminé sur chaque fichier source, l’ éditeur de liens intervient et les claque tous ensemble.

Enfin, lorsque votre utilisateur est prêt, il exécute votre programme. Sémantiquement, c’est à ce moment que le 10 * 50 est calculé. (En réalité, la plupart des compilateurs reconnaîtront que ce sera toujours la même valeur et le remplaceront par 500, mais c’est un détail d’implémentation).

Les langages de script aiment brouiller toutes ces lignes afin que je puisse voir où une personne habituée à l’une d’elles pourrait être confuse.

Les macros de préprocesseur sont exécutées avant le compilateur. Par définition, il n’est pas possible de faire exactement ce que vous essayez de faire.

Pour convertir un nombre en chaîne au moment de l’exécution, appelez la fonction itoa , comme itoa :

 char thessortingng[8]; itoa(10 * 50, thessortingng, 10); 

Notez que ce code déclare la thessortingng comme un tableau et non comme un pointeur. Pour plus d’informations, consultez la rubrique C sur la gestion de la mémoire.

Vous devez interpréter la chaîne. C ne fait pas cela seul, cherchez une bibliothèque qui le fera pour vous.

http://expreval.sourceforge.net/ http://www.codeproject.com/KB/library/expreval.aspx

Il y en a d’autres, cherchez google.

Vous pouvez écrire un script (perl?) À utiliser comme préprocesseur qui reconnaît les chaînes à évaluer, les évalue et appelle ensuite le vrai cpp du fichier “évalué”.

Peut-être que ça pourrait marcher.

Comme les autres réponses l’ont dit, cela ne peut pas être fait avec le pré-processeur C. C’est l’une des nombreuses faiblesses de C résolues par C ++. C’est le genre de chose qui peut être accomplie de manière très élégante en utilisant la métaprogrammation des modèles.

Pour calculer une expression arithmétique au moment de la compilation:

 #include  namespace mpl = boost::mpl; int main(int argc, char *argv[]) { const int n = mpl::multiplies, mpl::int_<50> >::value; return 0; } 

Voici une métafonction de formatage de chaîne trouvée dans les archives de la liste de diffusion boost. Cette version convertira un int (comme celui calculé ci-dessus) en chaîne dans la base de votre choix:

 #include  #include  #include  #include  #include  #include  #include  #include  namespace mpl = boost::mpl; struct itoa_ct { // radix for _itoa() goes up to 36, but only bother with 16 here typedef mpl::vector_c radix_t; template  struct radix_convert { typedef typename mpl::push_back< typename radix_convert::type , mpl::char_::type::value> >::type type; }; template  struct radix_convert { typedef mpl::ssortingng<> type; }; template  struct apply { // All bases != 10 consider I as unsigned typedef typename radix_convert< Radix, static_cast((Radix == 10 && I < 0) ? -I : I) >::type converted_t; // Prefix with '-' if negative and base 10 typedef typename mpl::if_< mpl::bool_<(Radix == 10 && I < 0)> , mpl::push_front > , mpl::identity >::type::type type; }; }; 

En réunissant les deux, votre expression devient:

 const char *thessortingng = mpl::c_str, mpl::int_<50> >::value>::type>::value; 

… et tout cela ne devient rien de plus qu’une chaîne constante “500” lors de la compilation 🙂