修改函数内部的字符串数组

时间:2013-04-05 15:23:54

标签: c c-strings

以下代码示例不会打印test1

test5中包含的字符串array - main() 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

修改的代码

5 个答案:

答案 0 :(得分:2)

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

定义make()函数堆栈上的字符串p2。 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'd字符串:

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

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

答案 1 :(得分: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;
}

答案 2 :(得分:0)

除上述答案外;

您必须在char ***array函数

的开头为make()分配内存
*array = malloc(ELEMENTS * sizeof(char *));

ELEMENTS应定义为5,而不是4

#define ELEMENTS 5

答案 3 :(得分:0)

只需定义p2 [] static

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

同样,ELEMENTS应为5,arraymain的声明是一个简单的“指针指针”,它应该是“指针数组”:

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);
    /* ... */
}

答案 4 :(得分: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;
}