Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите осилить алгоритм преобразования числа в байты

408
09 июля 2011 года
Lei fang
265 / / 01.10.2005
Сразу вспомнилась эта http://pachkov.ru/wp-content/uploads/2008/03/windows_vista.jpg картинка, только в отношении к подобным преобразованиям.

суть проблемы в том, что есть у меня массив из 44 байтов к примеру.
не важно что он хранит, важно что последние 4 байта отвечают за число.
вот пара примеров:
 
Код:
//55 47 28 00 29 87 1C 00 07 00 07 00 B5 0E 00 00 17 00 00 00 17 00 00 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF E0 F5 05 - число 99999999
//55 47 28 00 7C 9F 1C 00 07 00 07 00 B1 C2 00 00 17 00 00 00 17 00 00 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 - число 1
//55 47 28 00 00 00 1C 00 07 00 07 00 6F D2 01 00 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 32 00 00 00 - число 50
//55 47 28 00 00 00 1C 00 07 00 07 00 5D 8B 00 00 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 - число 256


мне надо туда записывать свои числа... в эти последние 4 байта.
возникает огромное множество проблем, связанных с тем, каким образом разбить число так на байты и записать...

в wpf к примеру есть замечательная функция pint которая и занимается подобными вещами.
к примеру в результате pint(buf, 50, 40, 4);
50 - число которое преобразовать
40 - начальный элемент массива
4 количество байт отведенных под число
массив с неважно какими последними 4 байтами превратится в
 
Код:
//55 47 28 00 00 00 1C 00 07 00 07 00 5D 8B 00 00 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 32 00 00 00


я пытался сделать такой же аналог... ну или хотя бы получить массив из 4 байт, где бы хранилось то что мне надо (32 00 00 00 к примеру).
просидел весь день пытаясь сделать все возможные методы конветирования этих штук %)

последний вариант моей хрени
Код:
// TestPacket.cpp: определяет точку входа для консольного приложения.
//

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

#include <string>
#include <bitset>
#include <sstream>

char* double_to_hex_string(double value)
{
    static char result[1000];
    char *p = result;
    char *p_bound = p + sizeof(result) - 1;

    double v = value;
    double a = 1.0;

    if( v < 0 ) return "(value is negative)";

    while( a * 16 <= v ) a *= 16;

    while( a >= 1 )
    {
        int m;
        for( m = 0; m < 16 && (m + 1) * a <= v; m++ ) {}
        if( p < p_bound ) *p++ = "0123456789abcdef"[ m ], *p = 0;
        v -= m * a;
        a /= 16;
    }

    return result;
}

void string_to_bytearray(std::string str, unsigned char* &array, int& size)
{
    int length = str.length();
    // make sure the input string has an even digit numbers
    if(length % 2 == 1)
    {
        str = "0" + str;
        length++;
    }

    // allocate memory for the output array
    array = new unsigned char[length / 2];
    size = length / 2;

    std::stringstream sstr(str);
    for(int i = 0; i < size; i++)
    {
        char ch1, ch2;
        sstr >> ch1 >> ch2;
        int dig1, dig2;

        if(isdigit(ch1)) dig1 = ch1 - '0';
        else if(ch1 >= 'A' && ch1 <= 'F') dig1 = ch1 - 'A' + 10;
        else if(ch1 >= 'a' && ch1 <= 'f') dig1 = ch1 - 'a' + 10;

        if(isdigit(ch2)) dig2 = ch2 - '0';
        else if(ch2 >= 'A' && ch2 <= 'F') dig2 = ch2 - 'A' + 10;
        else if(ch2 >= 'a' && ch2 <= 'f') dig2 = ch2 - 'a' + 10;

        array = dig1 * 16 + dig2;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    //unsigned char* buf = NULL;
    //int size;

    //BYTE* temp = (BYTE*)double_to_hex_string(50);
    char hex_num[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    BYTE inv_hex_num[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    BYTE result_num[] = { 0, 0, 0, 0 };

    itoa(256, hex_num, 16);

    if (strlen(hex_num) % 2 == 1)
    {
        char temp[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
        temp[0] = 0;

        for (int i = 1; i < 8; i++)
            temp = hex_num[i - 1];

        memcpy(hex_num, temp, 8);
    }

    for(int i = 0; i < 8; i++)
        inv_hex_num[7 - i] = hex_num;

    memcpy(hex_num, inv_hex_num, 8);

    std::string hex_num_str = "";
    if (hex_num[7] != 0) hex_num_str += hex_num[7];
    hex_num_str += hex_num[6];
    result_num[3] = (BYTE)strtol(hex_num_str.c_str(), NULL, 16);

    hex_num_str.clear();
    if (hex_num[5] != 0) hex_num_str += hex_num[5];
    hex_num_str += hex_num[4];
    result_num[2] = (BYTE)strtol(hex_num_str.c_str(), NULL, 16);

    hex_num_str.clear();
    if (hex_num[3] != 0) hex_num_str += hex_num[3];
    hex_num_str += hex_num[2];
    result_num[1] = (BYTE)strtol(hex_num_str.c_str(), NULL, 16);

    hex_num_str.clear();
    if (hex_num[1] != 0) hex_num_str += hex_num[1];
    hex_num_str += hex_num[0];
    result_num[0] = (BYTE)strtol(hex_num_str.c_str(), NULL, 16);

    //string_to_bytearray(hex_num, buf, size);
   
    //int i = 0;

    //delete [] buf;

    return 0;
}


все работает не так как надо с начала и до конца %)
Смысла говорить что получается нет, так как ничего адекватного не получается вообще.
Может кто-то помочь с адекватным алгоритмом таких преобразований?
так чтоб на входе было число 50 к примеру, а на выходе массив из 4 байт {32, 00, 00, 00}
на входе 256, на выходе {00, 01, 00, 00}
278
09 июля 2011 года
Alexander92
1.1K / / 04.08.2008
[QUOTE=Lei fang]
Может кто-то помочь с адекватным алгоритмом таких преобразований?
так чтоб на входе было число 50 к примеру, а на выходе массив из 4 байт {32, 00, 00, 00}
на входе 256, на выходе {00, 01, 00, 00}
[/QUOTE]

Числа целые?
 
Код:
unsigned char *pack_int(int X, unsigned char *buf) {
    buf[0] = (X & 0x000000FF);
    buf[1] = (X & 0x0000FF00) >> 8;
    buf[2] = (X & 0x00FF0000) >> 16;
    buf[3] = (X & 0xFF000000) >> 24;
    return buf;
}
408
09 июля 2011 года
Lei fang
265 / / 01.10.2005
числа целые. сейчс попробую ваш вариант.
там еще это смена позиции начального числа меня в ступор вводит.
если 50 превращается в 32 00 00 00, то 99999999 превращается в FF E0 F5 05
т.е. в первом случае число начинается с 1 байта, а во втором с четвертого. %)
278
09 июля 2011 года
Alexander92
1.1K / / 04.08.2008
Ну это то, что называется little-endian и big-endian. Порядок байтов должен быть строго оговорен стандартом.
408
09 июля 2011 года
Lei fang
265 / / 01.10.2005
Работает :D
мда мда мда... гляда на то что я напрогал, и ваши несколько строк, понимаю что мне еще учиться и учиться.
Премного благодарен!
87
09 июля 2011 года
Kogrom
2.7K / / 02.02.2008
В качестве дополнения:

Код:
#include <stdio.h>
#include <stdint.h>


union PackInt
{
    uint8_t parts[4];
    uint32_t data;
};

int main()
{
    PackInt a;
    a.data = 50;
    printf("%02X, %02X, %02X, %02X", a.parts[0], a.parts[1], a.parts[2], a.parts[3]);
    return 0;
}


Правда тут используется stdint.h, что, возможно, может быть проблемой для старых компиляторов.
278
09 июля 2011 года
Alexander92
1.1K / / 04.08.2008
Кстати, можно мой вариант вообще в одну строчку написать:

 
Код:
unsigned char *pack_int(int X, unsigned char *buf) {
    sprintf(buf, "%c%c%c%c", (X & 0x000000FF), (X & 0x0000FF00) >> 8, (X & 0x00FF0000) >> 16, (X & 0xFF000000) >> 24);
    return buf;
}
14
11 июля 2011 года
Phodopus
3.3K / / 19.06.2008
А для x86 и AMD64 - вообще достаточно записать uint32_t по адресу начала числа
278
11 июля 2011 года
Alexander92
1.1K / / 04.08.2008
Да, только так, насколько мне сдается, можно получить только big-endian. А вообще, красивое решение. :)
10
11 июля 2011 года
Freeman
3.2K / / 06.03.2004
Нет, наоборот. На Intel работает, а насчёт big endian не уверен. В Delphi так вообще описанный Kogrom-ом тип для приведения является штатным, сидит в SysUtils.
260
11 июля 2011 года
Ramon
1.1K / / 16.08.2003
Little-endian / big-endian -какая разница. Но IA это не ARM и в нем только little. А насчет юниона - это платформенно зависимое решение, собственно как и раскладка в памяти.
5.9K
04 сентября 2011 года
assign
60 / / 13.12.2005
 
Код:
unsigned char array[44] = {...}; // Ваш массив
int *pointer = (int*)(array + 40); // адрес последних 4-х байт
*pointer = N; // где N - Ваше число


Число будет "разбито" на байты и размещено в последних 4-х элементах массива в формате little endian на платформе X86.
18K
05 сентября 2011 года
rrrFer
50 / / 08.09.2008
зачем преобразовывать в строку я не понял:
Цитата:
мне надо туда записывать свои числа... в эти последние 4 байта.
возникает огромное множество проблем, связанных с тем, каким образом разбить число так на байты и записать...


Если надо записывать что-то в последние 4 байта - то и используй memcpy
Ну или можно считать все кроме 4 байтов в поток, а вместо 4 байтов ввести туда свои данные...потом вывести из потока.
Вобщем зависит от конкретных нужд
Если нужен вариант Kogrom, но старый компилятор - то можно соорудить примерно такой велосипед:

Код:
#include <stdio.h>
union Int {
    unsigned long int data;
    struct {
        unsigned char
            p1 :8,
            p2 :8,
            p3 :8,
            p4 :8;
    } bt;
};

int main( ) {
    Int a;
    a .data = 50;
   
    printf("%02X, %02X, %02X, %02X", a .bt .p1, a .bt .p2, a .bt .p3, a .bt .p4);
    return 0;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог