[英]How to undo changes to an array after passing to a function
更改数组后,是否有任何方法可以撤消操作或获取原始数组,如下所示。
#include <stdio.h>
void function(int array[]){
array[2] = 20;
//do some extra work
return;
}
int main(void){
int array[5] = {1,2,3,4,5};
function(array);
// code which has to use original array
return 0;
}
简短地说:否。您无法还原操作-无论如何都不是简单的方法。 您可能想要的是在function()
具有数据的本地副本。 您可以通过创建一个新数组并将其复制到您的第一个数组来实现:
int array[5] = whatever;
int array_copy[5];
memcpy(array_copy, array, 5*sizeof(int));
function(array_copy);
//You have your array now unchanged
如果您确实不想这样做,则可以使用另一种方法将数组封装到结构中,然后让编译器为您合成复制操作。 但是,对于这种结构来说,存在严重的缺点,因为对于这样的大型结构,您可能最终会浪费您的堆栈。
struct MyArray {
int array[5];
};
void function(struct MyArray m) {
//This will create a local copy of m
int i;
for (i = 0; i < 5; i++) {
m.array[i] = i + 1;
}
}
void initialize(struct MyArray* m) {
int i;
assert(m != NULL);
for (i = 0; i < 5; i++) {
m->array[i] = i;
}
}
int main(int argc, char *argv[]) {
struct MyArray m;
int i;
initialize(&m);
function(m);
//Your m here will be untouched
return 0;
}
#include <stdio.h>
void function(int array[]){
array[2] = 20;
}
void save(const char *filename, const void *data, size_t size);
void undo(const char *filename);
int main(void){
int array[5] = {1,2,3,4,5};
save("save_2", &array[2], sizeof(int));//array[2] save to file
function(array);
undo("save_2");//restore
save("save_all", array, sizeof(array));
function(array);
undo("save_all");
// code which has to use original array
for(int i=0;i<5;++i)
printf("%d\n", array[i]);
remove("save_2");
remove("save_all");
return 0;
}
void save(const char *filename, const void *data, size_t size){
FILE *fp = fopen(filename, "wb");
fwrite(&data, sizeof(void *), 1, fp);
fwrite(&size, sizeof(size_t), 1, fp);
fwrite(data, size, 1, fp);
fclose(fp);、
}
void undo(const char *filename){
FILE *fp = fopen(filename, "rb");
void *data;
size_t size;
fread(&data, sizeof(void*), 1, fp);
fread(&size, sizeof(size_t), 1, fp);
fread(data, size, 1, fp);
fclose(fp);
}
您可以将两个32位整数(旧/新)打包为64位整数,例如:
#include <stdio.h>
#include <stdint.h>
void function(int64_t array[])
{
array[2] = (array[2] << 32) | 20;
}
void printarr(int64_t array[], size_t n)
{
size_t i;
for (i = 0; i < n; i++) {
printf("%d ", (int32_t)(array[i]));
}
printf("\n");
}
int main(void)
{
int64_t array[] = {1, 2, 3, 4, 5};
size_t i, n = sizeof(array) / sizeof(array[0]);
function(array);
puts("After function:");
printarr(array, n);
for (i = 0; i < n; i++) {
if (array[i] >> 32 != 0) /* Changed */
array[i] = array[i] >> 32; /* Undo */
}
puts("Original values:");
printarr(array, n);
return 0;
}
输出:
After function:
1 2 20 4 5
Original values:
1 2 3 4 5
注意:
当然,如果您使用短值来节省空间,则可以在32位整数中打包两个16位整数。
为了便携使用PRId32
格式(定义在<inttyes.h>
用于printf
和int32_t
:
printf("%"PRId32" ", (int32_t)x);
另一种方法:
如果这些更改是按正整数顺序进行的,则可以更改符号(以标识更改),并使用realloc
仅存储更改:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *value;
size_t length;
} t_undo;
void function(t_undo *undo, int array[], int index, int value)
{
undo->value = realloc(undo->value, sizeof(int) * (undo->length + 1));
/* check realloc */
undo->value[undo->length++] = array[index];
array[index] = -value;
}
void printarr(int array[], size_t n)
{
size_t i;
for (i = 0; i < n; i++) {
printf("%d ", abs(array[i]));
}
printf("\n");
}
int main(void)
{
t_undo *undo;
int array[] = {1, 2, 3, 4, 5};
size_t i, j = 0, n = sizeof(array) / sizeof(array[0]);
undo = malloc(sizeof(*undo));
/* check malloc */
undo->value = NULL;
undo->length = 0;
function(undo, array, 2, 20);
puts("After function:");
printarr(array, n);
for (i = 0; i < n; i++) {
if (array[i] < 0) /* Changed */
array[i] = undo->value[j++]; /* Undo */
}
puts("Original values:");
printarr(array, n);
free(undo->value);
free(undo);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.