Как преобразовать целое число в беззнаковый символ в C, учитывая целые числа больше 256? - PullRequest
1 голос
/ 07 января 2011

В рамках моего курса CS мне были даны некоторые функции для использования. Одна из этих функций берет указатель на беззнаковые символы для записи некоторых данных в файл (я должен использовать эту функцию, поэтому я не могу просто сделать свою собственную встроенную функцию, которая работает иначе, кстати) Мне нужно написать массив целых чисел, чьи значения могут быть до 4095 с помощью этой функции (которая принимает только беззнаковые символы).

Однако правильно ли я считаю, что беззнаковый символ может иметь максимальное значение только 256, поскольку его длина составляет 1 байт? Поэтому мне нужно использовать 4 знака без знака для каждого целого числа? Но приведение не работает с большими значениями для целого числа. Кто-нибудь знает, как лучше всего преобразовать массив целых чисел в беззнаковые символы?

Ответы [ 7 ]

5 голосов
/ 07 января 2011

Обычно беззнаковый символ содержит 8 битов с максимальным значением 255. Если вы хотите узнать это для вашего конкретного компилятора, распечатайте CHAR_BIT и UCHAR_MAX из <limits.h> Вы можете извлечь отдельные байты32-битного целого,

#include <stdint.h>

void
pack32(uint32_t val,uint8_t *dest)
{
        dest[0] = (val & 0xff000000) >> 24;
        dest[1] = (val & 0x00ff0000) >> 16;
        dest[2] = (val & 0x0000ff00) >>  8;
        dest[3] = (val & 0x000000ff)      ;
}


uint32_t
unpack32(uint8_t *src)
{
        uint32_t val;

        val  = src[0] << 24;
        val |= src[1] << 16;
        val |= src[2] <<  8;
        val |= src[3]      ;

        return val;
}
2 голосов
/ 08 января 2011

Беззнаковый символ обычно имеет значение 1 байт, поэтому вы можете разложить любой другой тип на массив беззнаковых символов (например, для 4-байтового типа int вы можете использовать массив из 4 беззнаковых символов).Ваше упражнение, вероятно, о дженериках.Вы должны записать файл как двоичный файл, используя функцию fwrite (), и просто записать в файл байт за байтом.

Следующий пример должен записать число (любого типа данных) в файл.Я не уверен, что это сработает, так как вы заставляете приводить к unsigned char * вместо void *.

int homework(unsigned char *foo, size_t size)
{
    int i;

    // open file for binary writing
    FILE *f = fopen("work.txt", "wb");
    if(f == NULL)
        return 1;

    // should write byte by byte the data to the file
    fwrite(foo+i, sizeof(char), size, f);

    fclose(f);
    return 0;
}

Надеюсь, приведенный пример по крайней мере даст вам отправную точку.

0 голосов
/ 08 января 2011

Если вам нужно написать массив целых чисел, просто преобразуйте массив в указатель на символ, а затем выполните массив.

int main()
{
    int    data[] = { 1, 2, 3, 4 ,5 };
    size_t size   = sizeof(data)/sizeof(data[0]); // Number of integers.

    unsigned char* out = (unsigned char*)data;
    for(size_t loop =0; loop < (size * sizeof(int)); ++loop)
    {
         MyProfSuperWrite(out + loop);  // Write 1 unsigned char
    }
}

Теперь люди упоминают, что 4096 будет помещаться в меньшем количестве бит, чем нормальное целое число. Наверное, правда. Таким образом, вы можете сэкономить место и не записывать старшие биты каждого целого числа. Лично я думаю, что это не стоит усилий. Дополнительный код для записи значения и обработки входящих данных не стоит той экономии, которую вы бы получили (возможно, если бы данные были размером с библиотеку конгресса). Правило одно: выполняйте как можно меньше работы (ее легче поддерживать). Правило два оптимизировать, если спросить (но сначала спросите, почему). Вы можете сэкономить место, но это будет стоить времени обработки и затрат на обслуживание.

0 голосов
/ 08 января 2011

Без информации о функции, которую вы должны использовать относительно ее аргументов, возвращаемого значения и семантики (то есть определения ее поведения), трудно ответить. Одна возможность:

Дано:

void theFunction(unsigned char* data, int size);

тогда

int array[SIZE_OF_ARRAY];
theFunction((insigned char*)array, sizeof(array));

или

theFunction((insigned char*)array, SIZE_OF_ARRAY * sizeof(*array));

или

theFunction((insigned char*)array, SIZE_OF_ARRAY * sizeof(int));

Все они передадут все данные в theFunction(), но будет ли смысл иметь значение, зависит от того, что theFunction() сделает.

0 голосов
/ 07 января 2011

Часть задания: integers whose values can be up to 4095 using this function (that only takes unsigned chars должна дать вам огромный намек. 4095 без знака - 12 бит.

Вы можете хранить 12 бит в 16 битах short, но это несколько расточительно - вы используете только 12 из 16 битов короткого. Поскольку при преобразовании символов вы имеете дело с более чем 1 байтом, вам, возможно, придется иметь дело с endianess результата. Самый простой.

Вы также можете использовать битовое поле или некоторую упакованную двоичную структуру, если вас беспокоит пространство. Больше работы.

0 голосов
/ 07 января 2011

Похоже, что вы действительно хотите сделать, это вызвать sprintf, чтобы получить строковое представление ваших целых чисел.Это стандартный способ преобразования числового типа в его строковое представление.Что-то вроде следующего может начать вас:

char num[5]; // Room for 4095

// Array is the array of integers, and arrayLen is its length
for (i = 0; i < arrayLen; i++)
{
    sprintf (num, "%d", array[i]);

    // Call your function that expects a pointer to chars
    printfunc (num);
}
0 голосов
/ 07 января 2011

Да, вы правы; символ / байт допускает только до 8 различных битов, так что это 2 ^ 8 различных чисел, от нуля до 2 ^ 8 - 1 или от нуля до 255. Чтобы получить байты, сделайте что-то подобное:

int x = 0;
char* p = (char*)&x;
for (int i = 0; i < sizeof(x); i++)
{
    //Do something with p[i]
}

(Это официально не C из-за порядка объявления, но как бы там ни было ... это более читабельно. :))

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

...