Ranged based loop to old style for old compilers

82 Views Asked by At

Recently I was trying to use this code to generate a MD5 from a String.

string SecureInfrastructure::Generate_MD5_FromString(const string &data)
{
    unsigned char result[MD5_DIGEST_LENGTH];
    MD5((unsigned char*)data.c_str(), data.size(), result);

    std::ostringstream sout;
    sout<<std::hex<<std::setfill('0');
    for(long long c: result)
    {
        sout<<std::setw(2)<<(long long)c;
    }
    return sout.str();
}

However, the compiler that I am using does not support range based for loops and I tried to convert this code into the traditional for(...;...;...) loop with the code presented below.

string SecureInfrastructure::Generate_MD5_FromString(const string &data)
{
    unsigned char result[MD5_DIGEST_LENGTH];
    MD5((unsigned char*)data.c_str(), data.size(), result);

    std::ostringstream sout;
    sout<<std::hex<<std::setfill('0');
    for(long long c; c<sizeof(result); c++) // long long c: result
    {
        sout<<std::setw(2)<<(long long)c;
    }
    return sout.str();
}

When, I tested it did not work because I am getting an empty string. I am having difficulties in find where the error is. How should I reimplement the first code with the traditional for-loop?

4

There are 4 best solutions below

0
On BEST ANSWER

When you have

for(long long c: result)
{
    sout<<std::setw(2)<<(long long)c;
}

the for(long long c: result) says: for each element in result assign it to a variable of type long long named c. The body of the loop then uses c. To get that same behavior in a regular for loop you need to do the same thing. To tell the compiler to loop through all the elements you need

for(size_t i = 0; i < MD5_DIGEST_LENGTH; i++)

instead of creating a variable you can just use the element directly in the loop. That would look like

sout<<std::setw(2)<<(long long)result[index_of_element];

and combining that together you get

for(size_t i = 0; i < MD5_DIGEST_LENGTH; i++)
{
    sout<<std::setw(2)<<(long long)result[i];
}
0
On

Here you use c uninitialized and start stepping it. That leads to undefined behaviour:

for(long long c; c<sizeof(result); c++) 

This should do it:

for(size_t i = 0; i < MD5_DIGEST_LENGTH; ++i) {
    sout << std::setw(2) << (unsigned) result[i];
}
0
On

Problem is that you are not initializing c and also you are not referring to the result array nowhere

for(long long c = 0; /*Initialize*/ c<sizeof(result); c++) // long long c: result
{
  //use result[c]
}
0
On

Use MD5_DIGEST_LENGTH instead of sizeof(result). And "c" has no initial value of 0 I think.