Как скопировать значения массива указателей на символы? - PullRequest
0 голосов
/ 16 октября 2018

Как мне скопировать значения в массиве указателей на символы в другой массив?Я действительно потерян, пожалуйста, помогите мне.Это то, что я имею до сих пор.

char **copy_values(char **values) {
    char **val;

    //do something 
    return val;
}

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Чтобы полностью скопировать указатели и значения ( на что они указывают ), вам необходимо знать три вещи:

  1. Сколько указателей я могу сделатьесть?
  2. Нужно ли мне также копировать то, на что они указывают ?;и если да, то
  3. Сколько указателей у меня есть, что указывает на то, что мне нужно скопировать.

Когда вы объявляете указатель на указатель на символ , онэто просто неинициализированный указатель.Чтобы обеспечить возможность адресации более чем одного адреса, вы затем выделяете некоторое необходимое количество указателей (скажем, MAXPTRS).Например:

#define MAXPTRS 32
...
char **values = NULL;

values = malloc (MAXPTRS * sizeof *values);   /* allocate MAXPTRS pointers */
if (values == NULL) {                         /* validate/handle error */
    perror ("malloc-values");
    /* handle error */
}

Теперь у вас есть MAXPTRS (32) указатели для работы.Если вы затем выделите хранилище для, скажем, 8 из них, например,

size_t count = 0;
while (fgets (buf, sizeof buf, stdin)) {
    size_t len = strlen (buf);
    values[count] = malloc (len + 1);
    if (!values[count]) {
        perror ("malloc-values[count]");
        break;
    }
    memcpy (values[count++], buf, len + 1);
}

Итак, на этом этапе в примере у вас выделено 32 указателей и 8 из этих указателей, указывающих на блоки памятиудержание строк, считанных из stdin.

Если вы хотите скопировать всю структуру, вы должны не только скопировать исходные указатели 32, но и блоки памяти 8, на которые указывают инициализированные указатели,Если вам не удастся скопировать указанные блоки памяти и просто назначить указатели (например, val[i] = values[i]), то любые изменения в оригинале, например, values[2], будут автоматически отражены в val[2] (это может или не может бытьто, что вы хотите)

Чтобы полностью скопировать указатель values на указатель на символ и вернуть val, содержащий такое же количество указателей, с копией каждой выделенной строки, содержащейся в исходном массиве valuesуказатели, вам нужна «глубокая копия», где вы копируете не только указатели, но и дублируете их содержимое, например,

char **copystrings (const char **values, size_t nptrs, size_t filled) 
{
    char **val = NULL;

    val = malloc (nptrs * sizeof *val);     /* allocate nptrs pointers */
    if (!val) {                             /* validate */
        perror ("malloc-val");
        return NULL;
    }

    for (size_t i = 0; i < filled; i++) {   /* loop over each filled ptr */
        size_t len = strlen (values[i]);    /* get length of string */
        val[i] = malloc (len + 1)           /* allocate storare val[i] */
        if (!val[i]) {                      /* validate */
            perror ("malloc-val[i]");
            break;
        }
        memcpy (val[i], values[i], len + 1);    /* copy to val[i] */
    }

    return val;     /* return val (may contain less than filled allocated) */
}

( примечание: не скомпилировано, также будетРекомендуется передать filled в качестве указателя и обновить filled значением i перед возвратом, чтобы обеспечить возможность проверки того, что все блоки памяти для filled указателей были продублированы. В противном случае ошибка mallocval[i] приведет к тому, что будет выделено и скопировано менее filled, и вы не сможете узнать - если вы не использовали calloc для обнуления новой памяти при выделении для val)

Глубокая копия позволяет изменять скопированные значения без изменения данных по адресам, указанным указателями в values.Если вы не изменяете данные (например, вы просто хотите отсортировать указатели с помощью qsort, тогда нет необходимости в «глубоком копировании», а вам нужно только выделить количество указателей filled и назначить адрес изvalues до val.

Понимание того, что вам нужно, и различия в том, как вы добиваетесь его достижения, является ключевым.

(спасибо @ 4386427 за ловлюпара упущений)

0 голосов
/ 16 октября 2018

Как скопировать значения в массиве указателей на символы в другой массив?

Что-то вроде:

char **copy_values(char **values, int size) {
    char **val = malloc(size * sizeof *val);
    if (val) memcpy(val, values, size * sizeof *val);
    return val;
}

Запомните free выделенноепамять, когда закончил с этим

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...