6
votes

Comment développer dynamiquement une chaîne en c

J'ai une fonction qui rend récursivement certains calculs sur un ensemble de nombres. Je tiens également à imprimer le calcul dans chaque appel de récursivité en faisant passer la chaîne du calcul précédent et en concaténant avec l'opération en cours. Une sortie d'échantillon peut ressembler à ceci:

/**********************************************************************
 * dynamically allocate and append new string to old string and return a pointer to it
 **********************************************************************/
 char * strapp(char * old, char * new)
 {
     // find the size of the string to allocate
     int len = sizeof(char) * (strlen(old) + strlen(new));

     // allocate a pointer to the new string
     char * out = (char*)malloc(len);

     // concat both strings and return
     sprintf(out, "%s%s", old, new);

     return out;
 }

/**********************************************************************
 * returns a pretty math representation of the calculation op
 **********************************************************************/
 char * mathop(char * old, char operand, int num)
 {
     char * output, *newout;
     char fstr[50]; // random guess.. couldn't think of a better way.
     sprintf(fstr, " %c %d", operand, num);
     output = strapp(old, fstr);
     newout = (char*)malloc( 2*sizeof(char)+sizeof(output) );
     sprintf(newout, "(%s)", output);
     free(output);
     return newout;  
 }


void test_mathop()
{
    int i, total = 10;
    char * first = "3";
    printf("in test_mathop\n");
    while (i < total)
    {
        first = mathop(first, "+", i);
        printf("%s\n", first);
        ++i;
    }
}


6 commentaires

La taille de (sortie) vous donnera la taille d'un pointeur. Très différent de SHLEN.


Vous n'avez pas initialisé i !!


Vous devriez probablement supprimer la taille de (char), c'est juste une grande façon d'écrire 1 qui clutters les choses et le pire des cas) ajoute de la confusion.


@Agnel Pourquoi ne les ajoutes-tu pas comme une réponse? Je dirais que vous méritez certains + pour vos observations :-)


@ Péter Török - Je ne me suis pas senti trop confiant à propos de ces réponses. Mais vous avez un point là-bas ...


@ SA125 - Où avez-vous reçu le nom "SA125"? Juste curieux. Une fois, j'ai su 125 sa 125 il y a longtemps ...


4 Réponses :


2
votes

Un problème immédiat que je peux voir est la suivante:

int len = sizeof(char) * (strlen(old) + strlen(new));


3 commentaires

Le NULL CHART est couvert par TIMILOF (CHAR)


@kenny non, ce n'est pas le cas. Testez-le pour vous-même.


@kenny: permet de dire que le vieux est "1" et nouveau est "2". Les deux ont une chaine de 1. Vous voulez maintenant les concaténer dans une seule chaîne. Il devrait accueillir '1', '2' et le '\ 0', pour marquer la fin de la chaîne. Nous avons donc besoin d'un moyen supplémentaire de la somme des longueurs de chaîne.



4
votes

Vous devez allouer un octet supplémentaire pour la terminaison 0.

et vous devez utiliser strlen code> au lieu de Tailleof code> ici: p>

newout = (char*)malloc( 2*sizeof(char)+sizeof(output) );


3 commentaires

Je pensais que Strstr était de trouver une sous-chaîne dans une autre chaîne


Non seulement il doit allouer de l'espace de la traînée \ 0, mais il doit aussi mettre \ 0 là-bas.


@shacharptooth BON POINT En effet, vaut la peine de mentionner explicitement. Bien que strcat le gérerait automatiquement.



2
votes

Essayez ceci, pour commencer: xxx pré>

Ceci est juste votre code, avec un certain nombre de correctifs: p>

  • Les chaînes d'entrée ne sont pas modifiées, elles doivent donc être déclarées const code>. li>
  • ajoutez-en une à la taille requise pour le nouveau tampon, d'avoir de la place pour le terminateur. Li>
  • Les longueurs de chaîne sont mieux stockées dans des variables de type Taille_t code>. Li>
  • Échelle inutile enlevée par Tailleof (Char) Code>. Li>
  • Ne pas lancer le retour de MALLOC () CODE>. LI>
  • Ne définissez pas les fonctions dont le nom commence par STR code>, c'est un espace réservé. Souligné par le commentateur, merci! Li> ul>

    Pour la performance, vous pouvez utiliser le fait que vous appelez strallen () code> sur les deux entrées et évitez d'utiliser sprintf () code>:

    char * append_strings(const char * old, const char * new)
    {
        // find the size of the string to allocate
        const size_t old_len = strlen(old), new_len = strlen(new);
        const size_t out_len = old_len + new_len + 1;
    
        // allocate a pointer to the new string
        char *out = malloc(out_len);
    
        // concat both strings and return
        memcpy(out, old, old_len);
        memcpy(out + old_len, new, new_len + 1);
    
        return out;
    }
    


3 commentaires

C'est techniquement une mauvaise idée de donner un nom de fonctions commençant par "STR".


@sgm Vous avez raison, mais IMO, cela devrait être un commentaire sur la question initiale.


@SGM: Vous avez absolument raison, je vais modifier pour inclure cela comme une amélioration.



0
votes

Merci pour toutes les réponses, elles ont été très utiles - en particulier les suggestions Strcat et découvrons que je devais allouer de l'espace pour le caractère «\ 0». J'ai fini par utiliser Realloc pour "étirer" la chaîne et appendez des caractères principaux et de fin. J'ai également éliminé la fonction Strapp (append_strings) et j'ai tout compris à travailler à l'intérieur de Mathop. Voici comment:

/**********************************************************************
 * returns a pretty math representation of the calculation op
 **********************************************************************/
 char * mathop(char * previous, char operand, float num)
 {
     char *output, *temp, calculation[50];
     size_t newlen;

     // copy the previous data into the temp string     
     temp = (char*)malloc( strlen(previous) + 1 );
     output = (char*)malloc(2);

     strcpy(temp, previous);
     strcpy(output, "(\0");

     // create the string portion to append to the output
     sprintf(calculation, " %c %.1f)\0", operand, num);

     // reallocate the output to append the additional string
     newlen = strlen(temp) + strlen(calculation) + 1;
     temp = realloc(temp, newlen);

     // append the new data to output
     strcat(temp, calculation);
     output = realloc(output, strlen(temp) + 2);
     strcat(output, temp);
     printf("%s\n", output);

     free(temp);
     return output;  
 }


0 commentaires