#c #pass-by-reference #dynamic-arrays #c-strings #strcat
#c #передача по ссылке #динамические массивы #c-строки #strcat
Вопрос:
Как мы знаем, функция strcat объединяет одну c-строку в другую, чтобы создать одну большую c-строку, содержащую две другие.
Мой вопрос в том, как создать strcat
функцию, которая работает с двумя динамически распределяемыми массивами.
Желаемая strcat
функция должна быть способна работать для myStr1 и myStr2 любого размера
//dynamic c-string array 1
char* myStr1 = new char [26];
strcpy(myStr1, "The dog on the farm goes ");
//dynamic c-string array 2
char* myStr2 = new char [6];
strcpy(myStr2, "bark.");
//desired function
strcat(myStr1,myStr2);
cout<<myStr1; //would output 'The dog on the farm goes bark.'
Это все, что я смог сделать самостоятельно:
//*amp; indicates that the dynamic c-string str1 is passed by reference
void strcat(char*amp; str1, char* str2)
{
int size1 = strlen(str1);
int size2 = strlen(str2);
//unknown code
//str1 = new char [size1 size2]; //Would wipe out str1's original contents
}
Спасибо!
Комментарии:
1. Вы можете продолжать в том же духе; но не назначайте новое пространство до
str1
тех пор, пока вы не скопируете старую строкуstr1
и не освободите старое пространство2. Я в недоумении, почему
std::string
не используется вместо этой вещи, которую вы опубликовали, от которой у меня глаза кровоточат.
Ответ №1:
Сначала вам нужно лучше понять, как работают указатели. Ваш код, например:
char* myStr1 = new char [25];
myStr1 = "The dog on the farm goes ";
сначала выделяет 25 символов, затем игнорирует указатель на эту выделенную область (технический термин — «утечка») и устанавливает myStr1
указатель на строковый литерал.
Вместо этого этот код должен был использоваться strcpy
для копирования из строкового литерала в выделенную область. За исключением того, что строка состоит из 25 символов, поэтому вам нужно будет выделить место как минимум для 26, поскольку один необходим для ASCII NUL
terminator ( 0x00
) .
Правильный код для этой части должен был быть:
char* myStr1 = new char [26]; // One more than the actual string length
strcpy(myStr1, "The dog on the farm goes ");
Для выполнения конкатенации строк C алгоритм может быть:
- измерьте длины
n1
иn2
двух строк (сstrlen
помощью) n1 n2 1
выделите символы для буфера назначения (1
требуется для завершения строки C)strcpy
первая строка в начале буфераstrcat
вторая строка в буфер (*)delete[]
память для исходных строковых буферов, если они не нужны (если это правильно или нет, зависит от того, кто является «владельцем» строк… эта часть сложна, поскольку строковый интерфейс C этого не указывает).
(*) Это не самый эффективный способ. strcat
переберет все символы строки, чтобы найти, где она заканчивается, но вы уже знаете, что первая длина строки n1
равна, и конкатенацию можно было бы выполнить вместо этого с strcpy
помощью too , выбрав правильное начало as buffer n1
. Еще лучше вместо strcpy
того, чтобы вы могли использовать memcpy
везде, если вы знаете количество, поскольку strcpy
вам нужно будет проверять каждый символ на наличие NUL
терминатора. Однако, прежде чем приступить к такого рода оптимизации, вы должны четко понимать, как все работает … только после того, как код конкатенации строк верен и для вас совершенно очевиден, вы имеете право даже начать думать об оптимизации.
PS: Как только вы получите все это правильно, работоспособно и эффективно, вы поймете, насколько упрощенным является использование std::string
объектов вместо этого, где весь этот запутанный код становится просто s1 s2
.
Комментарии:
1. Мне потребовалось некоторое время, чтобы понять, почему strcpy() — это способ назначения объектов в динамических массивах символов. Это глупая ошибка, назначающая ее как myStr1 = «bark». Я уверен, что это мне очень поможет!
Ответ №2:
Вы выделяете память и указываете свои указатели на эту память. Затем вы перезаписываете указатели, заставляя их указывать куда-то еще. Присвоение, например myStr1
, приводит к тому, что переменная указывает на строковый литерал вместо выделенной вами памяти. Вам нужно скопировать строки в выделенную вами память.
Конечно, это копирование приведет к другой проблеме, поскольку вы, похоже, забываете, что C-строкам нужен дополнительный символ для терминатора. Таким образом, для строки C с 5 символами требуется пространство для шести символов.
Что касается вашей функции конкатенации, вам также нужно выполнить копирование здесь. Выделите достаточно места для обеих строк плюс один символ-терминатор. Затем скопируйте первую строку в начало новой памяти, а вторую строку скопируйте в конец.
Также вам нужна временная переменная указателя для выделяемой вами памяти, так как в противном случае вы «уничтожили бы исходное содержимое str1» (не совсем верно, вы просто str1
указываете где-то в другом месте, теряя исходный указатель).