Подтвердить что ты не робот

Как скопировать строку в массив char в С++, не переходя через буфер

Я хочу скопировать строку в массив char и не перегружать буфер.

Итак, если у меня есть массив char размером 5, тогда я хочу скопировать максимум 5 байтов из строки в него.

какой код для этого?

4b9b3361

Ответ 1

Прежде всего, strncpy почти наверняка не то, что вы хотите. strncpy был разработан для определенной цели. Он в стандартной библиотеке почти исключительно потому, что он уже существует, а не потому, что он вообще полезен.

Вероятно, самый простой способ сделать то, что вам нужно, - это что-то вроде:

sprintf(buffer, "%.4s", your_string.c_str());

В отличие от strncpy, это гарантирует, что результат будет завершен NUL, но не будет заполнять дополнительные данные в целевом объекте, если источник короче указанного (хотя последний не является серьезной проблемой, когда конечная длина равна 5).

Ответ 2

Это именно то, что делает функция копирования std::string.

#include <string>
#include <iostream>

int main()
{

    char test[5];
    std::string str( "Hello, world" );

    str.copy(test, 5);

    std::cout.write(test, 5);
    std::cout.put('\n');

    return 0;
}

Если вам требуется нулевое завершение, вы должны сделать что-то вроде этого:

str.copy(test, 4);
test[4] = '\0';

Ответ 3

Используйте функцию strlcpy неработающая ссылка, а материал не найден на целевом сайте если ваша реализация обеспечивает один (функция не входит в стандартную библиотеку C), но она довольно широко признана в качестве де-факто стандартного имени для "безопасной" функции копирования с ограниченной длиной для строк с нулевым завершением.

Если ваша реализация не предоставляет функцию strlcpy, выполните ее самостоятельно. Например, что-то вроде этого может работать для вас

char *my_strlcpy(char *dst, const char *src, size_t n)
{
  assert(dst != NULL && src != NULL);

  if (n > 0)
  {
    char *pd;
    const char *ps;

    for (--n, pd = dst, ps = src; n > 0 && *ps != '\0'; --n, ++pd, ++ps)
      *pd = *ps;

    *pd = '\0';
  }

  return dst;
}

(Фактически, принятый де-факто strlcpy возвращает size_t, поэтому вы можете предпочесть реализовать принятую спецификацию вместо того, что я сделал выше).

Остерегайтесь ответов, рекомендующих использовать strncpy для этой цели. strncpy не является безопасной функцией ограничения длины строки и не предполагается использовать для этой цели. Хотя вы можете заставить strncpy "работать" для этой цели, он по-прежнему сродни приводу деревянных винтов молотком.

Ответ 4

Некоторые интересные версии libc предоставляют нестандартную, но большую замену для strcpy(3)/strncpy(3) - strlcpy(3).

Если ваш нет, исходный код свободно доступен здесь из OpenBSD.

Ответ 5

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

Во-первых, как отметил AndreyT в комментариях к этому вопросу, методы усечения (snprintf, strlcpy и strncpy) часто не являются хорошим решением. Часто бывает лучше проверить размер строки string.size() на длину буфера и вернуть/выбросить ошибку или изменить размер буфера.

Если в вашей ситуации усечение в порядке, IMHO, strlcpy является лучшим решением, являющимся самым быстрым/наименьшим издержками, который обеспечивает null прекращение. К сожалению, его не во многих/всех стандартных дистрибутивах, и поэтому он не переносится. Если вы делаете много из них, возможно, стоит выполнить вашу собственную реализацию, AndreyT дал пример . Он работает в O (длина результата). Также ссылочная спецификация возвращает количество скопированных байтов, что может помочь в обнаружении усечения источника.

Другими хорошими решениями являются sprintf и snprintf. Они являются стандартными и переносимы и обеспечивают безопасный результат с нулевым завершением. У них больше накладных расходов, чем strlcpy (разбор спецификатора строки формата и списка переменных аргументов), но если вы не делаете много из них, вы, вероятно, не заметите разницы. Он также работает в O (длина результата). snprintf всегда безопасен и что sprintf может переполняться, если вы неправильно определили спецификатор формата (как отмечали другие, строка формата должна быть "%.<N>s" not "%<N>s"). Эти методы также возвращают количество копируемых байтов.

Решением специального случая является strncpy. Он работает в O (длина буфера), потому что, если он достигнет конца src, он отбрасывает оставшуюся часть буфера. Полезно только в том случае, если вам нужно обнулить хвост буфера или уверены, что длина строк назначения и источника одинакова. Также обратите внимание, что он небезопасен тем, что он не обязательно завершает нуль. Если источник усечен, то null не будет добавлен, поэтому вызовите последовательность с нулевым присвоением для обеспечения нулевого завершения: strncpy(buffer, str.c_str(), BUFFER_LAST); buffer[BUFFER_LAST] = '\0';

Ответ 6

void stringChange(string var){

    char strArray[100];
    strcpy(strArray, var.c_str()); 

}

Я думаю, это должно сработать. он скопирует строку формы в массив char.

Ответ 7

std::string my_string("something");
char* my_char_array = new char[5];
strncpy(my_char_array, my_string.c_str(), 4);
my_char_array[4] = '\0'; // my_char_array contains "some"

С strncpy вы можете скопировать не более n символов из источника в пункт назначения. Однако обратите внимание, что если длина строки источника не превышает n символов, назначение не будет завершено нулем; вы должны поместить в него конечный нулевой символ.

A char массив длиной 5 может содержать не более строки из 4 символов, так как пятый должен быть завершающим нулевым символом. Следовательно, в приведенном выше коде n = 4.

Ответ 8

std::string str = "Your string";
char buffer[5];
strncpy(buffer, str.c_str(), sizeof(buffer)); 
buffer[sizeof(buffer)-1] = '\0';

Последняя строка требуется, потому что strncpy не гарантируется, что NUL завершает строку (вчера обсуждалась мотивация).

Если вы использовали широкие строки, вместо sizeof(buffer) вы использовали бы sizeof(buffer)/sizeof(*buffer) или, что еще лучше, макрос вроде

#define ARRSIZE(arr)    (sizeof(arr)/sizeof(*(arr)))
/* ... */
buffer[ARRSIZE(buffer)-1]='\0';

Ответ 9

Итак, у нас есть это:

std::string sz = "Hello, world!"
char ch[5];

Теперь просто сделайте простой:

ch = sz.substr(0, 5-1).c_str();

И теперь:

// ch = "Hell";

:)

Ответ 10

char mystring[101]; // a 100 character string plus terminator
char *any_input;
any_input = "Example";
iterate = 0;
while ( any_input[iterate] != '\0' && iterate < 100) {
    mystring[iterate] = any_input[iterate];
    iterate++;
}
mystring[iterate] = '\0';

Это базовый эффективный дизайн.

Ответ 11

Я думаю, snprintf() очень безопасен и прост.

snprintf ( buffer, 100, "The half of %d is %d", 60, 60/2 );

нулевой символ добавляет его автоматически:)

Ответ 12

Если у вас всегда есть буфер размером 5, вы можете сделать:

std::string s = "Your string";
char buffer[5]={s[0],s[1],s[2],s[3],'\0'};

Изменить: Конечно, если предположить, что ваш std::string достаточно большой.