C a-t-il des outils pour faire de l’ajout de ficelle?

Je fais une fonction qui retourne la dérivée d’une fonction qui est représentée comme un arbre comme

/ + \ * ^ / \ / \ x 5 3.14 x 

avec des noeuds de la forme

 typedef struct node { char * fx; // function struct node * gx; // left-hand side char * op; // operator struct node * hx; // right-hand side } node; 

Si un nœud n’a pas d’enfant, par exemple x , 5 , 3.14 dans l’exemple ci-dessus, alors op , gx et hx sont NULL et sinon fx est NULL .

Ma fonction de calcul de la dérivée ressemble à

 char * deriveFromTree ( node * rt ) { char * buff = malloc(100*sizeof(char)); int curBuffIdx = 0; if (rt->op) // if rt is of the form rt = gx op hx { char * dgdx = deriveFromTree(rt->gx); // g'(x) char * dhdx = deriveFromTree(rt->hx); // h'(x) char thisop = *rt->op; if (thisop == '+' || thisop == '-') { // ... want to do equivalent of // buff = dgdx + thisop + dhdx } else if (thisop == '*') { // ... } else if (thisop == '/') { // ... } else if (thisop == '^') { // ... } } else // rt is a base expression -- x or a constant { buff[curBuffIdx] = strcmp(rt->fx, 'x') ? '1': '0'; } buff[++curBuffIdx] = '\0'; return buff; } 

mais je me fais trébucher sur toute l’addition de chaîne. Je pourrais créer de toutes pièces un additionneur de corde, s’il existe déjà un moyen compact de faire

  // ... want to do equivalent of // buff = dgdx + thisop + dhdx 

alors j’aimerais utiliser cet outil.

Si votre bibliothèque standard C est GNU ou * BSD, asprintf est probablement disponible. Cependant, vous devrez peut-être activer une macro de test de fonctionnalité pour l’utiliser. Si vous ne disposez pas d’ asprintf , vous pouvez facilement le définir à l’ vsnprintf fonction vsnprintf standard vsnprintf

asprintf renvoie le résultat du format sous forme de chaîne nouvellement allouée (qu’il vous incombe de free ). Pour que vous puissiez écrire, par exemple:

 char* buff; int n = asprintf(&buff, "%s%c%s", dgdx, thisop, dhdx); 

J’utilise généralement une fonction wrapper, qui renvoie la chaîne plutôt que la longueur, vous pouvez donc écrire:

 char* buff = concatf("%s%c%s", dgdx, thisop, dhdx); 

Voici trois implémentations simples; le premier fonctionnera sur des systèmes avec vasprintf ; la seconde sur les systèmes avec Posix vsnprintf ; et le troisième pour Windows, qui implémente apparemment une interface snprintf différente.

 // Version 1, systems which have vasprintf: char* concatf(const char* fmt, ...) { va_list args; char* buf = NULL; va_start(args, fmt); int n = vasprintf(&buf, fmt, args); va_end(args); if (n < 0) { free(buf); buf = NULL; } return buf; } // Version 2: Systems without vasprintf but with vsnprintf char* concatf(const char* fmt, ...) { va_list args; va_start(args, fmt); char* buf = NULL; int n = vsnprintf(NULL, 0, fmt, args); va_end(args); if (n >= 0) { va_start(args, fmt); buf = malloc(n+1); if (buf) vsnprintf(buf, n+1, fmt, args); va_end(args); } return buf; } // Version 3: Windows // Apparently, the implementation of vsnprintf on Windows returns -1 // if not enough space has been provided. So here is the above code // rewritten according to the documentation I found in // https://msdn.microsoft.com/en-us/library/w05tbk72%28VS.71%29.aspx // and // https://msdn.microsoft.com/en-us/library/1kt27hek%28v=vs.71%29.aspx // but totally untested. (If you try it, let me know) char* concatf(const char* fmt, ...) { char* buf = NULL; va_list args; va_start(args, fmt); int n = _vscprintf(fmt, args); va_end(args); if (n >= 0) { va_start(args, fmt); buf = malloc(n+1); if (buf) _vsnprintf(buf, n+1, fmt, args); va_end(args); } return buf; } 

C’est l’équivalent le plus concis que je connaisse des opérateurs de concaténation de chaînes dans d’autres langues. (Ce n’est pas nécessairement le temps d’exécution le plus efficace, mais c’est probablement le temps du programmeur.)

Ce que vous recherchez, c’est une concaténation de chaînes. La fonction standard de la bibliothèque C pour cela est strcat , ou mieux (car sans doute plus sûr) strncat .

Voir http://linux.die.net/man/3/strcat

Ce que vous essayez d’atteindre ne peut pas être fait en clair, car il n’ya pas de surcharge de l’opérateur. Vous pouvez utiliser strncat pour cela, mais strncat qu’il s’agit d’une solution de bas niveau nécessitant de gérer la mémoire manuellement.

Vous pouvez le faire proprement en C ++ en utilisant les objects std::ssortingng ou std::wssortingng , qui ont l’ operator+() approprié operator+() .

Vous pouvez également implémenter votre propre structure de chaîne avec une API appropriée, orientée object.