2010-10-03 2 views
2

C est toujours assez difficile avec les chaînes, mais il est généralement acceptable d'allouer juste un tableau char de taille 256 pour votre chaîne et être avec elle.Renvoyer des chaînes à partir de fonctions dont la longueur est inattendue?

Cependant, que se passe-t-il si vous voulez que la fonction retourne une chaîne et que vous ne connaissiez pas la taille, puisque vous allez concaténer des chaînes ensemble des dizaines ou des centaines de fois? Évidemment quelque chose comme ça ne fonctionnera pas:

char * my_function(int n, char *string){ 
    if (n < 20) { 
     return string; 
    } 
    else { 
     char *new_string = "abcdefghijklmnop"; 
     strcat(string, new_string); 
     return my_function(n--, string); 
    } 
} 

Alors, comment cela est-il géré dans c?

+0

Il est généralement acceptable d'utiliser un tableau de 256 caractères jusqu'à ce qu'il ne va pas bien, et il est alors appelé un débordement de mémoire tampon, ce qui est une mauvaise chose. Ne comptez pas sur de telles hypothèses, ** assurez-vous toujours que vos chaînes tiennent dans la mémoire disponible. – Secure

Répondre

4

La façon la plus simple de faire une fonction qui concatène un nombre arbitraire de chaînes est de:

  1. boucle par toutes les chaînes et additionnent leur strlen().
  2. malloc() pour la longueur totale.
  3. Effectuez toute la concaténation dans la chaîne malloc 'd, puis renvoyez-la.
0

Vous voulez utiliser quelque chose comme ceci:

void my_function (..., char ** result) 
{ 
    // decide how many bytes... 

    // Allocate enough memory. 
    (*result) = malloc(number_of_bytes); 

    // Fill the buffer... 
} 
3

Votre premier paragraphe fait de très mauvaises suppositions. J'espère que tu ne fais pas vraiment ça.

Dans tous les cas, la solution générale consiste à utiliser partout l'allocation dynamique et à la réallouer constamment. Cependant, cela est inefficace, et une meilleure approche peut être de changer l'hypothèse que vous voulez concaténer des chaînes du tout (beaucoup moins de centaines de fois) et au lieu de construire vos chaînes avec snprintf en une seule opération. Ensuite, vous pouvez d'abord calculer la taille requise, et vous avez la possibilité de l'allouer ou simplement d'utiliser un tampon de taille fixe dans lequel la sortie peut être tronquée.

1

Il y a quelques façons courantes que vous pouvez gérer les chaînes retour où la taille ultime est inconnue:

  • vous faire l'appelant responsable de la transmission dans un tampon pour le résultat qui sera assez grand pour contenir la résultat. Si vous faites cela, vous devez exiger que l'appelant transmette également la taille du tampon afin que vous puissiez renvoyer une erreur si le résultat est trop important au lieu de déborder le tampon (par exemple, suivez l'exemple snprintf() au lieu de sprintf() de).

  • vous pouvez allouer la mémoire pour le résultat dynamique, et rendre l'appelant responsable de la libération de la mémoire

Quelques exemples (non testé) pour vous my_function():

#include <string.h> 
#include <stdlib.h> 

/* 
    create new string in a dynamically allocated buffer 
*/ 
char * my_function1(int n, char *s1) 
{ 
    static char const new_string[] = "abcdefghijklmnop"; 

    int sz = strlen(s1) + (n * strlen(new_string)) + 1; 

    char* result = malloc(sz); 

    if (result) { 
     strcpy(result, s1); 

     while (n--) { 
      strcat(result, new_string); 
     } 
    } 

    return result; 
} 


/* 
    create new string in a caller provided buffer 
*/ 
int my_function2(int n, char *s1, char* buf, int buf_size) 
{ 
    static char const new_string[] = "abcdefghijklmnop"; 

    int sz = strlen(s1) + (n * strlen(new_string)) + 1; 

    if (sz > buf_size) { 
     return -1; /* error */ 
    } 

    strcpy(buf, s1); 

    while (n--) { 
     strcat(buf, new_string); 
    } 

    return sz-1; /* characters in result */ 
} 
0

Il y a façon d'ajouter des chaînes de n'importe quelle longueur à votre chaîne d'origine, en utilisant realloc. Vous n'avez pas besoin de connaître la longueur finale de la chaîne ici.

Je suppose que vous pouvez en toute sécurité modifier votre déclaration/initialisation de l'argument passé string dans la fonction appelante soit:

char * string = calloc(0, sizeof(char)); 

Remplacer 0 quel que soit la taille de la chaîne est d'abord, plus 1 pour la fin NULL.

Changer votre fonction:

char * my_function(int n, char *string){ 
    if (n < 20) { 
     return string; 
    } 
    else 
    { 
     char *new_string = "abcdefghijklmnop"; 
     if((temp = realloc(string, strlen(new_string)+ strlen(string) + 1)) == NULL) 
     { 
      printf("Memory allocation error"); 
      exit(1); 
     } 
     strcat(string, new_string); 
     return my_function(n--, string); 
    } 
} 
Questions connexes