我一直在慢慢研究一個允許用戶用 C 語言動態構建陣列的庫。在我撰寫的許多函式中,我開發了一個解決方案,用另一個值替換用戶定義索引處的值,但我不確定這是一個非常有效的解決方案,如果有人可能有更好的方法,我希望有任何想法不需要創建幾個中間陣列來存盤資料。
我正在使用一個typedef structtitledArray作為指標變數的容器array,它包含len陣列的活動長度,size其中包含陣列的分配大小,elem其中包含每個索引的記憶體分配,它可以根據用戶選擇的資料型別,name它是用戶可以分配給每個陣列實體化的字串,dat_type它參考一個enum來描述陣列實體化的資料型別。
到目前為止,我已經構建了幾個與Array容器一起作業的函式,其中與這個問題最相關的是以下函式;
type_dat
一個列舉,其中包含float、double、char和的變數int。
陣列astruct充當陣列的容器。
array_mem_alloc 該函式為陣列分配記憶體,不應直接呼叫。
init_array
這個函式作為一個包裝器array_mem_alloc,是用戶實體化陣列的方式。這將回傳一個Array容器。
append_array這允許用戶將標量或陣列附加到Array容器內的陣列中。
preappend_arrayArray此函式允許用戶將標量或陣列添加到容器內陣列的開頭。
int_array_val此函式從陣列中檢索整數變數。每種資料型別都有這個函式的一個版本;但是,此特定功能與下面的示例相關。
replace_int_array_indice此函式允許用戶輸入特定索引并將該索引處的變數替換為另一個整數值。我已經為這個函式撰寫了一個解決方案,但我不相信它是一個有效的實作。在下面的示例中,實作需要創建兩個中間陣列來存盤資料,然后memmoveandmemcpy函式可以將所有資料放在一起。 我希望有人能告訴我這個功能是否有比我在下面提供的更好的解決方案。
我的檔案如下所示
陣列.h
#ifndef ARRAY_H
#define ARRAY_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum
{
FLOAT,
DOUBLE,
CHAR,
INT
} dat_type;
// --------------------------------------------------------------------------------
typedef struct
{
void *array; // Pointer to array
size_t len; // Active length of array
size_t size; // Number of allocated indizes
int elem; // Memory consumption per indice
char name[20]; // The array name
dat_type dat;
} Array;
// --------------------------------------------------------------------------------
void array_mem_alloc(Array *array, size_t num_indices);
// --------------------------------------------------------------------------------
Array init_array(dat_type dat, size_t num_indices, char *name);
// --------------------------------------------------------------------------------
int append_array(Array *array, void *elements, size_t count);
// --------------------------------------------------------------------------------
int int_array_val(Array *array, int indice);
// --------------------------------------------------------------------------------
int preappend_array(Array *array, void *elements, size_t count);
// --------------------------------------------------------------------------------
void replace_int_array_indice(Array *array, int index, int replacement_value);
#endif /* ARRAY_H */
陣列.c
void array_mem_alloc(Array *array, size_t num_indices) {
// Determine the total memory allocation and assign to pointer
void *pointer;
pointer = malloc(num_indices * array->elem);
// If memory is full fail gracefully
if (pointer == NULL) {
printf("Unable to allocate memory, exiting.\n");
free(pointer);
exit(0);
}
// Allocate resources and instantiate Array
else {
array->array = pointer;
array->len = 0;
array->size = num_indices;
}
}
// --------------------------------------------------------------------------------
Array init_array(dat_type dat, size_t num_indices, char *name) {
// Determine memory blocks based on data type
int size;
switch(dat) {
case FLOAT:
size = sizeof(float);
break;
case INT:
size = sizeof(int);
break;
case DOUBLE:
size = sizeof(double);
break;
case CHAR:
size = sizeof(char);
break;
default:
printf("Data type not correctly entered, instantiating int array!\n");
size = sizeof(int);
dat = INT;
}
// Allocate indice size and call array_mem_alloc
Array array;
array.dat = dat;
array.elem = size;
array_mem_alloc(&array, num_indices);
strcpy(array.name, name);
return array;
}
// --------------------------------------------------------------------------------
int append_array(Array *array, void *elements, size_t count) {
// Allocae more memory if necessary
if (array->len count > array->size) {
size_t size = (array->len count) * 2;
void *pointer = realloc(array->array, size * array->elem);
// If memory is full return operations
if (pointer == NULL) {
printf("Unable to allocate memory, exiting.\n");
return 0;
}
// Allocate memory to variables and increment array size
array->array = pointer;
array->size = size;
}
// Append variables and increment the array length
memcpy((char *)array->array array->len * array->elem, elements, count * array->elem);
array->len = count;
return 1;
}
// --------------------------------------------------------------------------------
int preappend_array(Array *array, void *elements, size_t count) {
// Allocae more memory if necessary
if (array->len count > array->size) {
size_t size = (array->len count) * 2;
void *pointer = realloc(array->array, size * array->elem);
// If memory is full return operations
if (pointer == NULL) {
printf("Unable to allocate memory, exiting.\n");
exit(0);
}
// Allocate memory to variables and increment array size
array->array = pointer;
array->size = size;
}
// Preappend variables and increment the array length
memmove(
((char *) array->array) count * array->elem,
array->array,
array->len * array->elem);
memcpy(array->array, elements, count * array->elem);
array->len = count;
return 1;
}
// --------------------------------------------------------------------------------
void replace_int_array_indice(Array *array, int index, int replacement_value) {
// THIS FUNCTION WORKS, BUT I DO NOT THINK IT IS AN EFFICIENT IMPLEMENTATION
// Copy data to intermediate array
int arr[array->len];
memcpy(arr, array->array, array->elem * array->len);
memmove(((char *) array->array), arr index 1, array->len * array->elem);
array->len -= index 1;
// preappend with replacement value
preappend_array(array, &replacement_value, 1);
// preappend with initial indices up to replaced index
int new_arr[index - 1];
memcpy(new_arr, arr, index * array-> elem);
preappend_array(array, &new_arr, index);
}
主程式
#include "array.h"
int main(int argc, const char * argc[]) {
size_t indices = 10;
char name[6] = "array";
dat_type dtype = INT;
Array arr_test = init_array(dtype, indices, name);
int a[6] = {1, 2, 3, 4, 5, 6};
append_array(&arr_test, a, 6);
replace_int_array_indice(&arr_test, 1, 5);
for (int j = 0; j < array_test.len; j ) {
printf("%d\n", int_array_val(&arr_test, j);
}
}
uj5u.com熱心網友回復:
你肯定是想多了。
您只需要替換陣列中的一個值,因此找到偏移量,正確轉換,取消參考并分配:
* (int *) ((char *) array->array index * array->elem) = replacement_value;
或者,在構建基本功能時繼續memcpy使用,并使用它來創建進一步的抽象。
void array_set(Array *array, size_t index, void *data) {
memcpy(
(char *) array->array index * array->elem,
data,
array->elem);
}
void int_array_set(Array *array, size_t index, int value)
{
array_set(array, index, &value);
}
可能要檢查index是否有效。
uj5u.com熱心網友回復:
順便說一句,您的代碼中存在記憶體損壞漏洞。在init_array您使用strcpy(array.name, array);時,名稱只有 20 個位元組長。并且name是用戶控制的。你應該strncpy(array.name, array, sizeof(array.name);改用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/462802.html
