Как записать число в файл в двоичном режиме?
int value = 11; // . . . 00001011
В строковом режиме можно просто использовать fprintf(fp, «%d», value) и тогда в файл запишется символьное представление числа 11.
А как записать в файл двоичное представление числа, т.е само число а не строку.
Знаю только про методы fread/fwrite , но с помощью них можно записать только массив данных.
А как записать в файл одиночное число?
- Вопрос задан более трёх лет назад
- 1594 просмотра
1 комментарий
Простой 1 комментарий
Массив из одного числа. В качестве массива попробуй указатель на число.
Решения вопроса 1
GrigorySvetov @GrigorySvetov
1. Если про бинарный вывод (т.е. когда сам символ смысловой нагрузки не несет, а несет номер символа в кодировке) («настоящий» бинарный вывод).
Основной прикол в том, что массив в Си можно понимать как просто указатель на фиксированный по размеру набор значений, а саму переменную массива — как указатель на этот набор.
И действительно, так привычное нам обращение по индексу arr[i] в Си переводится в *(arr+i) (разыменование по указателю со смещением).
Поэтому когда мы пишем fwrite(arr, . ), на самом деле мы пишем туда УКАЗАТЕЛЬ. В остальном Си достаточно всё равно, что происходит (главное чтобы без выходов на чужую память, иначе тут уже система убьет процесс). Т.е. мы передаем указатель на ЧИСЛО (одно число) как будто это целый массив, дальше всё честно для него пишем. Код получается вот такой:
#include int main() < FILE *fp; //переменная файлового потока int value=11; //наша переменная с числом fp=fopen("output.txt","wb");//открываем файл на перезапись ('w') в бинарном режиме ('b' в "wb") if (fp==NULL)< //если файл не был открыт, то. perror("file hadn't opened");//вывести в поток ошибок сообщение (обычно это то же, что поток вывода (т.е. экран компьюетра) >else < //иначе.. fwrite(&value,sizeof(int),1,fp); //вывести значение как массив с единственной ячейкой >fclose(fp);//закрыть в любом случае (если fp==NULL, ошибкой всё равно не будет, а читается удобнее, чем все эти ветки if'ов return 0; >
2. Если про то, что в комментарии, т.е. с ноликами и единичками в файле. Это «ненастоящий» бинарный режим, т.к. каждый символ ‘0’ и ‘1’ — это правда честные отдельные символы, которые надо читать как текст. В этом случае, я думаю, Вы просто это число побитно обрабатываете и fputc()’ом загоняете (но fopen() будет уже таким: fopen(«», «w»); (а не fopen(»
Битовые операции в языке Си. Восьмеричные и шестнадцатеричные числа
Данный урок курса можно считать факультативным, т. е. необязательным. Для освоения темы этого урока вам потребуется знание о двоичной системе счисления, навыки перевода чисел из одной системы счисления в другую, а также вы должны иметь представление о том, что такое битовые (они же поразрядные) операции. С последним можно познакомиться по вот этой лекции.
В языке программирования C существуют следующие поразрядные операции: & (И), | (ИЛИ), ^ (исключающее ИЛИ), > (сдвиг вправо), ~ (поразрядное дополнение до единицы). Рассмотрим на примерах, как они работают, но перед этим уделим внимание выводу чисел в отличных от десятичной системах счисления.
В C можно присваивать целочисленные значения в десятичной, восьмеричной и шестнадцатеричной системах счисления. Для того, чтобы присвоить переменной число в восьмеричной системе счисления, перед ним надо написать 0 (ноль), в шестнадцатеричной — 0x (ноль и икс), например:
int a, b; a = 077; // восьмеричное число b = 0x1F; // шестнадцатеричное число
Любые целые числа можно выводить на экран в десятичном, восьмеричном и шестнадцатеричном представлении. Пример кода для вывода определенных ранее двух переменных в различных системаъ счисления:
printf("%d %o %x %X\n", a, a, a, a); printf("%d %o %x %X\n", b, b, b, b);
В результате на экране вы увидите:
63 77 3f 3F 31 37 1f 1F
Восьмеричные и шестнадцатеричные числа используются из-за удобства при работе с двоичной системой счисления. Каждая цифра восьмеричного числа может быть заменена тремя цифрами двоичного. И каждая цифра шестнадцатеричного числа легко заменяет четыре разряда двоичного числа. Вот таблица соответствия цифр восьмеричной системы счисления числам двоичной системы:
| 0 | 000 |
| 1 | 001 |
| 2 | 010 |
| 3 | 011 |
| 4 | 100 |
| 5 | 101 |
| 6 | 110 |
| 7 | 111 |
Теперь допустим, что у нас есть восьмеричное число 037. По таблице легко понять, что в двоичном выражении оно будет выглядеть как 011 111.
Шестнадцатеричное число 7D в двоичной системе счисления будет выглядеть как 0111 1101.
Если бы мы при работе с поразрядными операциями использовали десятичные числа, то чтобы оценить результат нам бы каждый раз приходилось переводить десятичное число в двоичную систему счисления, что относительно трудоемко. Если же человек видит, например, восьмеричное число, то он может представить как оно выглядит в двоичном представлении, помня или держа перед глазами таблицу соответствия чисел. Например, как только мы видим 017, то можем представить в уме, как последние четыре бита ячейки памяти забиты единицами.
Теперь вернемся к поразрядным операциям и посмотрим как работает каждая из них. Для этого напишем небольшую программу:
int a, b; a = 017; b = 036; printf("0%o & 0%o = 0%o\n", a, b, a & b); printf("0%o | 0%o = 0%o\n", a, b, a | b); printf("0%o ^ 0%o = 0%o\n", a, b, a ^ b); printf("0%o \n", a, a 2); printf("0%o >> 2 = 0%o\n", a, a >> 2); printf("~0%o = 0%o\n", a, ~a);
Результат ее работы будет выглядеть так:
017 & 036 = 016 017 | 036 = 037 017 ^ 036 = 021 017 > 2 = 03 ~017 = 037777777760
Этот результат будет проще понять с помощью рисунка:

В последнем случае получилось такое большое число потому, что под форматы вывода целых чисел ( %d , %o , %X ) выделяется по 4 байта.
Теперь рассмотрим пример использования битовых операций. Допустим, у нас есть массив, требуется снять с него «маску», которая бы отражала, в какой позиции стоят отрицательные, а в какой положительные элементы. Пусть единица в бите обозначает соответствующий ей положительный элемент массива, а ноль — отрицательный. Так «битовая маска» массива будет выглядеть как 101110, или в восьмеричном представлении как 056. Составим алгоритм решения этой задачи:
- Будем считать, что массив состоит не более чем из 32 элементов. Поэтому для хранения его «маски» достаточно переменной типа int . Назовем ее mask и присвоим значение 0.
- Переберем элементы массива в цикле for . Если встречается положительный элемент, то установим соответствующий ему бит значения mask в 1.
- Выведем значение переменной mask на экран в виде восьмеричного числа.
Вроде бы все просто, но как установить в единицу определенный бит числа? Существует закономерность соответствия степеней двойки и двоичного представления числа:
2 0 = 0000 0001
2 1 = 0000 0010
2 2 = 0000 0100
2 3 = 0000 1000
2 4 = 0001 0000
и т.д. Теперь если применить к mask побитовую операцию | (ИЛИ), а в качестве второго операнда использовать определенную степень двойки, то один бит будет установлен в 1. Например:
(0) 0000 0000 | (2 5 ) 0010 0000 = 0010 0000
(32) 0010 0000 | (2 7 ) 1000 0000 = 1010 0000
При переборе первый элемент массива имеет индекс 0, но соответствующий ему бит в maskдолжен стоять впереди остальных. Если известно общее количество элементов массива (N), то можно определить степень двойки по формуле N — i — 1 . Так, имея четвертый положительный элемент массива (его индекс 3) из 10 элементов, следует установить в единицу седьмой с конца бит (он же будет четвертым с начала), а это значит надо использовать вторым операндом битового ИЛИ 2 6 , а 6 как раз будет 10( N ) — 3( i ) — 1.
Другая проблема — как в языке C возвести число в степень. Понятно, что можно написать свой код, но скорее всего в стандартной библиотеке уже есть подобная функция. С помощью заголовочного файла math.h можно подключить библиотеку с математическими функциями. Среди них есть функция pow() , которая принимает два числа и возвращает результат возведения первого числа в степень, выраженную вторым числом. Однако результат возвращается в виде вещественного числа, а нам требуется целое. Как быть? В Си есть операции приведения типов, которые меняют тип значения с одного на другой. Например, чтобы преобразовать значение вещественной переменной a в целое, следует написать (int) a .
Вот как может выглядеть вышеописанная программа:
#include #include #define N 12 int main() { int nums[N] = {7, 3, 9, -5, -3, 2, 1, 0, 16, -4, 2, 0}; int mask = 0; for (int i = 0; i N; i++) if (nums[i] >= 0) mask = mask | (int) pow(2, N-i-1); printf("%o\n", mask); }
Если у вас не получается скомпилировать программу, добавьте в конце вызова gcc опцию -lm (например, gcc -o bits bits.c -lm ).
Курс с решением задач:
pdf-версия
Как вывести число в двоичном виде cи
видел манипуляторы, которые переводят число в hex, oct формат, а как быть если нужно в двоичном выбросить?
Заранее благодарю.
С уважением Fynjisx
Re: Как в поток вывести двоичное представление числа?
| От: | placement_new |
| Дата: | 10.10.10 08:06 |
| Оценка: |
Здравствуйте, Fynjisx, Вы писали:
F>Привет ВСем! Есть поток, ofstream.
F>В него вывожу так:
F>
F> ofstream ss; F> . F> ss . F>
F>видел манипуляторы, которые переводят число в hex, oct формат, а как быть если нужно в двоичном выбросить?
Самому написать?
Re: Как в поток вывести двоичное представление числа?
| От: | LaptevVV | |
| Дата: | 10.10.10 08:19 | |
| Оценка: | 4 (2) | |
Здравствуйте, Fynjisx, Вы писали:
F>Привет ВСем! Есть поток, ofstream.
F>В него вывожу так:
F>
F> ofstream ss; F> . F> ss . F>
F>видел манипуляторы, которые переводят число в hex, oct формат, а как быть если нужно в двоичном выбросить?
В стандартном С++ нет двоичного манипулятора.
Из моей книжки (глава 14):
Например, пусть нам требуется выводить целые значения в двоичном виде. Напишем класс binary (листинг 14.13).
Листинг 14.13. «Манипулятор» для двоичного вывода class binary < unsigned long k; public: binary(unsigned long k): k(k) <> friend ostream& operator<<(ostream& os, const binary& t); >; inline ostream& operator<<(ostream& os, const binary& t) < const unsigned long MAX = numeric_limitsunsigned long>::max(); unsigned long bit = ~(MAX >> 1); // старший бит while(bit) < os '1':'0'); bit >>= 1; > return os; >
const unsigned long MAX = numeric_limitsunsigned long>::max(); unsigned long bit = ~(MAX >> 1); // старший бит
В первой строке в переменную MAX заносится максимально возможное беззнаковое целое число, определенное в стандартном классе числовых пределов numeric_limits.
ПРИМЕЧАНИЕ
Класс-шаблон numeric_limits<> определен в заголовоке .
В двоичной записи это максимальное число представляет собой набор единичных битов:
1111. 111
Во второй строке все биты числа сдвигаются вправо на один разряд; самый правый бит (младший разряд числа) теряется; в самый левый бит (старший разряд числа) заносится ноль, так как тип — беззнаковый. Таким образом, в результате сдвига образуется такая конфигурация битов:
0111. 111
Потом эта конфигурация инвертируется операцией ~ и превращается в
1000. 000
Это значение и заносится в переменную bit. Далее старшая единичка в цикле сдвигается на 1 разряд, пока значение bit не станет равно 0.
Такой класс позволяет нам выводить любые целые в двоичном виде, например:
short a = -2; cout
Однако этот класс выводит в выходной поток всегда такое количество битом, которое содержится в типе unsigned long. Мы легко можем преобразовать этот класс в шаблон, который позволит выводить для беззнаковых целых нужное количество битов (листинг 14.14).
Листинг 14.14. Эффектор-шаблон // опережающие объявления template class T> class binary; templateclass T> ostream& operator<<(ostream& os, const binary& t); // класс-шаблон template class T> class binary < T k; public: binary(T k): k(k) <> friend ostream& operator(ostream& os, const binary& t); >; templateclass T> inline ostream& operator<<(ostream& os, const binary& t) < T MAX = numeric_limits::max(); T bit = ~(MAX >> 1); while(bit) < os '1':'0'); bit >>= 1; > return os; >
Обратите внимание на опережающие объявления и прототип функции-шаблона operator Использовать данный класс-шаблон в качестве манипулятора можно так:
short a = -2; cout unsigned short>(a) << endl; cout unsigned char>(128)
В результате на экран выводится следующее:
1111111111111110
10000000
Как видим, на экране ровно столько битов, сколько занимают типы unsigned short и unsigned char. Заметим, что использовать в качестве аргумента шаблона знаковый тип нельзя — программа зациклится!
Хочешь быть счастливым — будь им!
Без булдырабыз.
Re[2]: Как в поток вывести двоичное представление числа?
| От: | Fynjisx | |
| Дата: | 10.10.10 10:05 | |
| Оценка: | -1 | |
Здравствуйте, placement_new, Вы писали:
_>Здравствуйте, Fynjisx, Вы писали:
F>>Привет ВСем! Есть поток, ofstream.
F>>В него вывожу так:
F>>
F>> ofstream ss; F>> . F>> ss > . F>>
F>>видел манипуляторы, которые переводят число в hex, oct формат, а как быть если нужно в двоичном выбросить?
_>Самому написать?
Капитан очевидность?
Заранее благодарю.
С уважением Fynjisx
Re[2]: Как в поток вывести двоичное представление числа?
| От: | Fynjisx |
| Дата: | 10.10.10 10:08 |
| Оценка: |
LVV>Здравствуйте, LaptevVV, Вы писали:
.
LVV>[/q]
О спасибо большое, за очень исчерпывающий ответ. Не ожидал даже. Просто выручили. А не моли бы сказать что это за книжка у Вас?
Ещё раз большое спасибо. (побольше бы таких людей на форумах)
Заранее благодарю.
С уважением Fynjisx
Re[2]: а дай-ка и я напишу
| От: | Pavel Dvorkin |
| Дата: | 10.10.10 16:21 |
| Оценка: |
Здравствуйте, LaptevVV, Вы писали:
Правда, platform-dependent и без классов
void printbin(int x) < __int64 y = x; int i = 32; while(i) < printf("%d", ((y > 32); i--; > printf("\n"); > int _tmain(int argc, _TCHAR* argv[]) < printbin(100); return 0; >
вариант без печати незначащих нулей оставляю желающим в качестве самостоятельного упражнения.
Кстати, на ассемблере можно бы обойтись без __int64. Просто сдвигать и брать флаг С.
With best regards
Pavel Dvorkin
Re[3]: нет, можно проще
| От: | Pavel Dvorkin |
| Дата: | 10.10.10 16:33 |
| Оценка: |
void printbin(int x) < int i = 32; while(i) < printf("%d", (x & 0x80000000) >> 31); i--; x printf("\n"); > int _tmain(int argc, _TCHAR* argv[]) < printbin(100); return 0; >
With best regards
Pavel Dvorkin
Re[3]: Как в поток вывести двоичное представление числа?
| От: | LaptevVV |
| Дата: | 10.10.10 19:19 |
| Оценка: |
Здравствуйте, Fynjisx, Вы писали:
LVV>>Здравствуйте, LaptevVV, Вы писали:
F>.
LVV>>[/q]
F>О спасибо большое, за очень исчерпывающий ответ. Не ожидал даже. Просто выручили. А не моли бы сказать что это за книжка у Вас?
F>Ещё раз большое спасибо. (побольше бы таких людей на форумах)
Первоисточник — в книге Брюса Эккеля. А я несколько модифицировал и в своей книжке написал.
Хочешь быть счастливым — будь им!
Без булдырабыз.
| От: | Ops |
| Дата: | 13.10.10 17:47 |
| Оценка: |
Здравствуйте, Fynjisx, Вы писали:
F>видел манипуляторы, которые переводят число в hex, oct формат, а как быть если нужно в двоичном выбросить?
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[3]: Как в поток вывести двоичное представление числа?
| От: | blackhearted |
| Дата: | 13.10.10 17:58 |
| Оценка: |
Здравствуйте, Fynjisx, Вы писали:
F>Здравствуйте, placement_new, Вы писали:
_>>Здравствуйте, Fynjisx, Вы писали:
F>>>Привет ВСем! Есть поток, ofstream.
F>>>В него вывожу так:
F>>>
F>>> ofstream ss; F>>> . F>>> ss >> . F>>>
F>>>видел манипуляторы, которые переводят число в hex, oct формат, а как быть если нужно в двоичном выбросить?
_>>Самому написать?
F>Капитан очевидность?
Я сегодня за него.
В чём проблема?
Как вывести число в двоичном виде cи
Форумчанин
Регистрация: 18.04.2009
Сообщений: 688
как вывести число в двоичной форме?
как вывести число в двоичной форме?
среда: vc
я прочёл МСДН, но так тока увидел cout cout про двоичную ничё
Форумчанин
Регистрация: 18.04.2009
Сообщений: 688
// TObase64.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include using namespace std; int _tmain(int argc, _TCHAR* argv[]) < short a; a = 6; ~a;//не работает. почему не знаю((((( поскажите плиз coutslength = 8 - slength; for (int i = 0; i
почему-то не работает ~a