c++ - 如何在不遍历缓冲区的情况下将字符串复制到 C++ 中的字符数组中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2889421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to copy a string into a char array in C++ without going over the buffer
提问by neuromancer
I want to copy a string into a char array, and not overrun the buffer.
我想将一个字符串复制到一个字符数组中,而不是溢出缓冲区。
So if I have a char array of size 5, then I want to copy a maximum of 5 bytes from a string into it.
因此,如果我有一个大小为 5 的字符数组,那么我想将最多 5 个字节从字符串复制到其中。
what's the code to do that?
这样做的代码是什么?
回答by CB Bailey
This is exactly what std::string
's copy function does.
这正是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;
}
If you need null termination you should do something like this:
如果您需要空终止,您应该执行以下操作:
str.copy(test, 4);
test[4] = 'sprintf(buffer, "%.4s", your_string.c_str());
';
回答by Jerry Coffin
First of all, strncpy
is almost certainly notwhat you want. strncpy
was designed for a fairly specific purpose. It's in the standard library almost exclusively because it already exists, not because it's generally useful.
首先,strncpy
几乎肯定不是你想要的。strncpy
是为相当特定的目的而设计的。它在标准库中几乎完全是因为它已经存在,而不是因为它通常很有用。
Probably the simplest way to do what you want is with something like:
做你想做的事情最简单的方法可能是:
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 != 'void stringChange(string var){
char strArray[100];
strcpy(strArray, var.c_str());
}
'; --n, ++pd, ++ps)
*pd = *ps;
*pd = 'snprintf ( buffer, 100, "The half of %d is %d", 60, 60/2 );
';
}
return dst;
}
Unlike strncpy
, this guarantees that the result will be NUL terminated, but does not fill in extra data in the target if the source is shorter than specified (though the latter isn't a major issue when the target length is 5).
与 不同strncpy
,这保证结果将以 NUL 终止,但如果源比指定的短,则不会在目标中填充额外的数据(尽管当目标长度为 5 时,后者不是主要问题)。
回答by AnT
Use function broken link, and material not found on destination siteif your implementation provides one (the function is not in the standard C library), yet it is rather widely accepted as a de-facto standard name for a "safe" limited-length copying function for zero-terminated strings.strlcpy
使用功能 如果您的实现提供了一个断开的链接,并且在目标站点上找不到材料(该函数不在标准 C 库中),但它被广泛接受为“安全”有限长度复制函数的事实上的标准名称对于以零结尾的字符串。strlcpy
If your implementation does not provide strlcpy
function, implement one yourself. For example, something like this might work for you
如果您的实现不提供strlcpy
功能,请自己实现一个。例如,这样的事情可能对你有用
std::string str = "Your string";
char buffer[5];
strncpy(buffer, str.c_str(), sizeof(buffer));
buffer[sizeof(buffer)-1] = '#define ARRSIZE(arr) (sizeof(arr)/sizeof(*(arr)))
/* ... */
buffer[ARRSIZE(buffer)-1]='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] = 'char mystring[101]; // a 100 character string plus terminator
char *any_input;
any_input = "Example";
iterate = 0;
while ( any_input[iterate] != '##代码##' && iterate < 100) {
mystring[iterate] = any_input[iterate];
iterate++;
}
mystring[iterate] = '##代码##';
'; // my_char_array contains "some"
';
';
(Actually, the de-facto accepted strlcpy
returns size_t
, so you might prefer to implement the accepted specification instead of what I did above).
(实际上,事实上接受的strlcpy
返回size_t
,所以你可能更喜欢实现接受的规范而不是我上面所做的)。
Beware of the answers that recommend using strncpy
for that purpose. strncpy
is not a safe limited-length string copying function and is not supposed to be used for that purpose. While you can force strncpy
to "work" for that purpose, it is still akin to driving woodscrews with a hammer.
当心推荐strncpy
用于该目的的答案。strncpy
不是安全的有限长度字符串复制函数,不应用于该目的。虽然您可以strncpy
为此目的强制“工作”,但它仍然类似于用锤子驱动木螺钉。
回答by academicRobot
Update:Thought I would try to tie together some of the answers, answers which have convinced me that my own original knee-jerk strncpy response was poor.
更新:我想我会尝试将一些答案联系在一起,这些答案让我相信我自己最初的下意识反应很差。
First, as AndreyT noted in the comments to this question, truncation methods (snprintf, strlcpy, and strncpy) are often not a good solution. Its often better to check the size of the string string.size()
against the buffer length and return/throw an error or resize the buffer.
首先,正如 AndreyT 在对这个问题的评论中所指出的,截断方法(snprintf、strlcpy 和 strncpy)通常不是一个好的解决方案。通常最好string.size()
根据缓冲区长度检查字符串的大小并返回/抛出错误或调整缓冲区大小。
If truncation is OK in your situation, IMHO, strlcpyis the best solution, being the fastest/least overhead method that ensures null termination. Unfortunately, its not in many/all standard distributions and so is not portable. If you are doing a lot of these, it maybe worth providing your own implementation, AndreyT gave an example. It runs in O(result length). Also the reference specification returns the number of bytes copied, which can assist in detecting if the source was truncated.
如果在您的情况下截断没问题,恕我直言,strlcpy是最佳解决方案,它是确保空终止的最快/最少开销方法。不幸的是,它不在许多/所有标准发行版中,因此不可移植。如果你做了很多这样的事情,也许值得提供你自己的实现,AndreyT 举了一个例子。它以 O(结果长度) 运行。此外,参考规范返回复制的字节数,这有助于检测源是否被截断。
Other good solutions are sprintfand snprintf. They are standard, and so are portable and provide a safe null terminated result. They have more overhead than strlcpy (parsing the format string specifier and variable argument list), but unless you are doing a lot of these you probably won't notice the difference. It also runs in O(result length). snprintf is always safe and that sprintf may overflow if you get the format specifier wrong (as other have noted, format string should be "%.<N>s"
not "%<N>s"
). These methods also return the number of bytes copied.
其他好的解决方案是sprintf和snprintf。它们是标准的,因此是可移植的,并提供安全的空终止结果。它们比 strlcpy (解析格式字符串说明符和变量参数列表)有更多的开销,但除非你做了很多这些,否则你可能不会注意到差异。它还以 O(结果长度) 运行。snprintf的始终是安全的,如果你得到的格式说明不对的sprintf的可能溢出(其它所指出的,格式字符串应该是"%.<N>s"
没有"%<N>s"
)。这些方法还返回复制的字节数。
A special case solution is strncpy. It runs in O(buffer length), because if it reaches the end of the src it zeros out the remainder of the buffer. Only useful if you need to zero the tail of the buffer or are confident that destination and source string lengths are the same. Also note that it is not safe in that it doesn't necessarily null terminate the string. If the source is truncated, then null will not be appended, so call in sequence with a null assignment to ensure null termination: strncpy(buffer, str.c_str(), BUFFER_LAST); buffer[BUFFER_LAST] = '\0';
一个特例解决方案是strncpy。它在 O( buffer length) 中运行,因为如果它到达 src 的末尾,它会将缓冲区的其余部分归零。仅当您需要将缓冲区的尾部归零或确信目标和源字符串长度相同时才有用。另请注意,它并不安全,因为它不一定以 null 终止字符串。如果源被截断,则不会附加空值,因此使用空值分配顺序调用以确保空值终止:strncpy(buffer, str.c_str(), BUFFER_LAST); buffer[BUFFER_LAST] = '\0';
回答by Nikolai Fetissov
Some nice libc versions provide non-standard but great replacement for strcpy(3)
/strncpy(3)
- strlcpy(3)
.
一些不错的 libc 版本为strcpy(3)
/ strncpy(3)
-提供了非标准但很好的替代品strlcpy(3)
。
If yours doesn't, the source code is freely available herefrom the OpenBSDrepository.
回答by Sunil
I guess this should work. it'll copy form string to an char array.
我想这应该有效。它会将表单字符串复制到一个字符数组。
回答by Dark Corp
i think snprintf() is much safe and simlest
我认为 snprintf() 非常安全和简单
##代码##null character is append it end automatically :)
空字符是附加它自动结束:)
回答by Matteo Italia
The last line is required because strncpy isn't guaranteed to NUL terminate the string (there has been a discussion about the motivation yesterday).
最后一行是必需的,因为 strncpy 不能保证 NUL 终止字符串(昨天已经讨论了动机)。
If you used wide strings, instead of sizeof(buffer)
you'd use sizeof(buffer)/sizeof(*buffer)
, or, even better, a macro like
如果你使用宽字符串,而不是sizeof(buffer)
使用sizeof(buffer)/sizeof(*buffer)
,或者更好的是,像这样的宏
回答by Péter T?r?k
With strncpy
, you can copy at most ncharacters from the source to the destination. However, note that if the source string is at most nchars long, the destination will not be null terminated; you must put the terminating null character into it yourself.
使用strncpy
,您最多可以将n 个字符从源复制到目标。但是,请注意,如果源字符串的长度最多为n 个字符,则目标字符串不会以空字符结尾;您必须自己将终止空字符放入其中。
A char array with a length of 5 can contain at most a string of 4 characters, since the 5th must be the terminating null character. Hence in the above code, n= 4.
长度为 5 的 char 数组最多可以包含 4 个字符的字符串,因为第 5 个必须是终止空字符。因此在上面的代码中,n= 4。
回答by Péter T?r?k
This is the basic efficient design.
这是基本的高效设计。