Как мне использовать char **? (указатель на массив символов) - PullRequest
0 голосов
/ 13 апреля 2019

Так что я пытаюсь сделать char**, я полностью понимаю, как это работает в фоновом режиме и все такое, но я не понимаю, как написать код для него.Я хочу сделать указатель на массив символов, который имеет имя в нем.Мне нужна помощь с хранением строки в нем (с помощью strcpy ()) и распечатать его после этого.

char** name = (char**)malloc((strlen("MyName") + 1) * sizeof(char*));
strcpy(name, "MyName"); // I get an error right here

Ответы [ 3 ]

0 голосов
/ 13 апреля 2019

Первое, что вы должны понять, это то, что объявление переменной как единственного указателя или двойного указателя (или любого другого n указателя) на самом деле не говорит о том, содержит ли базовая переменная единственное значение или массив значений.

Один указатель указывает на адрес памяти, на котором хранится фактическое значение.Двойной указатель указывает на адрес памяти, на котором хранится один указатель и т. Д.

Теперь, чтобы создать указатель на массив указателей на символы, вы можете использовать один указатель на символы (char*), но яРекомендуется использовать двойной символ указателя (char**) для удобства обслуживания.

Рассмотрим следующий код:

char** names = (char**)malloc(100 * sizeof(char*));

Он выделит пространство памяти для 100 указателей на символы (char*) накучи и вернуть вам двойной указатель (char**) на первый единственный указатель (char*) в этом пространстве памяти.Это означает, что вы сможете сохранить 100 указателей на символы (или 100 имен в вашем случае) в этом пространстве памяти.Затем вы можете использовать их следующим образом:

char* name0 = "First Name"; // Saved on stack
char* name1 = malloc((strlen("Second Name") + 1) * sizeof(char));  // Saved on heap
strcpy(name1, "Second Name");

names[0] = name0;
names[1] = name1;

Также обратите внимание, что при сохранении строки в куче необходимо добавить еще одно место для нулевого символа (вручную).

0 голосов
/ 13 апреля 2019

Итак, я пытаюсь сделать char**, я полностью понимаю, как это работает в фоновом режиме и все такое, но я не понимаю, как написать код для него.

Умм ... Нет, не совсем.

Чтобы объявить указатель на символ , вы просто decalre:

    char *name = malloc (strlen("MyName") + 1);

Почему?Когда вы делаете вызов malloc, malloc выделяет блок памяти, предоставляя strlen("MyName") + 1 байтов, и возвращает начальный адрес этому блоку памяти, который вы назначаете для name.Затем вы можете скопировать "MyName" в имя (с 1 байтом, оставшимся для символа , заканчивающегося нулем *1021*).Подход может быть следующим:

    size_t len = strlen ("MyName");
    char *name = malloc (len + 1);      /* allocate len + 1 bytes */
    if (name == NULL) {                 /* validate EVERY allocation */
        perror ("malloc-name");
        /* handle error by returning or exiting */
    }
    memcpy (name, "MyName", len + 1);   /* no need to scan again for \0 */

    /* do something with name - here */

    free (name);    /* don't forget to free name when you are done */

Что тогда делает char**?

Когда вы имеете дело с pointer-to-pointer-to-char , сначала вы должны выделить какое-то количество указателей , затем вы можете выделить и назначить блок памяти для каждого из указателей и использовать каждый указатель так же, как вы использовали name выше.

Например:

    /* array of ponters to string-literals for your source of strings */
    char *band[] = { "George", "Ringo", "Paul", "John" };
    char **names;
    size_t nmembers = sizeof band / sizeof *band;

    /* allocate nmembers pointers */
    names = malloc (nmembers * sizeof *names);
    if (names == NULL) {                /* validate EVERY allocation */
        perror ("malloc-name_pointers");
        /* handle error by returning or exiting */
    }

    /* now loop allocating for each name and copy */
    for (size_t i = 0; i < nmembers; i++) {
        size_t len = strlen (band[i]);      /* get length */
        names[i] = malloc (len + 1);        /* allocate */
        if (names[i] == NULL) {             /* validate EVERY allocation */
            perror ("malloc-names[i]");
            /* handle error by returning or exiting */
        }
        memcpy (names[i], band[i], len + 1);/* no need to scan again for \0 */
    }

    /* output each */
    for (size_t i = 0; i < nmembers; i++)
        printf ("member[%zu]: %s\n", i + 1, names[i]);

Освобождение names - это двухэтапный процесс.Вы должны освободить память, выделенную для каждого из names указателей, а затем освободить сами указатели, например,

    for (size_t i = 0; i < nmembers; i++)
        free (names[i]);    /* free each allocated names[i] */
    free (names);           /* free pointers */

Теперь, надеюсь, вам ближе "... fully understand how it works".Дайте мне знать, если у вас есть какие-либо вопросы.

0 голосов
/ 13 апреля 2019

Если вы действительно хотите указатель на массив символов, вы можете сделать следующее:

char** name = (char**)malloc(sizeof(char*)); //initialize the pointer
*name = (char*)malloc((strlen("MyName") + 1) * sizeof(char)); //initialize the array
strcpy(*name, "MyName");
...