Как читать и печатать шестнадцатеричные числа из файла на C
Я пытаюсь прочитать из файла 14-значные шестнадцатеричные числа, а затем распечатать их. Моя идея — использовать long long int и читать строки из файлов с помощью fscanf, как если бы они были строками, а затем преобразовывать строку в шестнадцатеричное число с помощью atoll. Проблема в том, что я получаю значение сегмента в моей строке fscanf согласно valgrind, и я абсолютно не знаю, почему. Вот код:
3 ответа
Эта переменная line не инициализирована, поэтому, когда fscanf() разыменовывает ее, вы получаете неопределенное поведение.
Вы должны использовать:
Если вы используете C99, вы можете использовать uint64_t для хранения числа, поскольку это дает понять, что подойдут 14-значные шестнадцатеричные числа (4 * 14 = 56).
Вы уверены, что хотите читать свои числа как символьные строки? Почему бы не позволить scanf делать работу за вас?
Кстати, обратите внимание на спецификатор размера ll для преобразования %x в printf — он определяет, что целочисленное значение будет иметь тип long long .
Изменить
Вот простой пример двух циклов чтения трехстрочного ввода (с двумя, нет и тремя числами в последовательных строках) в формате ‘hex int’ и в формате ‘string’:
http://ideone.com/ntzKEi
Вызов rewind позволяет второму циклу читать те же входные данные.
Другие ответы хороши, но я хочу прояснить реальную причину сбоя, который вы видите. Проблема в том, что:
. по сути означает «прочитать строку из файла и сохранить ее в буфере, на который указывает line ». В этом случае ваша переменная line не была инициализирована, поэтому она никуда не указывает. Технически это неопределенное поведение; на практике результатом часто будет запись поверх произвольного места в адресном пространстве вашего процесса; кроме того, поскольку он часто указывает на незаконный адрес, операционная система может обнаружить и сообщить об этом как о нарушении сегмента или подобном, что вы действительно видите.
Обратите внимание, что fscanf с преобразованием %s не обязательно будет читать всю строку — он читает строку, разделенную пробелами. Он может пропускать строки, если они пусты, и может читать несколько строк из одной строки. Это может не иметь значения, если вы знаете точный формат входного файла (например, он всегда имеет одно значение на строку).
Хотя в этом случае кажется, что вы, вероятно, можете просто использовать соответствующий модификатор для чтения шестнадцатеричного числа ( fscanf(fp, «%llx», &num) ), а не читать строку и пытаться выполнить преобразование, существуют различные ситуации, когда вам действительно нужно прочитать струны и особенно целые строки. Существуют различные решения этой проблемы в зависимости от того, на какой платформе вы работаете. Если это система GNU (обычно включая Linux) и вас не волнует переносимость, вы можете использовать модификатор m и изменить line на &line :
Это передает указатель на line на fscanf , а не на его значение (которое не инициализировано), и m заставляет fscanf выделить буфер и сохранить его адрес в <
Если вы не используете систему GNU или заботитесь о переносимости, используйте fgets вместо fscanf — это более прямо и позволяет вам ограничить длину считываемой строки, что означает, что вы выиграли » t переполнить фиксированный буфер — просто имейте в виду, что он будет читать всю строку за раз, в отличие от fscanf , как обсуждалось выше. Вы должны объявить line как char — массив, а не как char * , и выбрать для него подходящий размер. (Обратите внимание, что вы также можете указать «максимальную ширину поля» для fscanf , например fscanf(fp, «%1000s», line) , но вы также можете использовать fgets ).
Преобразование десятичного числа в шестнадцатеричное
Задача 2.26
Дано натуральное число X в десятичной системе счисления. Перевести его в шестнадцатеричную систему счисления. Результат вывести на экран.
Программистам приходится довольно часто это делать. Поэтому почти во всех языках программирования имеются стандартные подпрограммы для преобразования различных форматов записи чисел. В Паскале для этого есть множество функций (одну из них вы увидите ниже), а в С++ можно использовать манипуляторы и флаги форматирования (подробнее об этом в моей книге Основы С++).
Однако использование стандартных средств — это было бы слишком просто. Поэтому мы создадим собственную функцию для перевода десятичного числа в шестнадцатеричное.
Кстати, если вы подзабыли, что такое натуральное число, то читайте здесь.
Запись шестнадцатеричных чисел в Паскале и С++
На всякий случай напомню (хотя для решения нашей задачи это и не обязательно), что в исходных текстах на Паскале шестнадцатеричное число записывается так:
то есть перед цифрами числа ставится знак доллара, а затем записывается число в шестнадцатеричной системе.
В Си и С++ это делается так:
то есть перед числом ставится 0х, а затем записываются цифры числа.
Разумеется, цифр в числе может быть не обязательно четыре, как в примерах.
Функция преобразования числа в шестнадцатеричное
В Паскале есть стандартная функция для преобразования десятичных чисел в шестнадцатеричные: IntToHex. Эта функция объявлена в модуле SysUtils, и её мы будем использовать для проверки работы нашей собственной функции, которую я назову MyIntToHex, и которая будет работать примерно также, как и стандартная функция IntToHex.
Кроме того, чтобы упростить код основной функции, я использую вспомогательную функцию DigitToHex, которая будет переводить одну десятичную цифру в шестнадцатеричную.
Решение будет, быть может, не самым простым. Но зато мы постараемся использовать как можно меньше стандартных функций. Коды функций отдельно приводить не буду — см. их в примерах программ.
Также не забываем, что по условию задачи нам требуется выполнить преобразование только для натуральных чисел. Отрицательные числа не являются натуральными, поэтому наша функция с ними не работает (хотя если убрать в теле функции проверку числа, то будет работать также как и стандартная функция IntToHex).
Программирование на C, C# и Java
Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы
ОСТОРОЖНО МОШЕННИКИ! В последнее время в социальных сетях участились случаи предложения помощи в написании программ от лиц, прикрывающихся сайтом vscode.ru. Мы никогда не пишем первыми и не размещаем никакие материалы в посторонних группах ВК. Для связи с нами используйте исключительно эти контакты: vscoderu@yandex.ru, https://vk.com/vscode
Шестнадцатеричная система счисления
Системы счисления – одна из самых главных основ информатики. Практически ни в одной школе и ни в одном университете не пропускают данную тему, но зачастую именно с переводом шестнадцатеричной системы у многих возникают проблемы, хотя это не такая уж сложная задача, и её перевод практически не отличается от других систем счисления.
Давайте рассмотрим эту систему поподробнее.
Для чего нужна шестнадцатеричная система
Итак, шестнадцатеричная система счисления, как следует из названия, имеет в своём основании число 16. Почему так? Дело в том, что единица информации в информатике – это бит. Восемь бит образуют байт. Также информационной среде существует такое понятие, как машинное слово – это минимальная единица данных, представляющая собой шестнадцать бит, то есть два байта. Считается, что машинное слово – это минимальная величина разрядности регистров процессора, при которой можно работать с ЭВМ.
Так вот, как мы знаем, компьютер работает на двоичном коде. Однако, если Вы когда-нибудь переводили числа из двоичной системы в десятичную, то замечали, что в ней бывает довольно много разрядов, особенно при переводе больших чисел, например, перевод числа 5132 в двоичной системе будет записано так:

Как можно увидеть, при переводе в двоичную систему этого числа у нас получилось аж 13 разрядов (с 0 до 12). Довольно муторно, а главное, занимает много места на письме и отнимает много времени для перевода.
Именно для этого придумали восьмеричную и шестнадцатеричную системы счисления, для этого придумали и байты. Эти системы помогают сократить затраты на перевод чисел и привести их к более приятному визуальному виду.
Если перевести то же число 5132 в восьмеричную систему счисления, то получится «более сокращённая версия» двоичного кода:

Как мы видим, количество символов сократилось, так как разрядность уменьшилась до 5 (с 0 до 4).
Как можно уже понять, шестнадцатеричная система ещё сильнее сокращает разрядность (с 0 до 3) и ещё сильнее сжимает на письме переведённое число:

Человеку такой вид записи в любом случае удобнее, чем бесконечные нули и единицы.
Таким образом, шестнадцатеричная система используется довольно широко в современных информационных системах. Например, при помощи неё указываются коды цветовых схем, данная система используется для записи кодов ошибок, а также для программирования на языках низкого уровня типа Ассемблера, шестнадцатеричную систему зачастую используют для предоставления данных и адресов в малоразрядных ЭВМ.
Как перевести из десятичной системы в шестнадцатеричную
Выше мы уже немного затронули процесс перевода чисел. Теперь мы рассмотрим его подробнее и на примерах.
Но прежде чем начать, надо узнать одну очень важную особенность шестнадцатеричной системы.
Так как система имеет своим основанием число 16, то, следовательно, всего в этой системе имеется 16 цифр, но если первые десять цифр (0-9) вполне привычные для нас, то остальные имеют вид не совсем цифровой, но, тем не менее, являются цифрами, а именно значения A, B, C, D, E, F, которые соответствуют нашим привычным числам с 10 до 15. Все цифры шестнадцатеричной системы и их «аналоги» в десятичной записаны в таблице ниже.

Итак, допустим, у нас есть число 40 563 в десятичной системе счисления. Переведём его в шестнадцатеричную.
- Сначала мы просто делим наше исходное число 40 563 на 16 в столбик. В частном у нас получилось 2 535, если умножить это число на 16, то получится 40 560, а в остатке 3. Эту тройку мы выделяем.

- Теперь мы делим 2 535, и тоже на 16, и тоже абсолютно таким же образом. Частное – 158, 16*158 = 2 528, а в остатке 7. Остаток так же, как и в тот раз, выделяем.

- Делим полученные частные до тех пор, пока они не станут меньше 16 , тогда деление заканчивается. Делим 158 на 16, и находим остаток от этого деления.

Остаток от деления – 14, а частное, полученное при делении 158 на 16 равно 9. Так как 9 меньше 16, то процесс вычислений закончен, а 9 также выделяется.
- Процесс преобразования десятичного числа в шестнадцатеричное почти окончен. Для того, чтобы получить его, надо всего лишь выписать выделенные числа справа налево (т.е. в данном случае от девятки к тройке), НО, как мы писали выше, у шестнадцатеричной системы свой особый «алфавит» с 10 по 15. И как раз один из наших «остатков» (число 14) вписывается в этот диапазон, поэтому надо посмотреть в таблице, либо просто самостоятельно посчитать, что в шестнадцатеричной системе 14 будет буквой Е.
Итого весь процесс преобразования приведён на следующем изображении:

Таким образом мы научились переводить числа из десятичной системы в шестнадцатеричную. Теперь давайте попробуем сделать обратное преобразование, но уже с другим числом.
Как перевести из шестнадцатеричной системы в десятичную
Перевести шестнадцатеричное число в привычное нам десятичное также совсем не сложно, более того, мы уже делали это в самом начале статьи, когда сравнивали двоичную, восьмеричную и шестнадцатеричную системы счислений, теперь же разберём этот процесс более подробно.
Давайте сразу приступим к примеру и переведём шестнадцатеричное число 1C3B3 в десятичную систему.
По сути, процесс перевода можно разделить на 2 этапа:
- Мы справа налево отделяем от числа все цифры и умножаем каждую из них на 16, и всё это складываем:

Также обязательно необходимо перевести буквенные обозначения шестнадцатеричной системы в числовые, чтобы можно было посчитать их в десятичном виде, то есть, для данного случая, перевести B в 11 и C в 12.
- После того, как мы сделали этот шаг, нам необходимо пронумеровать разряды чисел. Делается это просто – мы приписываем ко всем числам 16, на которые мы умножали наши исходные цифры, степени, начиная с нулевой:

Теперь нам остаётся только перемножить и сложить всё это:

Таким образом, мы превратили шестнадцатеричное число 1C3B3 в десятичное число 115 635.
Как видите, ничего сложного. Также у нас на сайте имеется статья, описывающая процесс перевода чисел из шестнадцатеричной системы в двоичную.
Спасибо за прочтение!