重新分配后无法打印字符串数组?
Trouble printing an array of strings after realloc?
下面的代码读取字符并在遇到定界符时将它们拆分为C风格的字符串,然后将单词(以白色-space分隔的字符序列)存储在字符串数组中,直到标记为遭遇;更新字符串数组的大小:
#include <stdio.h> // printf()
#include <stdlib.h> // malloc(); realloc()
#include <string.h> // strcmp()
#include <stddef.h> // size_t
void print_array(char* arr[ ], size_t size); // forward declaration to use in to_array()
char* get_word(char delimiter)
{
size_t size = 8;
size_t index = 0;
int c = 0;
char* word = 0;
char* expand_word = 0;
word = (char*) malloc(sizeof(char) * size);
if (word == NULL)
{
perror("get_word::bad malloc!\n");
exit(-1);
}
while ((c = getchar()) != EOF && c != delimiter && c != '\n')
{
if (index >= size)
{
size *= 2;
expand_word = (char*) realloc(word, sizeof(char) * size);
if (expand_word == NULL)
{
perror("get_word::bad realloc!\n");
exit(-1);
}
word = expand_word;
}
word[index++] = c;
}
word[index] = 0;
return word;
}
//-------------------------------------------------------------------------------------
void to_array(char* arr[ ], size_t* size, char* sentinel)
{
size_t index = 0;
char* word = 0;
char** expand_arr = 0;
char delimiter = ' ';
while ((word = get_word(delimiter)) && strcmp(word, sentinel) != 0)
{
if (index >= (*size))
{
(*size) *= 2;
expand_arr = (char**) realloc(arr, sizeof(char*) * (*size));
if (expand_arr == NULL)
{
perror("to_array::bad realloc!\n");
exit(-1);
}
arr = expand_arr;
}
arr[index++] = word;
}
(*size) = index;
// print_array(arr, *size); // <---- here, all words printed OK.
// getchar();
}
//-------------------------------------------------------------------------------------
void print_array(char* arr[ ], size_t size)
{
size_t i = 0;
printf("{ ");
for (i; i < size; ++i)
{
printf("%s", arr[i]);
if (i < size - 1)
{
printf(", ");
}
}
printf(" }\n");
}
//-------------------------------------------------------------------------------------
int main()
{
size_t size = 4;
char** arr = 0;
char* sentinel = "quit";
arr = (char**) malloc(sizeof(char*) * size);
if (arr == NULL)
{
perror("array of strings::bad malloc!\n");
exit(-1);
}
printf("Type a sentence and get each word as an array element:\n");
to_array(arr, &size, sentinel);
printf("Words:\n");
print_array(arr, size); // <--------- here, error!
getchar();
}
尝试打印字符串数组时,我得到:
Access violation reading location 0xcd007361.
为什么我无法在最后打印 arr
中的字符串?
P.S.: 我猜问题出在指针算法和函数 to_array()
中 char** arr
的重新分配。 (如果前面是对的)我不确定处理它的标准方法是什么?
问题:
void to_array()
中的第一个参数,即 char* arr[ ]
将指针的副本传递给 char
的数组。函数内部指针的每次更改都不会影响外部指向 char
数组的实际指针,特别是函数 realloc()
可能会将初始内存块移动到新位置,这会使传递的指针无效第一个参数。
解决方法:
要么修改函数void to_array()
为return修改后的arr
,要么修改函数的第一个参数至 char** arr[ ]
。选择了后者,修改后的代码如下所示:
void to_array(char** arr[ ], size_t* size, char* quit)
{
size_t index = 0;
char* word = 0;
char** expand_arr = 0;
char sentinel = ' ';
while ((word = get_word(sentinel)) && strcmp(word, quit) != 0)
{
if (index >= (*size))
{
(*size) *= 2;
expand_arr = (char**) realloc((*arr), sizeof(char*) * (*size));
if (expand_arr == NULL)
{
perror("to_array::bad realloc!\n");
exit(-1);
}
(*arr) = expand_arr;
}
(*arr)[index++] = word;
}
(*size) = index;
}
那么函数调用必须按照以下方式完成:
to_array(&arr, &size, quit);
下面的代码读取字符并在遇到定界符时将它们拆分为C风格的字符串,然后将单词(以白色-space分隔的字符序列)存储在字符串数组中,直到标记为遭遇;更新字符串数组的大小:
#include <stdio.h> // printf()
#include <stdlib.h> // malloc(); realloc()
#include <string.h> // strcmp()
#include <stddef.h> // size_t
void print_array(char* arr[ ], size_t size); // forward declaration to use in to_array()
char* get_word(char delimiter)
{
size_t size = 8;
size_t index = 0;
int c = 0;
char* word = 0;
char* expand_word = 0;
word = (char*) malloc(sizeof(char) * size);
if (word == NULL)
{
perror("get_word::bad malloc!\n");
exit(-1);
}
while ((c = getchar()) != EOF && c != delimiter && c != '\n')
{
if (index >= size)
{
size *= 2;
expand_word = (char*) realloc(word, sizeof(char) * size);
if (expand_word == NULL)
{
perror("get_word::bad realloc!\n");
exit(-1);
}
word = expand_word;
}
word[index++] = c;
}
word[index] = 0;
return word;
}
//-------------------------------------------------------------------------------------
void to_array(char* arr[ ], size_t* size, char* sentinel)
{
size_t index = 0;
char* word = 0;
char** expand_arr = 0;
char delimiter = ' ';
while ((word = get_word(delimiter)) && strcmp(word, sentinel) != 0)
{
if (index >= (*size))
{
(*size) *= 2;
expand_arr = (char**) realloc(arr, sizeof(char*) * (*size));
if (expand_arr == NULL)
{
perror("to_array::bad realloc!\n");
exit(-1);
}
arr = expand_arr;
}
arr[index++] = word;
}
(*size) = index;
// print_array(arr, *size); // <---- here, all words printed OK.
// getchar();
}
//-------------------------------------------------------------------------------------
void print_array(char* arr[ ], size_t size)
{
size_t i = 0;
printf("{ ");
for (i; i < size; ++i)
{
printf("%s", arr[i]);
if (i < size - 1)
{
printf(", ");
}
}
printf(" }\n");
}
//-------------------------------------------------------------------------------------
int main()
{
size_t size = 4;
char** arr = 0;
char* sentinel = "quit";
arr = (char**) malloc(sizeof(char*) * size);
if (arr == NULL)
{
perror("array of strings::bad malloc!\n");
exit(-1);
}
printf("Type a sentence and get each word as an array element:\n");
to_array(arr, &size, sentinel);
printf("Words:\n");
print_array(arr, size); // <--------- here, error!
getchar();
}
尝试打印字符串数组时,我得到:
Access violation reading location 0xcd007361.
为什么我无法在最后打印 arr
中的字符串?
P.S.: 我猜问题出在指针算法和函数 to_array()
中 char** arr
的重新分配。 (如果前面是对的)我不确定处理它的标准方法是什么?
问题:
void to_array()
中的第一个参数,即 char* arr[ ]
将指针的副本传递给 char
的数组。函数内部指针的每次更改都不会影响外部指向 char
数组的实际指针,特别是函数 realloc()
可能会将初始内存块移动到新位置,这会使传递的指针无效第一个参数。
解决方法:
要么修改函数void to_array()
为return修改后的arr
,要么修改函数的第一个参数至 char** arr[ ]
。选择了后者,修改后的代码如下所示:
void to_array(char** arr[ ], size_t* size, char* quit)
{
size_t index = 0;
char* word = 0;
char** expand_arr = 0;
char sentinel = ' ';
while ((word = get_word(sentinel)) && strcmp(word, quit) != 0)
{
if (index >= (*size))
{
(*size) *= 2;
expand_arr = (char**) realloc((*arr), sizeof(char*) * (*size));
if (expand_arr == NULL)
{
perror("to_array::bad realloc!\n");
exit(-1);
}
(*arr) = expand_arr;
}
(*arr)[index++] = word;
}
(*size) = index;
}
那么函数调用必须按照以下方式完成:
to_array(&arr, &size, quit);