我已经阅读了有关在C中动态扩展数组的内容以及许多答案,但我无法找到问题的根源。我尝试使用空格作为分隔符进行标记,并将每个字符串存储在一个数组中,因此"this is string"
变为{ "this", "is", "string" }
。
我能够使用预定义的数组大小来执行此操作,但是当传入的语句超过声明时,无法扩展它。以下是代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DEFAULT_SIZE 3 /* default size of an array of words */
// array object
typedef struct {
char pointer[DEFAULT_SIZE][256];
int used;
int size;
} Array;
void createArray(Array *array, int start_size) {
array->used = 0;
array->size = start_size;
}
void append(Array *array, char* elem) {
if (array->used >= array->size) { // if every slot is used, then we expand
array->size += 2; // expand by 2 slots
Array *array = malloc(sizeof(Array));
array = realloc(array, sizeof(array) + 2 * 256);
}
strcpy(array->pointer[array->used] , elem); // insert new element
array->used++; // <-- wrong value here. increment info about used slots
}
char * args_str; // passed string
Array args_list; // expandable array holding words
void parse(char* command) {
createArray(&args_list, DEFAULT_SIZE);
args_str = strtok(command, " ");
while (args_str != NULL) {
append(&args_list, args_str);
args_str = strtok(NULL, " ");
}
return ;
}
我注意到array->used
的值正确递增,直到数组扩展为止。如果有超过3个项目,则类似于1,2,3,66123(或其他随机值)。我怀疑这是错误的realloc
,但我
答案 0 :(得分:2)
您遇到的一个问题是您对动态分配的内存可以扩展(或使用)的基本理解。您的typedeffed结构Array
是固定大小。如果您为Array *array
分配,则之后realloc
array
不能sizeof *array
。它始终是Array
。为它分配更多的内存,没有任何好处,因为它不包含指向任何额外内存的指针,并且会破坏该类型的指针算术。
你唯一能做的就是分配DEFAULT_SIZE
的任何数组。但这会相当麻烦,因为每个元素只能存储最多pointer
个令牌。
如果我理解你要完成什么,而不是让你的结构包含一个固定大小的2D数组pointer
,你需要char[256]
实际上是一个指向一个指针-array #define DEFAULT_SIZE 3 /* default size of an array of words */
#define TOKEN_SIZE 256
typedef struct {
char (*pointer)[TOKEN_SIZE];
int used;
int size;
} arr;
。例如,您想要:
camelCase
(注意: C避免使用PascalCase
或Array
变量名称支持所有小写,同时保留用于宏和常量的大写名称。)
现在,您确实可以在arr
(标准情况下为arr
)中调整大小。您可以分配arr->pointer
的实例,然后在realloc
arr->pointer
(以及arr->used >= arr->size
realloc
重新修改您的示例,为每个内存分配添加正确的验证,并使用realloc
方案,每个方案arr->pointer
2 * arr->size
到arr->used >= arr->size
时间#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_SIZE 3 /* default size of an array of words */
#define TOKEN_SIZE 256
typedef struct {
char (*pointer)[TOKEN_SIZE];
int used;
int size;
} arr;
arr *createArray (int start_size)
{
arr *array = malloc (sizeof *array);
if (!array) {
perror ("malloc - array");
exit (EXIT_FAILURE);
}
array->used = 0;
array->size = start_size;
array->pointer = malloc (start_size * sizeof *array->pointer);
if (!array->pointer) {
perror ("malloc - array->pointer");
exit (EXIT_FAILURE);
}
return array;
}
void append (arr *array, char *elem)
{
if (array->used >= array->size) {
void *tmp = realloc (array->pointer, array->size * 2 * sizeof *array->pointer);
if (!tmp) {
perror ("realloc - array->pointer");
return; /* you should change function type provide success/failure */
}
array->pointer = tmp;
array->size *= 2; /* update size */
}
if (strlen (elem) + 1 < sizeof *array->pointer) {
strcpy (array->pointer[array->used], elem); // insert new element
array->used++; // <-- wrong value here. increment info about used slots
}
else
fprintf (stderr, "error: token too long.\n");
}
arr *parse (char* command)
{
char *args_str;
arr *args_list = createArray (DEFAULT_SIZE);
args_str = strtok (command, " ");
while (args_str != NULL) {
append (args_list, args_str);
args_str = strtok (NULL, " ");
}
return args_list;
}
/* simple print function */
void prnarr (arr *array)
{
int i;
for (i = 0; i < array->used; i++)
printf ("array[%2d] : %s\n", i, array->pointer[i]);
}
/* simple function to free allocated memory */
void freearr (arr *array)
{
free (array->pointer);
free (array);
}
int main (void) {
char str[] = "my dog has fleas my cat has none lucky cat";
arr *args = parse (str);
prnarr (args);
freearr (args);
return 0;
}
,您可以执行以下操作:
$ ./bin/arr_struct_arr_of_ptrs
array[ 0] : my
array[ 1] : dog
array[ 2] : has
array[ 3] : fleas
array[ 4] : my
array[ 5] : cat
array[ 6] : has
array[ 7] : none
array[ 8] : lucky
array[ 9] : cat
示例使用/输出
valgrind
内存使用/错误检查
在你编写的动态分配内存的任何代码中,你有2个职责关于任何分配的内存块:(1)总是保留一个指向起始地址的指针内存块,(2)当不再需要时,它可以释放。
必须使用内存错误检查程序,以确保您不会尝试访问内存或写入超出/超出已分配块的范围,尝试读取或基于未初始化值的条件跳转,最后,确认您释放了所有已分配的内存。
对于Linux $ valgrind ./bin/arr_struct_arr_of_ptrs
==9128== Memcheck, a memory error detector
==9128== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9128== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9128== Command: ./bin/arr_struct_arr_of_ptrs
==9128==
array[ 0] : my
array[ 1] : dog
array[ 2] : has
array[ 3] : fleas
array[ 4] : my
array[ 5] : cat
array[ 6] : has
array[ 7] : none
array[ 8] : lucky
array[ 9] : cat
==9128==
==9128== HEAP SUMMARY:
==9128== in use at exit: 0 bytes in 0 blocks
==9128== total heap usage: 4 allocs, 4 frees, 5,392 bytes allocated
==9128==
==9128== All heap blocks were freed -- no leaks are possible
==9128==
==9128== For counts of detected and suppressed errors, rerun with: -v
==9128== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
是正常的选择。每个平台都有类似的记忆检查器。它们都很简单易用,只需通过它运行程序即可。
double max = decMax[0];
for (int counter = 1; counter < decMax.length; counter++){
if(max<decMax[i]){
max=decMax[i]; //swapping
decMax[i]=decMax[0];
}
}
System.out.println("The max value is "+ max);
始终确认已释放已分配的所有内存并且没有内存错误。
仔细看看,如果您有其他问题,请告诉我。
答案 1 :(得分:1)
您使用realloc
错误。
Array *array = malloc(sizeof(Array));
array = realloc(array, sizeof(array) + 2 * 256);
realloc
用于调整(增大或缩小)动态分配的内存量。它使
在下一步中首先分配然后重新分配的意义不大。为什么不这样做
你首先分配了足够的内存吗?
这是你应该重新分配更多内存的方法:
Array *append(Array *array, char* elem) {
size_t size;
if(array == NULL)
size = 2;
else if (array->used >= array->size)
size = array->size + 2;
Array *tmp = realloc(array, size * sizeof *tmp);
if(tmp == NULL)
return NULL; // telling the caller that something went wrong
array = tmp;
array->size = size;
// I don't understand what you are trying to do here
// strcpy(array->pointer[array->used] , elem); // insert new element
// array->used++; // <-- wrong value here. increment info about used slots
return array;
}
我不知道你在realloc
获得256的位置。现在致电append
:
Array *tmp = append(array, element);
if(tmp == NULL)
{
// something went wrong
// do error handling,
// do NOT continue
}
array = tmp;
...
说实话,我真的不明白你在做什么
Array
结构。 pointer
是一个无法动态调整大小的数组,
因为它的大小是固定的。相反,您正在创建越来越多Array
已经有二维数组的对象。我不明白这个原因
为此。
无论如何,这就是我要用的:
typedef struct {
char **words;
size_t size;
size_t used;
} Array;
Array *createArray(size_t size) {
Array *array = malloc(sizeof *array);
if(array == NULL)
return NULL;
array->used = 0;
array->size = size;
array->words = calloc(size, sizeof *array->words);
if(array->words == NULL)
{
free(array);
return NULL;
}
return array;
}
// it can make grow and shrink the array
int resize_array(Array *array, size_t newsize)
{
if(array == NULL)
return 0;
if(array->size == newsize)
return 1;
char **tmp = realloc(array->words, newsize * sizeof *tmp);
if(tmp == NULL)
return 0;
array->words = tmp;
if(array->size < newsize)
{
// setting new fields to 0
memset(array->words + array->size, 0, newsize - array->size);
} else {
if(array->used > newsize)
array->used = newsize;
}
array->size = newsize;
return 1;
}
int append(Array *array, char* elem) {
if(array == NULL || elem == NULL)
return 0;
if(array->used >= array->size)
{
// adding 2 more spaces
if(!resize_array(array, array->size + 2))
return 0;
}
array->words[array->used++] = strdup(elem);
return 1;
}
void free_array(Array *array)
{
if(array == NULL)
return;
for(int i = 0; i < array->size; ++i)
free(array->words[i]);
free(array->words);
free(array);
}
别忘了释放记忆,请不要使用全局变量,这是一种不好的做法。你必须使用 全局变量只有在它们真正必要时才会出现。