C++ copy std::string to char array with no null termination
Asked Answered
W

4

8

I am writing to a binary file using a struct that just contains a char[32]. I basically need to format each block of data by performing various calculations on string arrays and concatenating the results. I am attempting to copy an std::string to a char array with no null termination. The more I read into this, the more confused I get. If I do:

struct block{
    char data[32];
};
block blocks[2048];
std::string buffer;

buffer = "12345678123456781234567812345678";
strcpy(blocks[0].data, buffer.c_str());

I get an error, because adding the null terminator with c_str() makes the string length 33. If I subtract one char from the string, it works, but then I have the null terminator, which I don't want. I can successfully do the following:

strcpy(blocks[0].data, "12345678123456781234567812345678");

but I want to construct the string first, since it often involves concatenating different strings from various arrays. For instance, I can do this with std::string:

std::string buffer = stringArray1[0] + stringArray2[0];
strcpy(blocks[0].data, buffer.c_str());

but then I have the null terminator again. I'd just like to copy exactly the chars in the std::string with no null terminator.

I am using VC++ 6.0.

Waldack answered 1/12, 2011 at 17:28 Comment(2)
You do know that VC++ 6.0 is just like IE 6. Hidious. If you are in a position to switch a compiler do so and fast.Tyche
Thank you all for you responses. I ended up using memcpy; I had tried that before, mistakenly using std::string.c_str instead of std::string.data. Also, we typically use VS2010, but this is a legacy product that requires some old libraries that haven't been updated to support anything past VS6.0.Waldack
B
12

Use memcpy instead of strcpy, that's what it's there for:

memcpy(blocks[0].data, buffer.data(), sizeof(blocks[0].data)); 
Bedad answered 1/12, 2011 at 17:31 Comment(2)
@AlfP.Steinbach: Of course. I picked memcpy because it is closest to what the OP already has, and they will be comfortable using it. I imagine the same cannot be said for the std::copy version if it's the first time you come upon it.Bedad
Exactly what I needed. Thanks! I am going to get familiar with std::copy as well, but you're right: I slammed memcpy right in and it worked.Waldack
C
17

You can't use strcpy because that looks for the NULL terminator to identify the end of the string, and copies the NULL to the output string.

Since you're going from a string to a char buffer, the simplest thing would be to use std::copy:

#include <algorithm>

static const size_t data_size = 32;
struct block{
    char data[data_size];
};

/* ... */

std::string buffer = stringArray1[0] + stringArray2[0];
std::copy( buffer.begin(), buffer.end(), blocks[0].data );

And, by the way, you might be able to use a vector<char>, rather than a char data[32]

EDIT:

An aside: VC6 is an ancient compiler which was bad when it came out, terrible when the C++ Standard was ratified, and is completely unsupported by Microsoft. If something were to go wrong with it, they won't even talk to you. You should get off VC6 as soon as possible.

Cranston answered 1/12, 2011 at 17:32 Comment(1)
Thank you for the answers and the suggestions. I ended up using memcpy for simplicity's sake but I am going to get familiar with these methods going forward.Waldack
B
12

Use memcpy instead of strcpy, that's what it's there for:

memcpy(blocks[0].data, buffer.data(), sizeof(blocks[0].data)); 
Bedad answered 1/12, 2011 at 17:31 Comment(2)
@AlfP.Steinbach: Of course. I picked memcpy because it is closest to what the OP already has, and they will be comfortable using it. I imagine the same cannot be said for the std::copy version if it's the first time you come upon it.Bedad
Exactly what I needed. Thanks! I am going to get familiar with std::copy as well, but you're right: I slammed memcpy right in and it worked.Waldack
C
1

Use strncpy() instead of strcpy():

strncpy(blocks[0].data, buffer.c_str(), 32); 
Cosh answered 1/12, 2011 at 18:43 Comment(0)
A
-1

Use one of the lines below

memcpy(blocks[0].data, buffer.c_str(), buffer.size());
memcpy(blocks[0].data, buffer.c_str(), 32);
memcpy(blocks[0].data, buffer.c_str(), buffer.size() > 32 ? 32 : buffer.size());
std::copy(buffer.begin(), buffer.end(), blocks[0].data).

BTW, do you handle the case when the string is shorter than 32 characters? Do you want to append a null byte then?

Armitage answered 1/12, 2011 at 17:38 Comment(3)
no, memcpy accepts destination as first parameter - passing it c_str() of a string is useless...Afferent
Minor nitpick: buffer.data() would be more appropriate here than buffer.c_str() (even though it would not make a difference).Bedad
signature of memcpy is void * memcpy ( void * destination, const void * source, size_t num ) so your example is copying the wrong way.Rabbit

© 2022 - 2024 — McMap. All rights reserved.