Как я могу создать копию очереди на C?

#c #queue #memcpy

#c #очередь #memcpy

Вопрос:

Я пытаюсь СКОПИРОВАТЬ очередь в другую очередь, чтобы, если я уничтожу одну, она не уничтожит другую.

Я пытался использовать memcpy этот способ:

 memcpy(queue1, queue2, sizeof(queue2));
  

Но я получаю следующую ошибку:

ожидается ‘void * restrict’, но аргумент имеет тип ‘Queue’

Возможно ли скопировать одну очередь в другую?

Редактировать

Это структура очереди:

 typedef char *Following;

typedef struct _NodeQ {
    Following element;
    struct _NodeQ * next;
} NodeQ;


typedef struct {
    int error;
    NodeQ * first;
    NodeQ * last;
} Queue; 
  

Комментарии:

1. под «очередью» вы подразумеваете «массив»? Пожалуйста, лучше объясните, что такое ваша очередь.

2. Под очередью я подразумеваю: динамический FIFO. Я отредактировал вопрос, чтобы вы могли видеть структуру.

Ответ №1:

memcpy это определенно не так, потому что это приведет вас только к выполнению «мелкой копии». Если вы считаете, что ваш объект может хранить указатели на внешние данные, поверхностная копия этого объекта будет указывать на те же самые внешние данные, а не дублировать все («глубокая копия»).

мелкая-против-глубокой-копии-img
(источник изображения)

Метод выполнения глубокой копии полностью зависит от реализации. Похоже, что ваша очередь использует простую реализацию связанного списка (см., Как Каждая NodeQ структура содержит указатель на другую NodeQ структуру, которая имеет указатель на другую и так Далее). Это очень распространено в C. Сложная часть заключается в том, чтобы выяснить, как скопировать часть «данных» каждого объекта внутри очереди (в данном случае переменную Following типа). Я не могу сказать, какую библиотеку или фреймворк вы используете, который определяет Queue тип, вам следует обратиться к некоторой документации, которая поможет вам разобраться в деталях. Кто знает, может быть, вы найдете поддерживаемый библиотекой способ копирования так, как вы хотите. Тем не менее, я попытаюсь сделать то, что вы хотите, с некоторыми предположениями.

Предположения с этого момента и далее

Это только предположение, но похоже Following , что оно может представлять строку, поскольку это указатель на символ. Код, который я написал ниже, использует это предположение. Обратите внимание, что это непроверенный и немного поспешный способ, я просто пытаюсь проиллюстрировать, как может выглядеть выполнение глубокого копирования вручную в вашем сценарии.

 Queue queue2;
NodeQ *e2, *e2prev = NULL, *e2first = NULL;

// Iterate through all elements of the first queue
for (NodeQ *e1 = queue1.first; e1; e1 = e1->next) {

    // Allocate memory for the new element of queue 2
    if (!(e2 = (NodeQ*)malloc(sizeof(NodeQ)))) {
        printf("not enough memoryn");
    }

    // Remember the first element of queue for future use
    if (!e2first)
        e2first = e2;

    // Note that strlen here could cause a segfault if my guess that "element" is a string is wrong
    size_t buflen = strlen(e1->element)   1; //  1 for null terminator
    if (!(e2->element = (Following)malloc(sizeof(char) * buflen))) {
        printf("not enough memoryn");
    }
    strcpy(e2->element, e1->element);

    e2->next = NULL;

    // Link new element with previous element
    if (e2prev)
        e2prev->next = e2;

    e2prev = e2;
}

queue2.error = queue1.error;
queue2.first = e2first;
queue2.last  = e2;
  

Ответ №2:

Ваш компилятор предупреждает вас, что memcpy в качестве первого аргумента требуется два указателя. Это был бы правильный способ копирования:

 memcpy(amp;queue1, amp;queue2, sizeof(queue2));
  

Приведенная выше строка перезапишет структуру queue1 содержимым queue2 , эффективно копируя quque2 queue1 .