web-dev-qa-db-ja.com

Cの関数から文字配列を返すにはどうすればよいですか?

それは可能ですか? 2文字の配列を返したいとしましょう

char arr[2];
arr[0] = 'c';
arr[1] = 'a';

関数から。関数にはどのタイプを使用しますか?ポインタを使用して関数を無効にする唯一の選択肢はありますか?これまでのところ、char *関数またはchar []を試してみました。どうやらあなたはchar(* [])の関数しか持つことができません。ポインターの使用を避けたい唯一の理由は、関数が「何かを返す」と遭遇したときに関数が終了しなければならないという事実です。 "something"の値は文字配列(文字列ではない!)であるため、メイン関数を介して関数に渡す値に応じてサイズが変わる可能性があります。事前に対応してくださった方に感謝します。

9
user5042178

いくつかのオプションがあります:

1)malloc()を使用してheapに配列を割り当て、その配列へのポインタを返します。また、自分で長さを追跡する必要があります。

void give_me_some_chars(char **arr, size_t *arr_len)
{
    /* This function knows the array will be of length 2 */
    char *result = malloc(2);

    if (result) {
        result[0] = 'c';
        result[1] = 'a';
    }

    /* Set output parameters */
    *arr = result;
    *arr_len = 2;
}

void test(void)
{
    char *ar;
    size_t ar_len;
    int i;

    give_me_some_chars(&ar, &ar_len);

    if (ar) {
        printf("Array:\n");
        for (i=0; i<ar_len; i++) {
            printf(" [%d] = %c\n", i, ar[i]);
        }
        free(ar);
    }
}

2)callerstack上の配列にスペースを割り当て、呼び出された関数に入力します。

#define ARRAY_LEN(x)    (sizeof(x) / sizeof(x[0]))

/* Returns the number of items populated, or -1 if not enough space */
int give_me_some_chars(char *arr, int arr_len)
{
    if (arr_len < 2)
        return -1;

    arr[0] = 'c';
    arr[1] = 'a';

    return 2;
}

void test(void)
{
    char ar[2];
    int num_items;

    num_items = give_me_some_chars(ar, ARRAY_LEN(ar));

    printf("Array:\n");
    for (i=0; i<num_items; i++) {
        printf(" [%d] = %c\n", i, ar[i]);
    }
}

これを実行しないでください

char* bad_bad_bad_bad(void)
{
    char result[2];      /* This is allocated on the stack of this function
                            and is no longer valid after this function returns */

    result[0] = 'c';
    result[1] = 'a';

    return result;    /* BAD! */
}

void test(void)
{
    char *arr = bad_bad_bad_bad();

    /* arr is an invalid pointer! */
}
14

関数から配列のポインターを返すことはできますが、ローカル配列へのポインターを返すことはできません。参照は失われます。

したがって、3つのオプションがあります。

  1. グローバル変数を使用します。

    char arr[2];
    
    char * my_func(void){
        arr[0] = 'c';
        arr[1] = 'a';
        return arr;
    }
    
  2. 動的割り当てを使用します(呼び出し元には、使用後にポインターを解放する責任があります。ドキュメントでそれを明確にしてください)

    char * my_func(void){
    
        char *arr;    
        arr = malloc(2);
        arr[0] = 'c';
        arr[1] = 'a';
    
        return arr;
    }
    
  3. 呼び出し元に配列を割り当てさせ、参照として使用させます(私の推奨)

    void my_func(char * arr){
    
        arr[0] = 'c';
        arr[1] = 'a';
    }
    

配列を返す関数が本当に必要な場合は、次のように同じ参照を返すことができます。

char * my_func(char * arr){
    arr[0] = 'c';
    arr[1] = 'a';
    return arr;
}
0
DSLima90

次のように、配列を関数に渡し、関数にそれを変更させることができます

void function(char *array)
 {
    array[0] = 'c';
    array[1] = 'a';
 }

その後

char array[2];

function(array);
printf("%c%c\n", array[0], array[1]);

戻り値として必要な場合は、動的メモリ割り当てを使用する必要があります。

char *function(void)
 {
    char *array;

    array = malloc(2);
    if (array == NULL)
        return NULL;
    array[0] = 'c';
    array[1] = 'a';

    return array;
 }

その後

char *array = function();
printf("%c%c\n", array[0], array[1]);
/* done using `array' so free it because you `malloc'ed it*/
free(array);

重要な注意

上記のように入力された配列は文字列ではないため、たとえばこれを行うことはできません。

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

"%s"は一致する文字列が渡されることを期待し、cでは配列は最後の文字が'\0'でない限り文字列ではないため、2文字の文字列の場合は3文字のスペースを割り当てる必要があり、最後のものを'\0'に設定します。

0
Iharob Al Asimi

あらかじめ決められたサイズの配列があるので、構造体でラップすれば、配列を実際に返すことができます。

struct wrap
{
    char a[2] ;
} ;

struct wrap Get( void )
{
    struct wrap w = { 0 } ;

    w.a[0] = 'c';
    w.a[1] = 'a';

return w ;
}
0
this