繁体   English   中英

传递给函数后如何撤消对数组的更改

[英]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>用于printfint32_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM