Foreword
In the actual project development, string copy is a very common usage. There are many ways, we use, any problems generally do not occur, or is generally the compiler does not compile error, or even run error. However, some potential pitfalls are often present, such as when using VS 2017 development, you will find a lot of grammar compiler detected will be more rigorous, previously not being given such vs2010, vs2017 will not compile, or compile successful, run error.
Nonsense: just in time to work, I feel as long as the function can be achieved, is to complete the task. With experience, a lot of things you like to go to get to the bottom, to think, why so used, so with what benefits, efficiency will not be higher, the performance will not be better.
Well, nonsense is more than just words, following the official opening of today's discussion topic.
Copy format
There are many string copy the way, here I mainly talk about memcpy, strcpy, string :: copy of these three.
Memory copy memcpy
Function prototype
void* __cdecl memcpy(
_Out_writes_bytes_all_(_Size) void* _Dst,
_In_reads_bytes_(_Size) void const* _Src,
_In_ size_t _Size
);
Simpler:
void *memcpy(void *dest, const void *src, size_t count);
Parameters not elaborate here.
example:
std::string CopyString(const std::string &strBody)
{
int nLen = strBody.length();
char *cBody = new char(nLen);
memcpy(cBody, strBody.c_str(), nLen);
std::cout << "FONCTION:" << cBody << std::endl;
return cBody;
}
int main()
{
std::string strBody = "This is a Test!";
std::string strReturn = CopyString(strBody);
std::cout << "MAIN:" << strReturn.c_str() << std::endl;
system("pause");
return 0;
}
The above function, an error will not occur in most cases, but there is a potential trap.
trap
Memory copy of the end of the string will not '\0'
be checked
result
After the copy, garbled at the end of the string.
solution
When applying a multi-bytes of memory for memory, in order to ensure that the end of string copied into.
std::string CopyString(const std::string &strBody)
{
int nLen = strBody.length();
char *cBody = new char(nLen + 1);
memcpy(cBody, strBody.c_str(), nLen + 1);
std::cout << "FONCTION:" << cBody << std::endl;
return cBody;
}
int main()
{
std::string strBody = "This is a Test!";
std::string strReturn = CopyString(strBody);
std::cout << "MAIN:" << strReturn.c_str() << std::endl;
delete strReturn.c_str();
system("pause");
return 0;
}
Copy String strcpy
Function prototype
char* __cdecl strcpy(
_Out_writes_z_(_String_length_(_Source) + 1) char* _Dest,
_In_z_ char const* _Source
);
Simpler:
char *strcpy(char *dst, const char *src);
example
std::string CopyString(const std::string &strBody)
{
int nLen = strBody.length();
char *cBody = new char(nLen);
strcpy(cBody, strBody.c_str());
std::cout << "FONCTION:" << cBody << std::endl;
return cBody;
}
int main()
{
std::string strBody = "This is a Test!";
std::string strReturn = CopyString(strBody);
std::cout << "MAIN:" << strReturn.c_str() << std::endl;
delete strReturn.c_str();
system("pause");
return 0;
}
Explanation
strcpy
Dedicated to the string copy function, and the memcpy
difference is that it will detect the end of the character '\0'
, so that the memory in the application do not apply excess.
The method of copy string string :: copy
prototype
size_type copy(_Out_writes_(_Count) _Elem * const _Ptr,
size_type _Count, const size_type _Off = 0) const
{ // copy [_Off, _Off + _Count) to [_Ptr, _Ptr + _Count)
auto& _My_data = this->_Get_data();
_My_data._Check_offset(_Off);
_Count = _My_data._Clamp_suffix_size(_Off, _Count);
_Traits::copy(_Ptr, _My_data._Myptr() + _Off, _Count);
return (_Count);
}
Or a simple point:
size_t copy (char* s, size_t len, size_t pos = 0) const;
Here to explain these parameters:
S
pointer to a set of characters.
This array should contain sufficient storage space for the characters to copy.
len
number of characters to be copied (if the string is shorter, as many characters are copied).
pos
the position of the first character to copy.
If this is greater than the length of the string, it throws out_of_range.
Note: The first character string is represented by a value of 0 (not 1).
example
// string::copy
#include <iostream>
#include <string>
int main ()
{
char buffer[20];
std::string str ("This is a Test");
std::size_t length = str.copy(buffer,6,5);
std::cout << "buffer contains: " << buffer << '\n';
return 0;
}
Trap & results
Because this copy
function is still the final call memcopy
, so the same trap, after the copy is complete, it will bring back a bunch of gibberish string
solution
At the end of copying, plus terminator '\0'
.
// string::copy
#include <iostream>
#include <string>
int main ()
{
char buffer[20];
std::string str ("This is a Test");
std::size_t length = str.copy(buffer,6,5);
buffer[length]='\0';
std::cout << "buffer contains: " << buffer << '\n';
return 0;
}
Here there is a way, but this approach to be discussed, because my current results are correct. That is in the memory after the application, the first time to initialize, so it will not appear garbled copy.
E.g:
std::string CopyString(const std::string &strBody)
{
char *cBody = NULL;
int nLen = strBody.size();
cBody = (char *)malloc(nLen);
memset(cBody, 0, nLen);
strBody.copy(cBody, nLen, 0);
std::cout << "FONCTION:" << cBody << std::endl;
return cBody;
}
int main()
{
std::string strBody = "This is a Test!";
std::string strReturn = CopyString(strBody);
std::cout << "MAIN:" << strReturn.c_str() << std::endl;
system("pause");
return 0;
}
Afterword
In our development process, a lot of details we need to scrutiny, attention to detail, not to touch the issue, a problem, even problems are easy to find, especially in large projects.