2017-02-20 39 views
1

Я хочу знать (я пытался, но программа зависает), если есть способ создать функцию, которая возвращает char * или char [], поэтому мне не нужно изменять строку, которую я посылаю функции , чтобы узнать, как сделать мой код более красноречивым.Могу ли я использовать char [] или char * в качестве возвращаемого значения функции?

#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 ; 
} 

Так я решил это, я думаю, что у меня возникла мысль об утечке памяти, не так ли? Обратите внимание, что я не изменяя исходную строку, которая является то, что я собирался сделать, и я не знаю, куда поместить free(newText) так распознан, но еще можно использовать для 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

Вы можете вернуть 'char *', но вам также нужно подумать о местонахождении в памяти, в которую будет входить измененная строка. –

+0

да, это простая вещь-указатель. У вас могут быть указатели в качестве возвращаемых значений функций. –

+0

@MM. Я сделал это так, потому что я не мог сделать это так, как я прошу, по моей первоначальной идее, я бы не стал измените строку. – newbie

ответ

1

В вообще, да, вы все хорошо иметь функцию, которая возвращает char *, но вы должны быть осторожны о нескольких вещах, как

  • вы должны быть уверены, чтобы не возвращать адрес локальной переменной вызываемой функции. Это создаст проблему использования недопустимой памяти в вызывающем. Предпочтительным способом является выделение памяти с использованием malloc() или семейства и возврата указателя. Вам также понадобится free(), как только вы закончите использовать его.
  • Если вы собираетесь использовать возвращаемый указатель, вам нужно убедиться в правильности возвращаемого указателя.

EDIT:

Итак, как только вы получили возвращенный указатель в вызывающем и сделаны с его использованием, необходимо освободить память, выделенную ранее, вызвав free() и передавая указатель. В вашем случае, это должно выглядеть

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

Спасибо, мужик! Я сделал это так, и он работает ... но я думаю, что я что-то пропустил в 'free()', я имею в виду, если я освобожу эту память в функции transformText, тогда я не смог бы ее показать в 'main()', правильно? но главное не знает, кто является char * newText, потому что я определил его на этой другой функции. – newbie

+0

, пожалуйста, проверьте изменения ... не можете ответить вам новым кодом. – newbie

+0

@newbie Будет обновлять мой ответ, следить за ним. –

-3

очень прямо:

#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 ; 
} 

возвращает то же значение: enter image description here

1

Поскольку функции не могут возвращать массивы, вам нужно возвращать указатель из кучи. Причина, по которой вы не можете вернуть массивы, состоит в том, что они объявляются в стеке и стираются при возврате функции. Если вместо этого вы вернете указатель, вы можете поделиться этим указателем в своей программе.

Ваш код будет примерно так:

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); 
} 

Вот еще один пример, который показывает, что вы все еще можете использовать void() для вашей функции, а не возвращать ничего:

#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

спасибо, я тоже подумал, что так нужно, но я просто пытался сделать что-то более выразительное, понимаешь? например 'printf ("% s \ n ", transformText (text))', но я думаю, что я не могу сделать этого таким образом и освободить выделенную память без ссылки на нее. Я полагаю, мне просто нужно объявить статическую ссылку на указатель, чтобы иметь возможность удерживать этот адрес, но это то же самое, что использовать «void transormText (char * text)», а затем освободить char * на основная функция, я имею в виду transformText, просто изменил бы этот указатель и не вернул бы его, потому что мне это не понадобится. – newbie

+0

@newbie Вы можете использовать 'void()' для этого, но подход выше - это самый простой способ сделать это. Я отредактировал ответ, чтобы включить другой пример. – RoadRunner

+0

Я знаю, что могу, мне просто интересно, есть ли способ не использовать функцию 'void()', а функцию 'char *'. – newbie

0

Чаще всего, вы не хотите возвращать char* из функции. В вашем случае нет очевидной выгоды.

Альтернативы либо иметь вызывающий сделать копию:

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

или иметь функцию это сделать:

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

Там нет очевидных причин, почему динамическое распределение будет полезно здесь. Использование динамической памяти скорее звучит как побочный эффект, вызванный плохим дизайном программы. Следует избегать возврата указателей на динамическую память, поскольку это дает высокий потенциал утечки памяти.

По возможности оставьте выделение вызывающему абоненту.