C++ - Convert array of floats to std::string - c++

I have an array of floats with a fixed length. Now I want to convert that array to a binary string.
I cannot use const char * because my string will contain null-bytes. How would I use memcpy in that case? I have already tried a reinterpret_cast<string *>, but that won't work because the string is also/only storing pointers to the begin and end of the data (correct me if I am wrong).
I'm already constructing an empty string:
string s;
s.resize(arr_size);
But how would I copy an array of floats to that string?
Basically, I want to dump the memory region of a fixed float array to a string.
Don't be to hard with me, I'm still learning c++

Like this:
#include <algorithm>
#include <string>
float data[10]; // populate
std::string s(sizeof data);
char const * p = reinterpret_cast<char const *>(data);
std::copy(p, p + sizeof data, &s[0]);
Note that sizeof data is the same as 10 * sizeof(float), i.e. the number of bytes in the array.
Update: As suggested by James, you can do even better and write it all in one go:
char const * p = reinterpret_cast<char const *>(data);
std::string s(p, p + sizeof data); // beginning + length constructor
Or even:
#include <iterator>
std::string s(reinterpret_cast<char const *>(std::begin(data)), // begin + end
reinterpret_cast<char const *>(std::end(data))); // constructor

Getting all of the bytes of the array into a string is easy:
std::string
bitwiseDump( float const* begin, float const* end )
{
return std::string( reinterpret_cast<char const*>( begin ),
reinterpret_cast<char const*>( end ) );
}
But why? There's nothing you can do with the string except copy
it back into an array of the same type. (And even for that use,
std::vector<char> or std::vector<unsigned char> would be
more natural. And less obfuscating.)

Take a look at this...
#include <iostream>
#include <array>
#include <string>
int main()
{
std::string floatString;
std::array<float, 5> data = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f};
for (auto& element : data)
floatString.append(std::to_string(element));
std::cout << floatString;
std::cin.get();
}

Related

How to read uint8_t data that was converted from vector of string?

I need to use a function func(uint8_t* buffer, uint size); supposing I can't change its parameters, I want to pass it a string.
I have a vector<string> that I must convert to uint8_t* and then read it and convert it back to vector<string>.
I tried this code for reading (printing) the vector.data() output but it prints garbage:
#include <cstdint>
#include <string>
#include <vector>
#include <iostream>
int main() {
std::string a1 = {"ath"};
std::cout <<"1: "<< a1<<" end\n";
std::vector<std::string> vec;
vec.push_back(a1);
uint8_t *ptr = reinterpret_cast<uint8_t*>(vec.data());
std::cout <<"2: "<< ptr[0]<<" end\n";
}
output:
1: ath end
2: � end
questions:
why this doesn't work?
I saw in some links that they init a std::string with char* array like this:
char *ptr={'a'};
std::string myStr(ptr);
I suppose this works because of added '\0', is this related to my problem?
why this doesn't work?
This can't work, because a std::string is not just a contiguous piece of memory containing nothing but the characters in the string. You're simply mistaken about what std::string is!
Using a vector here is plain not the right approach. A vector does not contain your string's contents. Just the std::string objects themselves, which are not the string data.
Instead, you want to make one long std::string:
std::string foo {"foo"};
std::string bar {"bar "};
std::string baz {"bazaz"};
std::string complete = foo + bar + baz;
auto* whole_cstring = reinterpret_cast<uint8_t*>(complete.c_str());
// call your C-string-accepting function
func(whole_cstring, complete.length());
If you actually do have a std::vector of std::strings to begin with, the concatenation can be done in a simple loop:
std::vector<std::string> my_vector_of_strings;
// insert strings into the vector
/// … ///
std::string complete;
for(const auto& individual_string : my_vector_of_strings) {
complete += individual_string;
}
auto* whole_cstring = reinterpret_cast<uint8_t*>(complete.c_str());
// call your C-string-accepting function
func(whole_cstring, complete.length());
… missing \0 … I suppose this works because of added '\0', is this related to my problem?
No, that's completely unrelated.
I have a vector that I must convert to uint8_t*
std::vector<std::string> vec;
"Converting" has a relatively strong definition in the C++ (and other languages) world. If I understand what you mean, I'd suggest the following:
#include <string>
#include <vector>
#include <algorithm>
int main(){
std::vector<std::string> vec;
// populate
std::vector<uint8_t*> vec2(vec.size());
std::transform(begin(vec), end(vec), begin(vec2), [](auto& s){ return reinterpret_cast<unsigned char*>(s.data()); });
}
Alternatively, if possible, you can use a std::basic_string<uint8_t> instead of std::string (a/k/a std::basic_string<char>) to avoid reinterpreting its content.

Filling char pointer correctly

I have a char pointer:
char* s = new char[150];
Now how do i fill it? This:
s="abcdef";
Gives warning about deprecation of conversion between string literal and char*, but generally works.
This:
char* s = new[150]("abcdef");
Does not work, gives an error.
How to do this properly? Note that I want the memory allocation to have 150*sizeof(char) bytes and contain "abcdef". I know about malloc, but is it possible to do with new?
Its for an assignment where i cant use the standard library.
This sequence of statements
char* s = new char[150];
s="abcdef";
results in a memory leak because at first a memory was allocated and its address was assigned to the pointer s and then the pointer was reassigned with the address of the string literal "abcdef". And moreover string literals in C++ (opposite to C) have types of constant character arrays.
If you allocated a memory for a string then you should copy a string in the memory either by using the C standard function strcpy or C standard function strncpy.
For example
char* s = new char[150];
std::strcpy( s, "abcdef" );
Or
const size_t N = 150;
char* s = new char[N];
std::strncpy( s, "abcdef", N );
s[N-1] = '\0';
Or even the following way
#include <iostream>
#include <cstring>
int main()
{
const size_t N = 150;
char *s = new char[N]{ '\0' };
std::strncpy( s, "abcdef", N - 1 );
std::cout << s << '\n';
delete []s;
}
In any case it is better just to use the standard class std::string.
std::string s( "abcdef" );
or for example
std::string s;
s.assign( "abcdef" );
The basic procedure for creating a memory area for a string and then filling it without using the Standard Library in C++ is as follows:
create the appropriate sized memory area with new
use a loop to copy characters from a string into the new area
So the source code would look like:
// function to copy a zero terminated char string to a new char string.
// loop requires a zero terminated char string as the source.
char *strcpyX (char *dest, const char *source)
{
char *destSave = dest; // save copy of the destination address to return
while (*dest++ = *source++); // copy characters up to and including zero terminator.
return destSave; // return destination pointer per standard library strcpy()
}
// somewhere in your code
char *s1 = new char [150];
strcpyX (s1, "abcdef");
Given a character array:
char * s = new char [256];
Here's how to fill the pointer:
std::fill(&s, &s + sizeof(s), 0);
Here's how to fill the array:
std::fill(s, s+256, '\0');
Here's how to assign or copy text into the array:
std::strcpy(s, "Hello");
You could also use std::copy:
static const char text[] = "World";
std::copy(text, text + sizeof(text), s);
Remember that a pointer, array and C-Style string are different concepts and objects.
Edit 1: Prefer std::string
In C++, prefer to use std::string for text rather than character arrays.
std::string s;
s = "abcdef";
std::cout << s << "\n";
Once you've allocated the memory for this string, you could use strcpy to populate it:
strcpy(s, "abcdef");

How do I convert a vector<string> to a const char* const* in c++?

I am trying to convert data into the right format for a specific unit test.
The task is to mine a set of words, the unit tests will make sure the results are correct. I have no access to the unit tests, just the declaration which takes a const char* const* Result.
So I need to get my
std::vector<string> Words;
to
const char* const* Result;
divided by a non-alpha char (for example space).
I am aware that this is a constant pointer to a constant character, so I am not sure what to do here since they both constant?
Any pointers (word pun not really intended) are appreciated!
You cannot meaningfully convert one to the other. However, you can convert an array of std::string into an array of pointers to char, and a pointer to the first element of such array would be compatible with your desired result:
std::vector<const char*> Ptrs;
std::transform(
std::cbegin(Words), std::cend(Words),
std::back_inserter(Ptrs),
[](auto& str) { return str.c_str(); }
);
const char* const* Result = Ptrs.data();
Just remember that the strings themselves are still stored in the std::string objects and those pointers within the new vector are only valid as long as the strings in the original vector exist, aren't resized, and the original vector itself isn't resized.
And the pointer to first element of the new vector is only valid as long as that vector exists and isn't resized.
Seems easy enough
#include <algorithm>
#include <functional>
// ...
std::vector<char const*> result_owner(Words.size());
std::transform(begin(Words), end(Words), begin(result_owner),
std::mem_fn(&std::string::c_str));
const char* const* Result = result_owner.data();
Just because Result must provide a const view of the buffer, doesn't mean the buffer has to really be const itself. So it's just another vector that we obtain by projecting Words on the std::string::c_str member.
After that Result can simply be another reference to result_owner.data();.
This of course assumes that Result doesn't have to own the buffer it points at. Owning raw pointers are best avoided.
And the caveman way to do it :)
#include <iostream>
#include <vector>
#include <string>
#include <string.h>
using namespace std;
char **foo(const vector<string> &vec_of_strings)
{
int num_strings = vec_of_strings.size();
int max_str_len = 0;
for (int i=0;i<num_strings;i++)
{
if (max_str_len < vec_of_strings[i].length()) {
max_str_len = vec_of_strings[i].length();
}
}
// for null termination ...
max_str_len++;
char **result = (char **) malloc(num_strings);
for (int i=0;i<num_strings;i++)
{
result[i] = (char *) malloc(max_str_len);
strcpy(result[i],vec_of_strings[i].c_str());
}
return result;
}
int main(int argc, char **argv)
{
vector<string> vec_of_strings;
vec_of_strings.push_back("Long");
vec_of_strings.push_back("Livvvvvvvve");
vec_of_strings.push_back("The");
vec_of_strings.push_back("King");
const char * const * Result = foo(vec_of_strings);
for (int i=0;i<4;i++)
{
printf("%s\n",Result[i]);
}
}

c++: Storing an adress as string

I'm trying to store the address of a pointer as a string. In other words, I want to insert the content of the bytes that make up the address into a char vector.
What is the best way of doing this?
I need a fully portable method, including for 64 bit system.
To get an array (or vector, if you prefer that) of the actual bytes of the address, this should do the trick:
int foo = 10;
int* bar = &foo;
// Interpret pointer as array of bytes
unsigned char const* b = reinterpret_cast<unsigned char const*>(&bar);
// Copy that array into a std::array
std::array<unsigned char, sizeof(void*)> bytes;
std::copy(b, b + sizeof(void*), bytes.begin());
To get an array containing the hexadecimal representation split up into single characters (whatever sense that makes), I'd use a stringstream - as some of the others already suggested. You can also use snprintf to get a string representation of the address, but that's more the C-style way.
// Turn pointer into string
std::stringstream ss;
ss << bar;
std::string s = ss.str();
// Copy character-wise into a std::array (1 byte = 2 characters)
std::array<char, sizeof(void*) * 2> hex;
std::copy(s.begin(), s.end(), hex.begin());
The simplest way is to do
char buf[sizeof(void*) * 2 + 3];
snprintf(buf, sizeof(buf), "%p", /* the address here */ );
std::string serialized (std::to_string ((intptr_t) ptr));
C++ way to dos this would be to use string streams
#include <string>
#include <sstream>
int main()
{
MyType object;
std::stringstream ss;
std::string result;
ss << &object; // puts the formatted address of object into the stream
result = ss.str(); // gets the stream as a std::string
return 0;
}
void storeAddr(vector<string>& v,void *ptr)
{
stringstream s;
s << (void*)ptr ;
v.push_back(s.str());
}

C++ char* array

When I create something like
char* t = new char[44];
t = strcpy(s,t);
then strlen(t); return some wrong results. how I can change this?
Both strcpy and strlen expect to find the special character NUL or '\0' in the array. An uninitialized array, as the one you've created, may contain anything at all, which means the behavior of your program is undefined when it is passed to strcpy as the source argument.
Assuming the goal was to copy s into t, to make the program behave as expected, try this:
#include <iostream>
#include <cstring>
int main()
{
const char* s = "test string";
char* t = new char[44];
// std::strcpy(t, s); // t is the destination, s is the source!
std::strncpy(t, s, 44); // you know the size of the target, use it
std::cout << "length of the C-string in t is " << std::strlen(t) << '\n';
delete[] t;
}
But keep in mind that in C++, strings are handled as objects of type std::string.
#include <iostream>
#include <string>
int main()
{
const std::string s = "test string";
std::string t = s;
std::cout << "length of the string in t is " << t.size() << '\n';
}
What are you trying to do? Do you want to copy from s to t? If so, the arguments to strcpy are reversed.
char* t = new char[44]; // allocate a buffer
strcpy(t,s); // populate it
Such C-style string processing is a red flag, but that's all I can say given this little information.
This code might be helpful:
char * strcpy (char * destination, const char * source);
t = strcpy(t, s);
You have to initialize the variable t
Do something like this:
char *t = new char[44];
memset(t, 0, 44);
// strlen(t) = 0
The strcpy function is described thus:
#include <string.h>
char *strcpy(char *dest, const char *src);
The strcpy() function copies the string pointed to by src (including the terminating '\0' character) to the array pointed to by dest.
So, if you are trying to fill in your newly allocated array, you should be doing:
strcpy(t, s);
Not the other way around.