开发者

Using a static string with a vector

My history with programming is in C and CPython. Please bear with me here.

To help me learn C++ I am converting one of my old C programs to use C++ OOP, but it's not working the way I want it to work. I don't care about speed. I just care about learning.

Here's my old C code I want to put into a Checksum class:

    //This is the standard CRC32 implementation
    //"rollingChecksum" is used so the caller can maintain the current 
    //checksum between function calls
    unsigned int CalculateChecksum(unsigned char* eachBlock, int* sbox, long lengthOfBlock, unsigned int rollingChecksum)
    {
       int IndexLookup;
       int blockPos;

       for(blockPos = 0; blockPos < lengthOfBlock; blockPos++)
       {
         IndexLookup = (rollingChecksum >> 0x18) ^ eachBlock[blockPos];
         rollingChecksum = (rollingChecksum << 0x08) ^ sbox[IndexLookup];
       }
       return rollingChecksum;
    }

So here's how I translated it into more C++'ey code:

 void Checksum::UpdateStream(std::vector<unsigned char> binaryData)
 {
   unsigned int indexLoo开发者_JAVA百科kup;
   unsigned int blockPos;

   for(blockPos = 0; blockPos < binaryData.size(); blockPos++)
   {
      indexLookup = (this->checksum >> 0x18) ^ binaryData[blockPos];
      this->checksum = (this->checksum << 0x08) ^ this->sbox[indexLookup];
   }
 }

But then when I try to use it:

int main(int argc, char* argv[])
{
 Checksum Test;
 Test.UpdateStream("foo bar foobar");
 std::cout << Test.getChecksum() << std::endl;
}

I get this error:

1>main.cpp(7) : error C2664: 'Checksum::UpdateStream' : cannot convert parameter 1 from 'const char [15]' to 'std::vector<_Ty>'
1>        with
1>        [
1>            _Ty=unsigned char
1>        ]
1>        No constructor could take the source type, or constructor overload resolution was ambiguous

I decided to use the vector container above instead of the string class because of how this question turned out on StackOverflow and because I want to use binary data here.

DESIRED RESULT: How can I pass both strings and binary data to this method to calculate its checksum? Do I need to overload it or typecast the string in main? I'm completely lost.


You could copy a char array content into a vector using std::copy:

std::vector< char > vector;
char str[] = "foo bar foobar";
vector.resize( sizeof(str)-1 ); // thanks to Alf (see comments)
std::copy( str, str+sizeof(str)-1, vector.begin() );

or even better using std::vector constructor:

char str[] = "foo bar foobar";
std::vector< char > vector( str, str+sizeof(str)-1 );

Note that this code will copy the whole string but the terminating \0 (again, see comments for more details).


Your checksum class deals with raw bytes data that can come from anywhere, so that basic interface shouldn't impose conversion to e.g. std::vector.

I.e. the unsigned char const* formal argument type of original C code was and is fine.

However, you can provide higher level wrappers for common callers' types, such as string literal, std::vector, you name it.

If you absolutely want to have a std::vector as the formal argument type for the fundamental function, then you can copy a string literal to it as follows:

char const  s[] = "blah blah";
std::vector<unsigned char> const v( s, s + strlen( s ) );

Cheers & hth.,


You can't create vector out of string literal. Well, not directly at least. This should work:

std::string tmp = "foo bar foobar"
Test.UpdateStream(std::vector<unsigned char>(tmp.begin(), tmp.end()));

You could also update your UpdateStream signature to use (const std::vector<unsigned char>& binaryData) to avoid copying, since you don't need to modify it.

To shorten the code, you can provide an overload of UpdateStream for string:

void Checksum::UpdateStream(const std::string& str) {
    UpdateStream(std::vector<unsigned char>(str.begin(), str.end()));
}


In C++ a string literal in that context will decay to a char pointer to the first char and there is no implicit constructor making a vector out of a char pointer. Also unsigned char and char are distinct types and while there are implicit conversion rules between them there are no conversion rules between a pointer to unsigned char and a pointer to char.

My suggestion is not to try to learn C++ by experimenting, because C++ is a complex language with a long evolution history... it has been designed by many different minds and even formal committees. In many places C++ is far from intuitive or logical because some rules are the result of evolution, committee effect or backward compatibility with things that now don't exist any more.

Add to that the problem that when you make a mistake in C++ you get easily UB daemons instead of runtime error angels and you'll understand that experimentation is just the wrong path to C++. No matter how smart someone can be there's no way to infer history using logical reasoning. History must be studied.

Do yourself a favor and grab "The C++ Programming Language" and read it cover-to-cover: there are a lot of things that for someone with a strong C background will be easy to understand once you put them in a framework and context. Other books I liked a lot and that are IMO also an easy reading are "C++ FAQs" by Marshall Cline and the "Effective" series from Scott Meyers.

C++ is a nice language but can easily become your worst nightmare if you approach it from the wrong side.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜