2013-04-05 69 views
2

下面的代码示例内部字符串数组,不打印test1琴弦 - 包含在arraymain() function修改功能

test5但它的作品里面的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

+0

您仍在使您的阵列太小。 – 2013-04-05 15:26:59

回答

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

定义了函数堆栈中的字符串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); 
} 

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

+0

好的方法来回答:) – 2013-04-05 15:45:24

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

除了上述答案的;

你必须在一开始分配的char ***array内存make()功能

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

ELEMENTS应该被定义为5而不是4

#define ELEMENTS 5 
0

它与简单地定义P2 [ ] static

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

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

char *array[ELEMENTS]; 

,那么你会得到足够的空间你的5弦。

编辑:用指针数组工作simplfies的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); 
    /* ... */ 
} 
+0

虽然这个工作,它不是制作实际软件的最佳方法,因为如果您不止一次地使用该函数,它会中断。 – che 2013-04-05 15:57:30

+0

是的,但为什么要解析相同的字符串多次..实际的软件不应该这样做:) – 2013-04-05 15:59:43

+0

是的,但我见过一个函数被用来解析不同的字符串的情况。 – che 2013-04-05 17:28:15

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