以下代码示例不会打印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
修改的代码答案 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,array
中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);
/* ... */
}
答案 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;
}