2017-02-20 1 views
1

Je veux savoir (j'ai essayé de mais gèle le programme) s'il y a un moyen de créer une fonction qui retourne un char * ou un char [], donc je ne dois pas modifier la chaîne que j'envoie à la fonction , pour apprendre à rendre mon code plus éloquent.Puis-je utiliser char [] ou char * comme valeur de retour d'une fonction?

#include <stdio.h> 
#define LOW_LETTERS 97 
#define CAP_LETTERS 65 
#define N_LETTERS 26 
#define DIFF 32 
#define NUMBERS 48 
#define N_DIGITS 9 


void transformText (char text[]) 
{ 
    for (int i = 0 ; text[i] != '\0' ; i++) 
    { 
     if ((text[i] >= LOW_LETTERS) && (text[i] <= LOW_LETTERS + N_LETTERS)) 
      text[ i ] = text [ i ] - DIFF ; //same letter, but upper case 
     else 
      if ((text [ i ] >= CAP_LETTERS) && (text[i] <= CAP_LETTERS + N_LETTERS)) 
       text [ i ] = text [ i ] + DIFF ; //same letter, but lower case 
      else 
       if (text [i] >= NUMBERS && text[i] <= NUMBERS + N_DIGITS) 
        text[i] = '*'; //turns every number to a '*' 
    } 

} 

int main (void) 
{ 
    char text[] = "foOo123Oo44O99oO00" ; 
    transformText (text) ; 
    printf ("%s\n", text) ; //prints FOoO***oO**o**Oo** 

    return 0 ; 
} 

C'est de cette façon que je l'ai résolu, je pense que j'ai un problème de fuite de mémoire, n'est-ce pas? Notez que je ne suis pas modifier la chaîne d'origine, ce qui est ce que je comptais faire, aussi je ne sais pas vraiment où mettre le free(newText) il est reconnu, mais encore utilisable pour main()

#include <stdio.h> 
#define LOW_LETTERS 97 
#define CAP_LETTERS 65 
#define N_LETTERS 26 
#define DIFF 32 
#define NUMBERS 48 
#define N_DIGITS 9 
#define BUFFER 128 


char* transformText (char text[]) 
{ 
    char *newText = (char *) malloc (BUFFER) ; 
    for (int i = 0 ; text[i] != '\0' ; i++) 
    { 
     if ((text[i] >= LOW_LETTERS) && (text[i] <= LOW_LETTERS + N_LETTERS)) 
      newText[ i ] = text [ i ] - DIFF ; //same letter, but upper case 
     else 
      if ((text [ i ] >= CAP_LETTERS) && (text[i] <= CAP_LETTERS + N_LETTERS)) 
       newText [ i ] = text [ i ] + DIFF ; //same letter, but lower case 
      else 
       if (text [i] >= NUMBERS && text[i] <= NUMBERS + N_DIGITS) 
        newText[i] = '*'; //turns every number to a '*' 
       else 
        newText[i] = text[i] ; 
    } 

    return newText ; 
} 

int main (void) 
{ 
    char text[] = "foOo123Oo44O99oO00" ; 

    printf ("%s\n", transformText (text)) ; //prints FOoO***oO**o**Oo** 
    return 0 ; 
} 
+1

Vous pouvez retourner 'char *' mais vous devez également penser à la localisation de la chaîne modifiée. –

+0

oui c'est une simple chose pointeur .. vous pouvez avoir des pointeurs comme valeurs de fonctions retournées –

+0

@MM Je l'ai fait de cette façon, parce que je ne pouvais pas faire comme je le demande, dans mon idée originale, je ne serais pas modifiez la chaîne. – newbie

Répondre

1

En général, oui, vous êtes tous bien d'avoir une fonction qui renvoie une char *, mais vous devez faire attention à quelques choses, comme

  • vous devez être sûr de ne pas renvoyer l'adresse d'une variable locale la fonction appelée. Cela va créer le problème de l'utilisation d'une mémoire invalide dans l'appelant. Le moyen préférable est d'allouer de la mémoire en utilisant malloc() ou famille et retourner le pointeur. Vous avez besoin de free() la mémoire aussi, une fois que vous avez fini de l'utiliser.
  • Si vous voulez utiliser le pointeur retourné, vous devez vous assurer de la validité du pointeur retourné.

EDIT:

Alors, une fois que vous avez obtenu le pointeur retourné dans l'appelant et fait avec son utilisation, vous devez libérer la mémoire allouée précédemment en appelant free() et en passant le pointeur. Dans votre cas, il devrait ressembler

char * res = transformText (text); 
printf ("%s\n", res); // use the returned pointer 
free(res);         // release memory 
return 0 ;         // done 
+0

Merci, mec! Je l'ai fait comme ça et ça marche ... encore je pense qu'il me manque quelque chose à propos du 'free()', je veux dire si je libère cette mémoire dans la fonction transformText, alors je ne serais pas capable de le montrer 'principal()', non? mais le principal ne sait pas qui est char * newText, parce que je l'ai défini sur cette autre fonction. – newbie

+0

s'il vous plaît, vérifiez l'édition ... ne peut pas vous répondre avec le nouveau code. – newbie

+0

@newbie Mettra à jour ma réponse, surveille. –

-3

il est très simple:

#include <stdio.h> 
#define LOW_LETTERS 97 
#define CAP_LETTERS 65 
#define N_LETTERS 26 
#define DIFF 32 
#define NUMBERS 48 
#define N_DIGITS 9 


char* transformText (char text[]) 
{ 
for (int i = 0 ; text[i] != '\0' ; i++) 
{ 
if ((text[i] >= LOW_LETTERS) && (text[i] <= LOW_LETTERS + N_LETTERS)) 
text[ i ] = text [ i ] - DIFF ; //same letter, but upper case 
else 
if ((text [ i ] >= CAP_LETTERS) && (text[i] <= CAP_LETTERS + N_LETTERS)) 
text [ i ] = text [ i ] + DIFF ; //same letter, but lower case 
else 
if (text [i] >= NUMBERS && text[i] <= NUMBERS + N_DIGITS) 
text[i] = '*'; //turns every number to a '*' 
} 
return text; 

} 

int main (void) 
{ 
char text[] = "foOo123Oo44O99oO00" ; 
char* text2 = transformText (text) ; 
printf ("%s\n", text) ; //prints FOoO***oO**o**Oo** 
printf ("%s\n", text2) ; //prints FOoO***oO**o**Oo** 
free(text2); 
return 0 ; 
} 

rendements même valeur: enter image description here

1

Puisque les fonctions ne peuvent pas renvoyer des tableaux, vous devez retourner un pointeur du tas. La raison pour laquelle vous ne pouvez pas renvoyer les tableaux est qu'ils sont déclarés sur la pile et effacés lors du retour de la fonction. Alors que si vous renvoyez un pointeur à la place, vous pouvez partager ce pointeur dans votre programme.

Votre code serait à peu près comme ceci:

char* transformText(const char text[]) { 
    char *result = malloc(........); 
    /* check malloc */ 
    /* more code */ 
    return result; 
} 

int main(void) { 
    const char text[] = "foOo123Oo44O99oO00"; 
    char *result = transformText(text); 
    /* do more stuff */ 

    /* deallocate pointer */ 
    free(result); 
} 

Voici un autre exemple qui montre que vous pouvez toujours utiliser void() pour votre fonction, et ne retournera rien:

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

void allocate(const char text[], char **result) { 
    *result = malloc(strlen(text)+1); 
} 

int main(void) { 
    const char text[] = "foOo123Oo44O99oO00"; 
    char *result; 

    allocate(text, &result); 
    strcpy(result, text); 

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

    free(result); 

    return 0; 
} 
+0

merci, je pensais aussi que c'était comme ça que ça devait être fait, mais j'essayais juste de faire quelque chose de plus expressif, tu sais? comme 'printf ("% s \ n ", transformText (texte))' mais je suppose que je ne peux pas le faire de cette façon, et libérer la mémoire allouée sans référence. Je suppose, je vais juste devoir déclarer une référence statique à un pointeur pour pouvoir tenir cette adresse, mais c'est la même chose que d'utiliser un 'void transormText (char * texte)', puis libérer le char * sur le La fonction principale, je veux dire transformText, ne ferait que modifier ce pointeur et ne pas le retourner, parce que je n'aurais pas besoin de ça. – newbie

+0

@newbie Vous pouvez utiliser 'void()' pour faire cela, mais l'approche ci-dessus est la meilleure façon de le faire. J'ai édité la réponse pour inclure un autre exemple. – RoadRunner

+0

Je sais que je peux, je me demandais juste s'il y avait un moyen de ne pas utiliser une fonction 'void()' mais une fonction 'char *'. – newbie

0

Le plus souvent, vous ne voulez pas renvoyer un char* à partir d'une fonction. Il n'y a aucun avantage évident à le faire dans votre cas.

alternatives sont soit d'avoir l'appelant faire une copie:

const char text[] = "foOo123Oo44O99oO00"; 
char text_copy [strlen(text)+1]; 
memcpy(text_copy, text, sizeof(text)); 
transformText (text_copy); 

ou d'avoir la fonction faire:

void transformText (char* dst, const char* src) 
{ 
    // iterate over src 
    // store result in dst 
} 

Il n'y a pas de raison évidente pour laquelle l'allocation dynamique serait bénéfique ici. Utiliser la mémoire dynamique ressemble plutôt à un effet secondaire provoqué par une mauvaise conception du programme. Le retour des pointeurs vers la mémoire dynamique doit être évité, car il présente un fort potentiel de fuites de mémoire.

Dans la mesure du possible, laissez l'attribution à l'appelant.