strncpy equivalent for std::string?
C ++标准库中是否有与strncpy完全相同的东西?我的意思是一个函数,它将一个缓冲区中的字符串复制到另一个缓冲区中,直到命中终止0为止?例如,当我不得不从不安全的来源(例如TCP数据包)中解析字符串时,我可以在处理数据的同时进行长度检查。
我已经搜索了很多有关该主题的内容,还找到了一些有趣的主题,但是所有这些人都对std :: string :: assign感到满意,该函数还可以将字符大小复制为参数。我对该函数的问题是,它不执行任何检查是否已命中了终止null-它会认真对待给定的大小并像memcpy一样将数据复制到字符串缓冲区中。如果应对时进行了这种检查,则这种方式分配和复制的内存比必须完成的要多得多。
这就是我目前正在解决此问题的方式,但是我希望避免一些开销:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Get RVA of export name const ExportDirectory_t *pED = (const ExportDirectory_t*)rva2ptr(exportRVA); sSRA nameSra = rva2sra(pED->Name); // Copy it into my buffer char *szExportName = new char[nameSra.numBytesToSectionsEnd]; strncpy(szExportName, nameSra.pSection->pRawData->constPtr<char>(nameSra.offset), nameSra.numBytesToSectionsEnd); szExportName[nameSra.numBytesToSectionsEnd - 1] = 0; m_exportName = szExportName; delete [] szExportName; |
这段代码是我的PE-binaries解析器的一部分(准确地说,是解析出口表的例程)。 rva2sra将相对虚拟地址转换为PE部分相对地址。 ExportDirectory_t结构包含RVA到二进制文件的导出名称,该名称应为零终止的字符串。但这并非总是如此-如果有人愿意,它将能够省略终止零,这将使我的程序运行到不属于该部分的内存中,从而最终导致崩溃(最好的情况下...)。
我自己实现这样的功能不是什么大问题,但是如果在C ++标准库中实现了该功能的解决方案,我更喜欢它。
如果知道要创建
1 2 3 4 5 | const char[] buffer ="hello\\0there"; std::string s(buffer); // s contains"hello" |
如果不确定,则只需在字符串中搜索第一个空值,然后告诉
1 2 3 4 5 6 7 8 9 | int len_of_buffer = something; const char* buffer = somethingelse; const char* copyupto = std::find(buffer, buffer + len_of_buffer, 0); // find the first NUL std::string s(buffer, copyupto); // s now contains all the characters up to the first NUL from buffer, or if there // was no NUL, it contains the entire contents of buffer |
您可以将第二个版本(即使缓冲区中没有NUL,也总是可以运行)包装成一个简洁的小函数:
1 2 3 4 5 | std::string string_ncopy(const char* buffer, std::size_t buffer_size) { const char* copyupto = std::find(buffer, buffer + buffer_size, 0); return std::string(buffer, copyupto); } |
但需要注意的一件事是:如果您将单参数构造函数本身交给
不幸的是(或者幸运的是)对于
Is there an exact equivalent to strncpy in the C++ Standard Library?
我当然希望不会!
I mean a function, that copies a string from one buffer to another until it hits the terminating 0?
嗯,但这不是
您可以使用
1 2 3 | char dest[SOME_SIZE]; dest[0] = '\\0'; strncat(dest, source_string, SOME_SIZE); |
这将始终
您是否真的在寻找与之等效的
编辑:写完以上内容之后,我在博客上发布了这句话。
STL中的
有几种方法可以用较短的代码来实现您的目标:
1 2 | const char *ptr = nameSra.pSection->pRawData->constPtr<char>(nameSra.offset); m_exportName.assign(ptr, strnlen(ptr, nameSra.numBytesToSectionsEnd)); |
要么
1 2 3 4 | const char *ptr = nameSra.pSection->pRawData->constPtr<char>(nameSra.offset); m_exportName.reserve(nameSra.numBytesToSectionsEnd); for (int i = 0; i < nameSra.numBytesToSectionsEnd && ptr[i]; i++) m_exportName += ptr[i]; |
字符串的子字符串构造函数可以执行您想要的操作,尽管它与strncpy并不完全等效(请参阅最后的说明):
1 2 3 4 | std::string( const std::string& other, size_type pos, size_type count = std::string::npos, const Allocator& alloc = Allocator() ); |
Constructs the string with a substring [pos, pos+count) of other. If count == npos or if the requested substring lasts past the end of the string, the resulting substring is [pos, size()).
来源:http://www.cplusplus.com/reference/string/string/string/
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <iostream> #include <string> #include <cstring> int main () { std::string s0 ("Initial string"); std::string s1 (s0, 0, 40); // count is bigger than s0's length std::string s2 (40, 'a'); // the 'a' characters will be overwritten strncpy(&s2[0], s0.c_str(), s2.size()); std::cout <<"s1: '" << s1 <<"' (size=" << s1.size() <<")" << std::endl; std::cout <<"s2: '" << s2 <<"' (size=" << s2.size() <<")" << std::endl; return 0; } |
输出:
1 2 | s1: 'Initial string' (size=14) s2: 'Initial string' (size=40) |
与strncpy的区别:
- 字符串构造函数总是在结果后附加一个以零结尾的字符,而strncpy则不会。
- 如果在请求的计数之前到达了以空终止的字符,则字符串构造函数不会将结果填充为0,strncpy会这样做。
没有内置的等效项。您必须滚动自己的
1 2 3 4 5 6 7 8 9 10 11 12 | #include <cstring> #include <string> std::string strncpy(const char* str, const size_t n) { if (str == NULL || n == 0) { return std::string(); } return std::string(str, std::min(std::strlen(str), n)); } |
std :: string具有可以使用的下一个签名的构造函数:
1 | string ( const char * s, size_t n ); |
下一个说明:
Content is initialized to a copy of the string formed by the first n characters in the array of characters pointed by s.
使用类的构造函数:
1 2 | string::string str1("Hello world!"); string::string str2(str1); |
根据此文档,这将产生准确的副本:http://www.cplusplus.com/reference/string/string/string/