12
votes

Comment retourner un tableau à chaîne d'une fonction

char * myFunction () {

    char sub_str[10][20]; 
    return sub_str;

} 

void main () {

    char *str;
    str = myFunction();

}
error:return from incompatible pointer typethanks
c

0 commentaires

9 Réponses :


20
votes

Un tableau de chaîne en C peut être utilisé avec Char ** code> ou avec char * [] code>. Cependant, vous ne pouvez pas retourner des valeurs stockées sur la pile, comme dans votre fonction. Si vous souhaitez renvoyer le tableau de chaîne, vous devez la réserver de manière dynamique:

char** str = myFunction();
printf("%s", str[0]); /* Prints the first string. */


4 commentaires

Donc, la ligne de fonction doit changer en caractères ** mycéens () {?


N'oubliez pas de libérer tous les éléments plus tard (sur la fonction d'appel).


@Diegosevilla ne pouvez-vous pas MALLOC en dehors de la fonction et utilisez l'adresse du pointeur (sur Malloc) comme argument?


@aerijman, bien sûr, c'est une autre possibilité.



2
votes

Raison:
Vous avez besoin du type de retour pour être char (*) [20] . Mais même dans ce cas, vous ne voulez pas retourner un pointeur sur un objet local de la fonction.
Faire:
Utilisez MALLOC pour allouer SUB_STR et retourner Char ** .


0 commentaires

-3
votes
char *f()
{   
    static char str[10][20];

    // ......

    return (char *)str;
}

int main()
{

    char *str;
    str = f();

    printf( "%s\n", str );

    return 0;
}
You can use static instead of malloc. It's your choice.

2 commentaires

C'est un mauvais conseil pour éliminer les plaintes du compilateur. Surtout quand il y a un moyen propre d'écrire le code sans le casting.


Très mauvais conseil et cette ligne est tout simplement fausse: printf (str, "% s \ n");



0
votes

Comme d'autres les ont dit, vous ne pouvez pas retourner une matrice de caractère locale à l'appelant et utiliser la mémoire de tas pour cela.

Cependant, je voudrais NON CONNAISE à l'aide de MALLOC () dans la fonction.

Les bonnes pratiques sont que, quiconque alloue la mémoire , elfeLocates il (et gère la condition d'erreur si malloc () retourne null).

Etant donné que votre MyFunction () n'a pas de contrôle sur la mémoire qu'il a attribué une fois renvoyé, demandez à l'appelant de fournir la mémoire dans laquelle stocker le résultat et transmettez un pointeur sur cette mémoire. < / p>

De cette façon, l'appelant de votre fonction peut désaffecter ou réutiliser la mémoire (par exemple pour appels ultérieurs vers MyFunction () ), mais il voit l'ajustement.

Soyez prudent, cependant, d'être d'accord sur une taille fixe pour ces appels (via une constante globale) ou de transmettre la taille maximale en tant que paramètre supplémentaire, de peur que vous ne finissez pas les limites de tampon d'écrasement.


2 commentaires

Le retour ou le retour de la mémoire allouée est une question de convention. Une convention est une fois que vous avez dit. Un autre consiste à utiliser des pointeurs dynamiques dans la mesure du possible (et STRUP () Strat littéraux), de sorte que le dernier pointeur "utilisateur" sera toujours libéré. À travers elle plus complexe, la convention évite de nombreux tampons débordant de tampon, de dépassant des espaces de pile et beaucoup plus de fil de fil que d'utiliser "statique".


@Vivanium: pointeurs dynamiques en C? Et STRUP () n'est même pas dans la bibliothèque standard ...



8
votes

Pour les programmeurs, le concept d'une "pile" ou du "tas" pourrait être un peu déroutant, surtout si vous avez commencé à programmer dans une langue de niveau supérieur comme Ruby, Java, Python, etc.

Considérons: P>

void i_need_me_some_strings() {
  char **strings = get_me_some_strings();
  while(*strings) {
    printf("a fine string that says: %s", *strings);
    strings++;
  }
}


2 commentaires

Au lieu du MALLOC et Strcpy Pour chaque chaîne, vous pouvez plutôt utiliser STRUP


J'aimerais pouvoir voter ceci plus d'une fois, cela m'a tout simplement sauvé d'une mauvaise erreur de défaillance de segmentation après des jours de se demander quel était le problème. Je n'ai qu'à ajouter que vous devez prendre en compte le caractère null de terminaison de Strcpy . Donc, la ligne to_be_returned [i] = malloc (Tailleof (Char) * Strlen (* Strings)); doit lire: to_be_returne [I] = malloc (Tailleof (Char) * SHLEN ( * Strings) + 1); Notez le + 1 .



2
votes

La cause de votre erreur de compilateur est simple, mais pas la réponse à ce que vous voulez vraiment faire. Vous déclarez que la fonction renvoie un char *, tout en retournant un char * **

sans connaître les détails de ce que vous faites, je vais assumer que l'une des deux choses sont vraies: p> 1) Le but de la fonction est de créer et de retourner une gamme de chaînes. 2) la fonction effectue certaines opérations sur un tableau de chaînes. P>

Si # 1 est vrai, vous avez besoin de plusieurs appels MALLOC pour faire ce travail (cela peut être fait avec seulement deux, mais pour Des objectifs de la simplicité, je vais utiliser plusieurs). P>

Si vous ne savez pas à quel point le tableau est censé être, votre déclaration de fonction devrait ressembler à ceci: P>

void processStrings ( char ** strArray, int numberOfStrings, int strLength );


0 commentaires

1
votes

Comme d'autres disaient correctement, vous devez utiliser une allocation de mémoire dynamique par MALLOC code> pour stocker votre tableau à l'intérieur HEAU CODE> et renvoyer un pointeur sur son premier élément.

aussi je trouve Il est utile d'écrire un tableau simple de la mise en oeuvre de la chaîne code> qui a une API minimale pour la manipulation de données. p>

type et API: strong> P>

array_t*
array_string_new(int array_len, int string_len)
{
  int i;
  char **array_ptr = (char**) malloc(array_len * sizeof(char**));

  for(i = 0; i < array_len; i++) {
    array_ptr[i] = (char*) malloc(string_len * sizeof(char));
  }

  array_t *array = (array_t*) malloc(sizeof(array_t*));
  array->array_ptr = array_ptr;
  array->array_len = array_len;
  array->string_len = string_len;

  return array;
}

int
array_string_set(array_t *array, int index, char *string)
{
  strncpy(array->array_ptr[index], string, array->string_len);
  return 0;
}

char*
array_string_get(array_t *array, int index)
{
  return array->array_ptr[index];
}

int
array_string_len(array_t *array)
{
  return array->array_len;
}

int
array_string_free(array_t *array)
{
  int i;
  for(i = 0; i < array->array_len; i++) {
    free(array->array_ptr[i]);
  }
  free(array->array_ptr);
  return 0;
}


2 commentaires

Merci pour votre squelette pour savoir comment allouer une matrice de chaîne et libérer le tableau de la chaîne. C'est très utile pour moi.


Cette mise en œuvre entraînera une corruption de mémoire due à MALLOC (Tailleof (Array_T *)); il devrait être malloc (taille de (array_t)); (pas d'étoile).



0
votes

J'utilise cette fonction pour diviser une chaîne en matrice de chaîne xxx


1 commentaires

Généralement, les réponses sont beaucoup plus utiles s'ils incluent une explication de ce que le code est destiné à faire et pourquoi cela résout le problème sans introduire d'autres.



-1
votes

Tout d'abord, vous ne pouvez pas retourner une variable de chaîne stockée dans la pile que vous avez besoin d'utiliser MALLOC pour allouer la mémoire Dynamicy, voici des saisons avec l'exemple Go HTTPS: // NXTSpace .blogspot.com / 2018/09 / Retour-Array-of-String-and-Taking-in-C.HTML Obtenez une réponse appropriée


3 commentaires

Idéalement, vous devriez inclure un peu d'explication de la raison pour laquelle il est mauvais, puis explique qu'un "malloc" est requis, non seulement fournir un lien vers un autre site qui peut disparaître avec "Bit Rot".


J'apprécie mais je pense que les gens doivent comprendre avec des exemples de mots, c'est pourquoi j'ai donné ce lien, et si vous n'avez pas aimé, c'est bon. @Simonf


Le lien est bien d'avoir, et j'ai fait comme ça. Juste suggérer que le texte de soutien était également nécessaire 8D