Как * char + * char в C ++?

0

Вот проблема, с которой я столкнулся недавно.

Если я сделаю что-то вроде этого:

string str1 = "some";
string str2 = "thing";
cout << str1 + str2 << endl;

Я получу следующий результат: something

Но у меня есть только это:

char *chr1 = "How do"
char *chr2 = "I do this?"

и мне нужно получить следующий результат

Итак, как мне это сделать? И да, мне действительно нужен char *.

  • 0
    Если все, что вы делаете, это печатаете их, вы можете просто сделать cout << chr1 << chr2 << endl; Или, если вы действительно хотите добавить пробел: cout << chr1 << ' ' << chr2 << endl;
  • 0
    Не только печать, мне нужно получить переменную char * в качестве контейнера результатов, которая мне нужна для дальнейшего использования.
Показать ещё 2 комментария
Теги:
pointers
merge
char

7 ответов

4
Лучший ответ

Вам нужно создать буфер с размером 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
    Поскольку ОП - новичок, возможно, будет хорошей идеей, почему вы выделяете +1 символа?
  • 0
    если вам нужно удалить, лучше используйте boost::unique_ptr в C ++ или std::unique_ptr и std::make_unique в C ++ 11.
Показать ещё 4 комментария
3

Хотя 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();

Преимущества:

  • Может быть написано как oneliner, без каких-либо дальнейших дебакаций буферов и т.д.
  • Возможно облегчить манипуляции с помощью методов std::string и связанных с ними функций

Недостатки:

  • Дополнительные накладные расходы
  • Только const char* может быть получен, если требуется char*, необходимо снова скопировать c-строку

Учтите, что возвращаемый const char* напрямую указывает на внутренний буфер объекта std::string. Таким образом, указатель остается в силе только до тех пор, пока объект std::string не выходит за пределы области видимости. Поэтому, используя это с временным вроде этого const char* result = (std::string(str1) + str2).c_str(); это очень плохая идея (тогда как в вызове функции было бы законно писать подобное, поскольку временное остается до тех пор, пока вызов не вернется).

  • 0
    c_str (); Готово, приложение упало ...
  • 0
    c_str() имеет No-throw guarantee . Убедитесь, что указатель остается действительным только до тех пор, пока std::string остается действительным. Полученный указатель напрямую указывает на буфер объекта std::string . Это особенно важно при работе с временными. Я думаю, что я включу это в мой ответ
Показать ещё 4 комментария
2

Вы должны использовать strcat() в таком случае.
Как указано в комментариях, вам понадобится нечто вроде char[] в качестве буфера для новой строки.

  • 0
    Но будьте осторожны, невозможно использовать какой-либо из указателей строк в вопросе в качестве места назначения для strcat .
  • 0
    Это правда, я буду редактировать в буфер символов []; Благодарю.
Показать ещё 3 комментария
1

Поскольку это 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++, насколько это возможно.

0

Несколько соображений:

  • Сначала вы должны объявить 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'.
    
  • 0
    «Мне нужно char* » -> «сначала вы должны объявить str1 и str2 как const char* " :)
  • 1
    @ScarletAmaranth, никогда не поздно придерживаться передового опыта, строковые литералы являются константными как в C, так и в C ++, и опускание const является ошибкой, а в C ++ 11 это даже незаконно.
Показать ещё 3 комментария
0

Конкатенация строк не была необходима в первую очередь; вы можете продолжить использование оператора вставки потока << для выполнения эффективной конкатенации (вместо использования + для формирования одного, временного объекта 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-строки не инициализируются строковыми литералами.

0

Обычно ответом будет "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
  • 0
    Оооо ... в основном вместо того, чтобы просто использовать std::string в качестве контейнера и вызывать c_str() для получения const char* вы предлагаете использовать std::unique_ptr<char[]> в качестве контейнера и вызывать get() чтобы получить const char* ?
  • 0
    OP указал, что он нуждается в char* . Поскольку он не указывает, почему std :: string не будет в порядке, мы должны принять его слово. Это решение на основе char *, с добавлением RAII «безопасность». OP может использовать char * напрямую, но требует дополнительной строки (вызов delete[] ), не добавляет никаких преимуществ и делает код хуже / менее безопасным ,
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню