преобразование char ** в char * или char - PullRequest
1 голос
/ 09 марта 2009

У меня есть старая программа, в которой используется некоторая библиотечная функция, и у меня нет этой библиотеки.

Итак, я пишу эту программу, используя библиотеки c ++. В этом старом коде есть какая-то функция, которая называется вот так

* string = newstrdup («Некоторая строка идет сюда»);

строковая переменная объявлена ​​как char ** string;

Что он может делать в этой функции с именем "newstrdup"? Я пробовал много вещей, но я не знаю, что он делает ... Может кто-нибудь помочь

Ответы [ 6 ]

4 голосов
/ 09 марта 2009

Функция используется для создания копии c-строк. Это часто необходимо, чтобы получить доступную для записи версию строкового литерала. Они (строковые литералы) сами по себе не доступны для записи, поэтому такая функция копирует их в выделенный доступный для записи буфер. Затем вы можете передать их функциям, которые изменяют заданный аргумент, например strtok, который записывает в строку, которую он должен токенизировать.

Я думаю, вы можете придумать что-то вроде этого, так как оно называется new strdup :

char * newstrdup(char const* str) {
    char *c = new char[std::strlen(str) + 1];
    std::strcpy(c, str);
    return c;
}

Вы должны были бы освободить его, когда закончите, используя строку, используя

delete[] *string;

Альтернативный способ написания - использование malloc. Если библиотека старая, она могла использовать ту, которую C ++ унаследовал от C:

char * newstrdup(char const* str) {
    char *c = (char*) malloc(std::strlen(str) + 1);
    if(c != NULL) {
        std::strcpy(c, str);
    }
    return c;
}

Теперь вы должны освободить строку, используя free, когда закончите:

free(*string);

Предпочитайте первую версию, если вы пишете на C ++. Но если существующий код использует free для освобождения памяти снова, используйте вторую версию. Помните, что вторая версия возвращает NULL, если нет памяти для дублирования строки, в то время как первая выдает исключение в этом случае. Еще одно замечание следует сделать о поведении, когда вы передаете аргумент NULL в newstrdup. В зависимости от вашей библиотеки это может быть разрешено или не разрешено. Поэтому вставьте соответствующие проверки в вышеуказанные функции, если это необходимо. В системах POSIX доступна функция с именем strdup, но она не допускает аргументов NULL и не использует оператор C++ new для выделения памяти.

Во всяком случае, я искал с помощью Google codesearch функции newstrdup и нашел немало. Может быть, ваша библиотека в числе результатов:

Google CodeSearch, newstrdup

3 голосов
/ 09 марта 2009

должна быть причина, по которой они написали "новую" версию strdup. Таким образом, должен быть угловой случай, который обрабатывает по-другому. как, возможно, пустая строка возвращает пустую строку.

ответ Литба заменяет strdup , но я думаю, что есть причина, по которой они сделали то, что сделали.

Если вы хотите использовать strdup напрямую, используйте определение, чтобы переименовать его, а не писать новый код.

1 голос
/ 27 июня 2010

Строка *string = newstrdup("Some string goes here"); не показывает каких-либо странностей для newstrdup. Если string имеет тип char **, то newstrdup просто возвращает char *, как и ожидалось. Предположительно string уже был установлен для указания на переменную типа char *, в которую должен быть помещен результат. В противном случае код записывается через неинициализированный указатель.

0 голосов
/ 09 марта 2009

Я думаю, вам нужно посмотреть, что происходит с переменной "string" в коде, так как прототип для функции newstrdup () будет идентичен версии библиотеки strdup ().

Есть ли в коде бесплатные (* строковые) вызовы?

Это может показаться странным, если только он не хранит внутри себя копию дублированной строки и снова не возвращает указатель на ту же строку.

Опять спрашиваю почему?

0 голосов
/ 09 марта 2009

Похоже, он написал функцию strdup () для работы с существующим указателем, возможно, для перераспределения его в новый размер и последующего заполнения его содержимого. Вероятно, он делает это, чтобы повторно использовать тот же указатель в цикле, где * строка будет часто меняться, предотвращая утечку при каждом последующем вызове strdup ().

Я бы, наверное, реализовал это как string = redup (& string, "new contents") ... но это только я.

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

Вот отрывок моей функции 'redup', которая может делать что-то похожее на то, что вы опубликовали, просто по-другому:

int redup(char **s1, const char *s2)
{
    size_t len, size;

    if (s2 == NULL)
        return -1;

    len = strlen(s2);
    size = len + 1;

    *s1 = realloc(*s1, size);

    if (*s1 == NULL)
        return -1;

    memset(*s1, 0, size);
    memcpy(*s1, s2, len);

    return len;
}

Конечно, мне, вероятно, следует сохранить копию * s1 и восстановить ее в случае сбоя realloc (), но мне не нужно было получать этот параноик.

0 голосов
/ 09 марта 2009

newstrdup, вероятно, создает новую строку, которая является дубликатом переданной строки; он возвращает указатель на строку (которая сама по себе указывает на символы).

...