How could I copy data that contain '\0' character

烂漫一生 提交于 2019-12-24 17:31:23

问题


I'm trying to copy data that conatin '\0'. I'm using C++ . When the result of the research was negative, I decide to write my own fonction to copy data from one char* to another char*. But it doesn't return the wanted result ! My attempt is the following :

#include <iostream>


char* my_strcpy( char* arr_out,  char* arr_in, int bloc )
{
 char* pc= arr_out;

 for(size_t i=0;i<bloc;++i)     
 {

        *arr_out++ = *arr_in++ ;
 }

 *arr_out = '\0';
 return pc;
}

int main()
{
    char * out= new char[20];
    my_strcpy(out,"12345aa\0aaaaa  AA",20);
    std::cout<<"output data: "<< out << std::endl;
    std::cout<< "the length of my output data: " << strlen(out)<<std::endl;
    system("pause");
    return 0;
}

the result is here:

I don't understand what is wrong with my code.

Thank you for help in advance.


回答1:


Your my_strcpy is working fine, when you write a char* to cout or calc it's length with strlen they stop at \0 as per C string behaviour. By the way, you can use memcpy to copy a block of char regardless of \0.




回答2:


If you know the length of the 'string' then use memcpy. Strcpy will halt its copy when it meets a string terminator, the \0. Memcpy will not, it will copy the \0 and anything that follows.




回答3:


(Note: For any readers who are unaware that \0 is a single-character byte with value zero in string literals in C and C++, not to be confused with the \\0 expression that results in a two-byte sequence of an actual backslash followed by an actual zero in the string... I will direct you to Dr. Rebmu's explanation of how to split a string in C for further misinformation.)


C++ strings can maintain their length independent of any embedded \0. They copy their contents based on this length. The only thing is that the default constructor, when initialized with a C-string and no length, will be guided by the null terminator as to what you wanted the length to be.

To override this, you can pass in a length explicitly. Make sure the length is accurate, though. You have 17 bytes of data, and 18 if you want the null terminator in the string literal to make it into your string as part of the data.

#include <iostream>
using namespace std;

int main() {
    string str ("12345aa\0aaaaa  AA", 18);
    string str2 = str;
    cout << str;
    cout << str2;
    return 0;
}

(Try not to hardcode such lengths if you can avoid it. Note that you didn't count it right, and when I corrected another answer here they got it wrong as well. It's error prone.)

On my terminal that outputs:

12345aaaaaaa  AA
12345aaaaaaa  AA

But note that what you're doing here is actually streaming a 0 byte to the stdout. I'm not sure how formalized the behavior of different terminal standards are for dealing with that. Things outside of the printable range can be used for all kinds of purposes depending on the kind of terminal you're running... positioning the cursor on the screen, changing the color, etc. I wouldn't write out strings with embedded zeros like that unless I knew what the semantics were going to be on the stream receiving them.

Consider that if what you're dealing with are bytes, not to confuse the issue and to use a std::vector<char> instead. Many libraries offer alternatives, such as Qt's QByteArray




回答4:


Your function is fine (except that you should pass to it 17 instead of 20). If you need to output null characters, one way is to convert the data to std::string:

std::string outStr(out, out + 17);
std::cout<< "output data: "<< outStr << std::endl;
std::cout<< "the length of my output data: " << outStr.length() <<std::endl;



回答5:


  • I don't understand what is wrong with my code.

    my_strcpy(out,"12345aa\0aaaaa AA",20);

Your string contains character '\' which is interpreted as escape sequence. To prevent this you have to duplicate backslash:

my_strcpy(out,"12345aa\\0aaaaa  AA",20);

Test

output data: 12345aa\0aaaaa  AA
the length of my output data: 18



回答6:


Your string is already terminated midway.

my_strcpy(out,"12345aa\0aaaaa  AA",20);

Why do you intend to have \0 in between like that? Have some other delimiter if yo so desire Otherwise, since std::cout and strlen interpret a \0 as a string terminator, you get surprises. What I mean is that follow the convention i.e. '\0' as string terminator



来源:https://stackoverflow.com/questions/26118818/how-could-i-copy-data-that-contain-0-character

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!