Передача по ссылке в inline функцию
От: tasko  
Дата: 07.12.10 12:35
Оценка:
Существует 2 почти идентичные функции по преобразованию вектора в строку.
Отличие — create_filtered_string игнорирует F и более "крупные числа"
  
inline void vector_to_string(std::vector<boost::uint8_t> const& in, std::string& out) {
        int len = in.size();

        char *p = new char(len + 1);

        for (int i = 0; i < len; i++)
            p[i] = in[i] < 10 ? in[i] + 48 : in[i] + 55;

        p[len] = 0;

        out = std::string(p);

        delete(p);
    }
    inline void create_filtered_string(std::vector<boost::uint8_t>& in, std::string& out) 
    {
        int len = in.size();
        char *p2 = new char(len + 1);
        for (int i = 0; i < len; i++)
        {
            if(in[i] < 10)
            {
                p2[i] = in[i] + 48;
            }
            else if(in[i] < 15)
            {
                p2[i] = in[i] + 55;
            }
        }       
        p2[len] = 0;        
        out = std::string(p2);
        delete(p2);
    }


Пример использования
unsigned char undef[] = {0x05 , 0x01 , 0x05 , 0x00 , 0x02 , 0x02 , 0x04 , 0x00 , 0x04 , 0x09 , 0x07 , 0x07 , 0x02 , 0x03 , 0x06 , 0x0f};
    std::vector<boost::uint8_t> tst(undef, undef + sizeof(undef));

    std::string out;
    ASN1::vector_to_string(tst, out);
    cout<<"vector_to_string(tst, out);"<<endl;
    std::cout<<out<<std::endl;
    
    std::string out2;   
    ASN1::create_filtered_string(tst, out2);
    cout<<"create_filtered_string(tst, out);"<<endl;
    std::cout<<out2<<std::endl;


но на выходе получаем интересное:
> ./convertVectorString 
ASN1::vector_to_string(tst, out);
515022404977236F
ASN1::create_filtered_string(tst, out);
515022404977236F

То есть идентичные строки.

Если из объявления
void create_filtered_string(std::vector<boost::uint8_t>& in, std::string& out)
убрать ссылочность на in и оставить std::vector<boost::uint8_t> in все проходит ожидаемо — F на конце не входит в итоговую строку.
> ./convertVectorString 
ASN1::vector_to_string(tst, out);
515022404977236F
ASN1::create_filtered_string(tst, out);
515022404977236


Что за особенность поведения такая?
с++ ссылки inline
Re: Передача по ссылке в inline функцию
От: uzhas Ниоткуда  
Дата: 07.12.10 13:08
Оценка:
Здравствуйте, tasko, Вы писали:

T>Что за особенность поведения такая?

char *p = new char(len + 1);

у вас тут нет проблем?
Re[2]: Передача по ссылке в inline функцию
От: tasko  
Дата: 07.12.10 14:02
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, tasko, Вы писали:


T>>Что за особенность поведения такая?

U>
U>char *p = new char(len + 1);
U>

U>у вас тут нет проблем?

Вроде нет
+1 символ для завершающего: p[len] = 0;
во втором случае возможен вариант что не будет использован вся выделенная под len+1 элемент память.
согласно описанию конструктора должно быть все хорошо
string ( const char * s );
Content is initialized to a copy of the string formed by the null-terminated character sequence (C string) pointed by s. The length of the caracter sequence is determined by the first occurrence of a null character (as determined by traits.length(s)). This version can be used to initialize a string object using a string literal constant.
Re[3]: Передача по ссылке в inline функцию
От: uzhas Ниоткуда  
Дата: 07.12.10 14:09
Оценка:
Здравствуйте, tasko, Вы писали:

T>Здравствуйте, uzhas, Вы писали:


U>>Здравствуйте, tasko, Вы писали:


T>>>Что за особенность поведения такая?

U>>
U>>char *p = new char(len + 1);
U>>

U>>у вас тут нет проблем?

T>Вроде нет

мне кажется, что вы не заметили ошибку
http://codepad.org/sDsLwlPt
для аллокации массивов следует использовать операторы new[]/delete[]
не по теме:
и вообще, рекомендую вам не использовать эти низкоуровневые операторы, а воспользоваться
std::string output(len, 0);
for (size_t x = ...)
{
  output[x] = ...
}
out = output;

это повысит надежность кода и устойчивость к исключениям (ну или RAII используйте вместо голых указателей)
при выходе за пределы контейнера в дебуге могут ассерты вам помочь
еще можно посмотреть в сторону std::transform
успехов
Re[4]: Передача по ссылке в inline функцию
От: uzhas Ниоткуда  
Дата: 07.12.10 14:22
Оценка:
набил я ваш код и вот что получил:
исходный код:
http://codepad.org/H4vIjlLP
подфикшенный код:
http://codepad.org/5nURjSpj
можете обратить внимание на комментарий, ибо там забытая логика
успехов
Re[5]: Передача по ссылке в inline функцию
От: uzhas Ниоткуда  
Дата: 07.12.10 14:33
Оценка: 1 (1)
Здравствуйте, uzhas, Вы писали:

U>набил я ваш код и вот что получил:

U>исходный код:
U>http://codepad.org/H4vIjlLP
U>подфикшенный код:
U>http://codepad.org/5nURjSpj
U>можете обратить внимание на комментарий, ибо там забытая логика
U>успехов
от делать нечего написал свою версию фильтрационной функции
http://codepad.org/BeOtcWS2
возможно, вам что-то пригодится
успехов)
Re[4]: Передача по ссылке в inline функцию
От: tasko  
Дата: 08.12.10 19:05
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, tasko, Вы писали:


T>>Здравствуйте, uzhas, Вы писали:


U>>>Здравствуйте, tasko, Вы писали:


T>>>>Что за особенность поведения такая?

U>>>
U>>>char *p = new char(len + 1);
U>>>

U>>>у вас тут нет проблем?

T>>Вроде нет

U>мне кажется, что вы не заметили ошибку
U>http://codepad.org/sDsLwlPt
U>для аллокации массивов следует использовать операторы new[]/delete[]

спасибо, действительно как-то мимо прошел Ваш намек

ps странно. не мог целый день залогиниться на rsdn... просто не давал зайти не под логином не анонимно.
Re[5]: Передача по ссылке в inline функцию
От: tasko  
Дата: 08.12.10 19:07
Оценка:
Здравствуйте, uzhas, Вы писали:

U>набил я ваш код и вот что получил:

U>исходный код:
U>http://codepad.org/H4vIjlLP
U>подфикшенный код:
U>http://codepad.org/5nURjSpj
U>можете обратить внимание на комментарий, ибо там забытая логика
U>успехов

после фикса new[] / delete[] проблема у меня так и осталась.
про забытую логику. она не совсем забытая. обрабатываются только интересующие нас символы.
Re[6]: Передача по ссылке в inline функцию
От: tasko  
Дата: 08.12.10 19:13
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, uzhas, Вы писали:


U>>набил я ваш код и вот что получил:

U>>исходный код:
U>>http://codepad.org/H4vIjlLP
U>>подфикшенный код:
U>>http://codepad.org/5nURjSpj
U>>можете обратить внимание на комментарий, ибо там забытая логика
U>>успехов
U>от делать нечего написал свою версию фильтрационной функции
U>http://codepad.org/BeOtcWS2
U>возможно, вам что-то пригодится
U>успехов)

спасибо за шаблон
после небольшой доработки функция приняла вид:


#define DT_EXCLUDE_FILLER       0
#define DT_INCLUDE_FILLER       1

    inline void vector_to_string(Common::ArrayOfUInt8 const& in, Common::String& out, Common::Bool includeFiller = DT_INCLUDE_FILLER)
    {
        out.clear();
        for (Common::ArrayOfUInt8::const_iterator i = in.begin(); i != in.end(); ++i)
        {
            if (*i < (15 + includeFiller))
            {
                out.push_back(((*i) < 10 ? (*i) + 48 : (*i) + 55));
            }
        }
    }

    inline void string_to_vector(Common::String const& in, Common::ArrayOfUInt8& out, Common::Bool includeFiller = DT_INCLUDE_FILLER)
    {
        out.clear();
        for(Common::String::const_iterator iter = in.begin(); iter != in.end(); ++iter)
        {
            //0-9
            if((*iter > 0x02F) && (*iter < 0x03A))
            {
                out.push_back(*iter - 0x030);
            }
            //A-E + fillerFlag
            else if((*iter > 0x040) && (*iter < (0x046 + includeFiller)))
            {
                out.push_back(*iter - 55);
            }
            //a-e  + fillerFlag
            else if((*iter > 0x060) && (*iter < (0x066 + includeFiller)))
            {
                out.push_back(*iter - 87);
            }
        }
    }


вопрос со странностью поведения & так и остался :/
Re[6]: Передача по ссылке в inline функцию
От: 24  
Дата: 08.12.10 19:43
Оценка:
Здравствуйте, tasko, Вы писали:

T>после фикса new[] / delete[] проблема у меня так и осталась.


Проблема в том, длина результирующей строки во втором случае получается меньше, чем len (в условии обрабатываются не все варианты). В данном случае остаётся один "недозаполненный" символ: 515022404977236<мусор>#0, и #0 (признак конца строки) стоит не сразу после окончания нужных данных. Так совпало, что на месте мусора оказалась F (скорее всего с прошлой функции). Поменяй вызовы функций местами — этой F с большой вероятностью там не будет. Решение — считать кол-во использованных символов, и ставить признак конца не p2[len] = 0, а p2[count] = 0.
Re[7]: Передача по ссылке в inline функцию
От: tasko  
Дата: 09.12.10 21:12
Оценка:
Здравствуйте, 24, Вы писали:

24>Здравствуйте, tasko, Вы писали:


T>>после фикса new[] / delete[] проблема у меня так и осталась.


24>Проблема в том, длина результирующей строки во втором случае получается меньше, чем len (в условии обрабатываются не все варианты). В данном случае остаётся один "недозаполненный" символ: 515022404977236<мусор>#0, и #0 (признак конца строки) стоит не сразу после окончания нужных данных. Так совпало, что на месте мусора оказалась F (скорее всего с прошлой функции). Поменяй вызовы функций местами — этой F с большой вероятностью там не будет. Решение — считать кол-во использованных символов, и ставить признак конца не p2[len] = 0, а p2[count] = 0.


Спасибо

"на месте мусора оказалась F (скорее всего с прошлой функции)".
Если передавать по сссылке параметры во вторую функцию то такое совпадение происходило.
Если же не по ссылке то происходило копировани вектора, как результат память new выделялась в "другом" месте.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.