Как правильно получить указатель на строку в стиле C в качестве аргумента и иметь возможность выделить память или изменить ее?
У меня есть следующий метод подписи:
int get_name(char* &name_out);
То, что я хотел бы иметь, это выделить память размером с name
за name_out
а затем скопируйте содержимое name
в name_out
,
Или было бы лучше изменить его на:
int get_name(char &name_out[], int size);
и позволить пользователю функции сначала выделить и отследить память, и вернуть ошибку, если размер данного массива недостаточно велик, чтобы содержать строку?
Единственное, что мне не нравится в этом, это то, что это потребует от пользователя get_name()
функция, чтобы иметь представление о длине строки имени.
Я чувствую, что было бы избыточно иметь две функции int get_name_length();
а также get_name(char* name_out);
Поскольку это часть задания по программированию, существуют условия:
- Строковый класс не допускается.
- Строки в стиле C должны быть использованы.
- Векторы не могут быть использованы.
- Функция должна возвращать int для обозначения ошибки.
- Обработка исключений не допускается.
Спасибо.
2 ответа
Стандартный способ C сделать это состоит в том, чтобы передать функции два указателя:
int getName(char** name_out, size_t* size_out);
Это имеет несколько преимуществ:
Вызывающая сторона свободна предварительно выделить память / повторно использовать выделение.
Вызываемый может свободно отрегулировать распределение с помощью
realloc()
(при условии, что строка в стиле C выделена сmalloc()
) или через паруdelete[]
/new[]
,Получение адреса является явным. Т.е. на сайте звонка вы бы написали:
char* name = null_ptr; size_t size = 0; if(getName(&name, &size)) handleError();
Явный
&
Оператор очень ясно дает понять, что функцияgetName()
может изменить обе переменные. Если вы идете со ссылками, вы не можете различить вызов по ссылке и вызов по значению, не глядя на объявление функции.
Также обратите внимание, что тип, используемый для размеров размещения size_t
: это тип, который гарантированно сможет содержать размер всего используемого адресного пространства.
Если я правильно понимаю, что вы пытаетесь сделать, это реализовать вариант для 'strcpy'.
Основное различие заключается в том, что вы передаете ответственность за распределение своей функции копирования, в то время как strcpy оставляет ее пользователю. Если это производственный код, то я рекомендую придерживаться подхода "strcpy", к которому привыкла отрасль.
Если это только для игры, оберните strcpy функцией, которая выполняет выделение, и придерживайтесь интерфейса strcpy.