Я хочу скопировать строку в массив char и не перегружать буфер.
Итак, если у меня есть массив char размером 5, тогда я хочу скопировать максимум 5 байтов из строки в него.
какой код для этого?
Я хочу скопировать строку в массив char и не перегружать буфер.
Итак, если у меня есть массив char размером 5, тогда я хочу скопировать максимум 5 байтов из строки в него.
какой код для этого?
Прежде всего, strncpy
почти наверняка не то, что вы хотите. strncpy
был разработан для определенной цели. Он в стандартной библиотеке почти исключительно потому, что он уже существует, а не потому, что он вообще полезен.
Вероятно, самый простой способ сделать то, что вам нужно, - это что-то вроде:
sprintf(buffer, "%.4s", your_string.c_str());
В отличие от strncpy
, это гарантирует, что результат будет завершен NUL, но не будет заполнять дополнительные данные в целевом объекте, если источник короче указанного (хотя последний не является серьезной проблемой, когда конечная длина равна 5).
Это именно то, что делает функция копирования 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';
Используйте функцию неработающая ссылка, а материал не найден на целевом сайте если ваша реализация обеспечивает один (функция не входит в стандартную библиотеку C), но она довольно широко признана в качестве де-факто стандартного имени для "безопасной" функции копирования с ограниченной длиной для строк с нулевым завершением.strlcpy
Если ваша реализация не предоставляет функцию 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
"работать" для этой цели, он по-прежнему сродни приводу деревянных винтов молотком.
Некоторые интересные версии libc предоставляют нестандартную, но большую замену для strcpy(3)
/strncpy(3)
- strlcpy(3)
.
Если ваш нет, исходный код свободно доступен здесь из OpenBSD.
Обновление: Мысль, что я попытаюсь связать некоторые ответы, ответы, которые убедили меня, что мой собственный первоначальный ответ на вызов коленного сустава был плохим.
Во-первых, как отметил 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';
void stringChange(string var){
char strArray[100];
strcpy(strArray, var.c_str());
}
Я думаю, это должно сработать. он скопирует строку формы в массив char.
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.
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';
Итак, у нас есть это:
std::string sz = "Hello, world!"
char ch[5];
Теперь просто сделайте простой:
ch = sz.substr(0, 5-1).c_str();
И теперь:
// ch = "Hell";
:)
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';
Это базовый эффективный дизайн.
Я думаю, snprintf() очень безопасен и прост.
snprintf ( buffer, 100, "The half of %d is %d", 60, 60/2 );
нулевой символ добавляет его автоматически:)
Если у вас всегда есть буфер размером 5, вы можете сделать:
std::string s = "Your string";
char buffer[5]={s[0],s[1],s[2],s[3],'\0'};
Изменить: Конечно, если предположить, что ваш std::string достаточно большой.