2

以下代码示例不打印字符串test1-test5包含arraymain() 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 - test5打印了两次,一次在里面,make() function一次在里面main() function

作为旁注,这只是我对stackoverflow的第二篇文章,这是我的第一个问题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 中返回字符串基本上有两种方法。

通过填充缓冲区:

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

第二种方法的优点是您可以将它与任意长的字符串一起使用。另一方面,您需要检查分配失败,并且您必须在完成后释放内存。

于 2013-04-05T15:32:58.867 回答
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

除了上述答案;

您必须char ***array在开始时为make()函数分配内存

*array = malloc(ELEMENTS * sizeof(char *));

并且ELEMENTS应该定义为5而不是4

#define ELEMENTS 5
于 2013-04-05T15:41:09.443 回答
0

它可以简单地定义 p2[] static

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

此外,ELEMENTS应该是 5,并且arrayin的声明main是一个简单的“指向指针的指针”,它应该是“指针数组”:

char *array[ELEMENTS];

那么您将获得足够的空间容纳 5 根琴弦。

编辑:使用指针数组简化了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 回答
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 回答