Вот проблема, с которой я столкнулся недавно.
Если я сделаю что-то вроде этого:
string str1 = "some";
string str2 = "thing";
cout << str1 + str2 << endl;
Я получу следующий результат: something
Но у меня есть только это:
char *chr1 = "How do"
char *chr2 = "I do this?"
и мне нужно получить следующий результат
Итак, как мне это сделать? И да, мне действительно нужен char *
.
Вам нужно создать буфер с размером strlen(chr1) + strlen(chr2) + 1 + 1
, (последний +1
поскольку strlen возвращает длину строки без нуль-терминатора, но c-строка должна заканчиваться нулевым терминатором), тогда скопируйте первую строку в новый буфер с помощью str(n)cpy
а затем используйте str(n)cat
.
char* buffer = new char[strlen(chr1) + strlen(chr2) + 1 + 1];
strcpy(buffer, chr1);
strcat(buffer, " ");
strcat(buffer, chr2);
// use buffer
delete[] buffer;
+1
символа?
boost::unique_ptr
в C ++ или std::unique_ptr
и std::make_unique
в C ++ 11.
Хотя strcat()
, вероятно, является лучшим решением, как уже упоминалось ScarletAmanranth, есть и другое.
Сначала можно также преобразовать c-строки в std::string
, выполнить любые требуемые операции над ними, а затем преобразовать результат обратно в c-строку. В некоторых случаях это может лучше соответствовать вашим потребностям.
Пример:
const char* str1 = "foo";
const char* str2 = "bar";
std::string combined = std::string(str1) + str2; // notice std::string + char* => std::string
const char* result = combined.c_str();
Преимущества:
std::string
и связанных с ними функцийНедостатки:
const char*
может быть получен, если требуется char*
, необходимо снова скопировать c-строку Учтите, что возвращаемый const char*
напрямую указывает на внутренний буфер объекта std::string
. Таким образом, указатель остается в силе только до тех пор, пока объект std::string
не выходит за пределы области видимости. Поэтому, используя это с временным вроде этого const char* result = (std::string(str1) + str2).c_str();
это очень плохая идея (тогда как в вызове функции было бы законно писать подобное, поскольку временное остается до тех пор, пока вызов не вернется).
c_str()
имеет No-throw guarantee
. Убедитесь, что указатель остается действительным только до тех пор, пока std::string
остается действительным. Полученный указатель напрямую указывает на буфер объекта std::string
. Это особенно важно при работе с временными. Я думаю, что я включу это в мой ответ
Вы должны использовать strcat()
в таком случае.
Как указано в комментариях, вам понадобится нечто вроде char[]
в качестве буфера для новой строки.
strcat
.
Поскольку это C++, должен быть кто-то, предлагающий то, что я собираюсь предложить. Используйте stringstream
.
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main() {
char *chr1 = "How do";
char *chr2 = "I do this?";
stringstream ss;
ss << chr1 << chr2;
string result = ss.str();
char* final = (char*) calloc(result.size()+1, sizeof(char));
strcpy(final, result.c_str());
cout << final << endl;
delete [] chr1, chr2, final;
return 0;
}
calloc(int size, sizeof([type]))
выделяет всю память, необходимую для сохранения последнего char*
. Таким образом, вы можете добавить два символа вместе C++. Однако то, что вы хотите сделать, больше похоже на C, но поскольку вы находитесь в C++, вы можете использовать методы, которые являются частью C++, насколько это возможно.
Несколько соображений:
chr1
и chr2
как const char *
, а не char *
потому что попытка изменить строковый литерал - это неопределенное поведение.operator +
по указателям включает в себя арифметику указателя, char *
не является особенным в этом отношении. Если вам нужно конкатенировать строки, вам нужно выделить буфер, в котором вы копируете две строки один за другим. В существующих ответах используются простые старые C-функции (кроме Paranaix), но в C++ было бы более идиоматично, если бы вы создали stringstream, который вы используете как std::cout
:
#include <string>
#include <stringstream>
std::ostringstream ss; ss << chr1 << " " << chr2;
const std::string s = ss.str();
const char *result = s.c_str(); // you can use this pointer during the scope of 's'.
char*
» -> «сначала вы должны объявить str1 и str2 как const char*
" :)
const
является ошибкой, а в C ++ 11 это даже незаконно.
Конкатенация строк не была необходима в первую очередь; вы можете продолжить использование оператора вставки потока <<
для выполнения эффективной конкатенации (вместо использования +
для формирования одного, временного объекта std::string
затем для вставки этой результирующей строки)
std::string str1 = "some";
std::string str2 = "thing";
std::cout << str1 << str2 << std::endl;
И поскольку это свойство потока, а не строки, вы можете сделать это с помощью ввода char*
:
const char* chr1 = "How do "
const char* chr2 = "I do this?"
std::cout << chr1 << chr2 << std::endl;
// Output: How do I do this?
Обратите внимание на то, что я добавил необходимый const
для строковых литералов; вы можете удалить его, если и только если ваши C-строки не инициализируются строковыми литералами.
Обычно ответом будет "use std :: string".
И да, мне действительно нужен символ *.
Не просто печать, мне нужно получить char * variable в качестве контейнера результатов, который мне нужен для более удобного использования.
... но в этом случае:
#include <cstring>
std::size_t len1 = std::strlen(str1);
std::size_t len2 = std::strlen(str2);
// unique_ptr: automated lifetime management
// 1 for '\0' terminator
std::unique_ptr<char[]> buffer( new char[len1 + len2 + 1] );
std::copy_n(str1, len1, buffer.get());
std::copy_n(str2, len2, buffer.get() + len1);
buffer.get()[len1 + len2] = '\0'; // after this, buffer.get()
// points to your string
std::string
в качестве контейнера и вызывать c_str()
для получения const char*
вы предлагаете использовать std::unique_ptr<char[]>
в качестве контейнера и вызывать get()
чтобы получить const char*
?
char*
. Поскольку он не указывает, почему std :: string не будет в порядке, мы должны принять его слово. Это решение на основе char *, с добавлением RAII «безопасность». OP может использовать char * напрямую, но требует дополнительной строки (вызов delete[]
), не добавляет никаких преимуществ и делает код хуже / менее безопасным ,
cout << chr1 << chr2 << endl;
Или, если вы действительно хотите добавить пробел:cout << chr1 << ' ' << chr2 << endl;