views:

167

answers:

6

Hello,

I'm trying to take a 2d vector of floats (input) and put them into a char* (output) in c++.

void foo(const std::vector<std::vector<float> > &input, char* &output )
{  
   char charBuf[sizeof(output)];
   int counter = 0;
   for(unsigned int i=0; i<input.size(); i++)
   {
      for(unsigned int p=0; p<input.at(i).size(); p++)
      {
         //what the heck goes here
      }
   }
A: 

What you're trying to do is called serialization. The C++ faq has a section dedicated to this: http://www.parashift.com/c++-faq-lite/serialization.html

Cogwheel - Matthew Orlando
+1  A: 

That depends greatly on what you mean by "put them into a char*".

Noah Roberts
-1 for it's not an answer. +1 for the question sorely needs clarification. So, my net action was this comment.
Nathan Ernst
+2  A: 

You could use a std::stringstream at each iteration to place the float into a std::string and then get the char* array from that. If you want one big char* array then just use a single string stream defined outside the loops.

Troubadour
+1  A: 

If you want the result to be human-readable, then you're after snprintf() -- that will convert the number 3.1415 into the string "3.1415". If you're just outputting data to be re-read by another program, then you can just dump the binary data into your output stream.

Just bear in mind that when you output the binary representation of a floating-point number, you have to be aware of how it's encoded. If you're both reading and writing on the same platform, then the encoding will be the same. In fact most desktop platforms use use the IEEE-754 spec for floating point numbers, but check up on it just to be safe.

Also, make sure that your output stream allows for some sort of versioning or other mechanism for modifying the format later on when you decide to do something different with it. Just a version number at the beginning is usually sufficient.

tylerl
It seems like you may need to clarify what "just dump the binary data into your output stream" would mean-- at least, I'm not sure what it means, because he doesn't (yet) have an output stream, just a char*.
mmr
snprintf() is rather outdated ;)
Alerty
@mmr: yes, the post was originally longer, but then I decided that it would do more harm than good to explain in any detail how to pursue that path, since it requires a lot more research before you can understand what you're really doing.
tylerl
A: 

The following code will get you a char* view of all the floats in your input parameter.

However, I'd very careful that this is actually what you want. The char* array is not endian robust, and I always try to avoid handing allocated pointers back to users. Anyone using this function will need to deallocate output with delete[], but that is in no way obvious from the function name or signature, a recipe for fragile code.

void foo(const std::vector<std::vector<float> > &input, char* &output )
{  
   //this was likely an error, it is always an array of size 4
   //char charBuf[sizeof(output)];

   std::vector<float> tmp_output;

   int counter = 0;  // Why was this here?

   for(unsigned int i=0; i<input.size(); i++)
   {
      // This is slightly more efficient than the hand rolled loop below.
      // std::copy( input[i].begin(), input[i].end(),
      //            std::back_inserter<float>(tmp_output) );

      for(unsigned int p=0; p<input.at(i).size(); p++)
      {
         tmp_output.push_back(input.at(i).at(p));
      }
   }
   output = new char[tmp_output.size()*sizeof(float)];
   std::copy( reinterpret_cast<const char*>(&(*tmp_output.begin())),
              reinterpret_cast<const char*>(&(*tmp_output.end())),
              output );
}
caspin
A: 

Don't try to put data into raw character arrays, especially when you don't know their size - which you don't here. Use a std::string instead, and a std::stringstream to write to it.

Whatever you do, get rid of that charBuf thing; anything you do with it will be wrong, since sizeof(output) is not the size of the output array.

Assuming you want a human-readable string, you might want something like

std::string foo(const std::vector<std::vector<float> > &input)
{
    std::ostringstream stream;
    for (std::size_t i = 0; i < input.size(); ++i)
    {
        if (i != 0) stream << "\n";
        for (std::size_t j = 0; j < input[i].size(); ++j)
        {
            if (j != 0) stream << ",";
            stream << input[i][j];
        }
    }

    return stream.str();
}
Mike Seymour