2

次のコード例では、文字列を出力しませtest1ん。test5arraymain() function

ただし、内部で機能しますmake() function

答えは簡単だと確信しています。どうすれば望ましい結果が得られるのでしょうか?

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

#define ELEMENTS 4

void make(char ***array) {

char p2[] = "test1 test2 test3 test4 test5";
char* token = strtok(p2, " ");
int i = 0;
while (token) 
{

    (*array)[i]= token;
    token = strtok(NULL, " ");
    i++;
}

printf("%s\n",(*array)[0]);
printf("%s\n",(*array)[1]);
printf("%s\n",(*array)[2]);
printf("%s\n",(*array)[3]);
printf("%s\n",(*array)[4]);

}

int main(int argc, char **argv) {
char **array;
make(&array);

int i;
for (i = 0; i < ELEMENTS; ++i) {
    printf("%s\n", array[i]);
}

return 0;
}

このコードは、エラーや警告なしでコンパイルされ、次の出力が生成されます。

test1
test2
test3
test4
test5
yf�


���

私の予想される結果は、test1 - test52 回印刷されることでしmake() functionた。main() function

補足として、これはstackoverflowへの2回目の投稿にすぎません。これは、最初の質問Passing a string array to a function in Cから変更されたコードです

4

5 に答える 5

2
char p2[] = "test1 test2 test3 test4 test5";

関数のスタックに文字列 p2 を定義しますmake()strtok()同じ配列へのポインターのみを返します。これは、make()戻るときに無効になります。

これと同じです:

char * foo()
{
    char array[] = "hello";
    printf("%s\n", array); // works fine
    return array;
}

void main()
{
    char * array = foo(); // just a pointer to invalid data
    printf("%s\n", array); // FAIL
}

正しく行う方法

C で文字列を返すには、基本的に 2 つの方法があります。

バッファを埋めることによって:

void fill_buf(char * buf, size_t len)
{
    char string[] = "hello";
    snprintf(buf, len, "%s", string);
}

void main()
{
    char buffer[25];
    fill_buf(buffer, sizeof(buffer));
    printf("%s\n", buffer);
}

または、malloc された文字列を返すことによって:

char * get_malloced_or_null()
{
    char my_string[] = "hello";
    char * copied_pointer = strdup(my_string); // might fail and return NULL
    return copied_pointer;
}

void main()
{
    char * string = get_malloced_or_null();
    if (string == NULL) { return; }
    printf("%s\n", string);
    free(string);
}

2 番目の方法の利点は、任意の長さの文字列で使用できることです。一方、割り当ての失敗を確認する必要があり、使用が終わったらメモリを解放する必要があります。

于 2013-04-05T15:32:58.867 に答える
0

このコードはきれいにコンパイルされ、目的の結果が生成されます。ポインターを理解するのに役立ったすべてのおかげです。次に、配列に割り当てたメモリを解放します

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

#define ELEMENTS 5

void make(char ***array) {

char p2[] = "test1 test2 test3 test4 test5";
char* token = strtok(p2, " ");
int i = 0;
while (token) 
{

    (*array)[i] = malloc(strlen(token) + 1);
    strcpy((*array)[i], token);
    token = strtok(NULL, " ");
    i++;
}

}

int main(int argc, char **argv) {
char **array;
make(&array);

int i;
for (i = 0; i < ELEMENTS; ++i) {
    printf("%s\n", array[i]);
}

return 0;
}
于 2013-04-08T04:02:45.547 に答える
0

関数では、ローカル変数make()を解析しています。そのため、スタック アドレスが返されます (また、配列は、いつでも上書きされる可能性のあるスタック内のコンテンツを参照します)。関数が完了すると、これらのポインターはスタック内のすべてのものを参照し、配列の内容は何でもかまいません。strtok()make()

これを次のように修正できます。

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

#define ELEMENTS 4

void make(char ***array)
{
    char p2[] = "test1 test2 test3 test4 test5";
    char* token = strtok(p2, " ");
    int i = 0;
    while (token) 
    {
        (*array)[i]= strdup(token);
        token = strtok(NULL, " ");
        i++;
    }

    printf("%s\n",(*array)[0]);
    printf("%s\n",(*array)[1]);
    printf("%s\n",(*array)[2]);
    printf("%s\n",(*array)[3]);
    printf("%s\n",(*array)[4]);

}

int main(int argc, char **argv)
{
    char **array;
    make(&array);

    int i;
    for (i = 0; i < ELEMENTS; ++i) {
        printf("%s\n", array[i]);
    }

    return 0;
}
于 2013-04-05T15:37:50.903 に答える
0

p2[] を定義するだけで機能しますstatic

static char p2[] = "test1 test2 test3 test4 test5";

また、 5 である必要があり、 inELEMENTSの宣言は単純な「ポインターへのポインター」であり、「ポインターの配列」である必要があります。arraymain

char *array[ELEMENTS];

そうすれば、5本の弦を入れるのに十分なスペースが得られます.

EDIT : ポインターの配列を操作すると、make()関数が簡素化されます。

void make(char **array) {
    static char p2[] = "test1 test2 test3 test4 test5";
    char *token = strtok(p2, " ");
    int i = 0;
    while (token) {
        array[i] = token;
        token = strtok(NULL, " ");
        i++;
    }
    for (i = 0; i < ELEMENTS; ++i)
        printf("%d: %s\n", i, array[i]);
}

int main(int argc, char **argv)
{
    char *array[ELEMENTS];
    make(array);
    /* ... */
}
于 2013-04-05T15:45:22.437 に答える