C语言实现十六进制与二进制的相互转换

 更新时间:2022年11月10日 16:01:07   作者:_苏沐  
这篇文章主要为大家详细介绍了如何利用c语言实现将文件中十六进制数据与二进制数据相互转换,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的可以学习一下

本文中的代码可以将文件中的十六进制存储与二进制存储相互转换。

十六进制->二进制

原理是:每两位存储为一个字符(char)保存。

因为十六进制数最大为 f,即 15,在内存中只需要 4 位就可以表示。而一般情况下一个字符是占一个字节 8 位,所以正好可以存储十六进制两位。

举个栗子:

在文件中存储十六进制为ab,ab转换为二进制,就是1010 1011,刚好八位,可以联想到ASCII码,用一个字符可以表示。

注意转为二进制后,前32个为不可见字符,附图ASCII码。

(将十六进制转为二进制还会压缩一倍的空间?因为ab本来占两个字节,现在转成二进制,即一个char字符,只占用一个字节大小。但是转换过程中时间消耗,我不太确定是否优化了)

#include <stdio.h>

int main() {

    FILE * in  = fopen("./data.txt", "r");
    FILE * out  = fopen("./data", "w");

    while (1) {
        char c;
        unsigned char d = 0;

        for (int i = 0; i < 2; ++i) {
            // 从 in 读取 1 个大小为 1 字节数据保存在 c
            if (fread(&c, 1, 1, in) == 0) {
                fclose(in);
                fclose(out);
                return 0;
            }
        	// 读到空格或者换行索引需要回退
            if (c == ' ' || c == '\n') {
                i--;
                continue;
            }
            // 将读到的十六进制字符转成具体的十进制数字
            if (c >= '0' && c <= '9') {
                c -= '0';
            } else if (c >= 'a' && c <= 'f') {
                c -= 'a';
                c += 10;
            } else {
                printf("error");
            }
            //printf("c -> %d  \n", c);
            d <<= 4;
            d |= c;
        }
        //printf("-------> %c\n", d);
        fwrite(&d, 1, 1, out);
    }

    return 0;

}

核心代码:

d <<= 4 and d |= c

解释:

内层for循环为两次,c读取两次:

我们假设第一次读到a字符,第二次读到b字符。

(或运算:参加运算的两个对象只要有一个为1,其值为1)

操作
第一次循环开始 :d (0000 0000) c(0000 1010)
d <<= 4 :d (0000 0000)     c(0000 1010)
d |= c :d (0000 1010) c(0000 1010)
第二次循环开始:d (0000 1010) c(0000 1011)
d <<= 4 : d (1010 0000)     c(0000 1011)
d |= c : d (1010 1011) c(0000 1011)
两次循环结束 将d写入文件,转换完成。 

如果想知道转换是否正确的话,可以用 hexdump -C + 文件名(data) 检查一下是否正确。(linux命令)

二进制->十六进制

这个就是上边操作相反的过程,读取二进制文件,然后转成十六进制字符保存。

#include <stdio.h>

int main() {

    FILE * in  = fopen("./data.txt", "r");
    FILE * out  = fopen("./data", "w");

    char space = ' ';
    char enter = '\n';

    int idx = 0;
    while (1) {
        char c[2];
        unsigned char d = 0;

        for (int i = 0; i < 4; ++i) {
            // 读取一个字节
            if (fread(&d, 1, 1, in) == 0) {
                fclose(in);
                fclose(out);
                return 0;
            }

            // 一个二进制字节转回两个十六进制字符
            char mask = 0xf;
            c[0] = d >> 4;      // 将低位移走就是该字节保存的第一个十六进制字符
            c[1] = d & mask;    // 保留 d 的低位就是该字节保存的第二个十六进制字符

            // 将十进制数字转回对应的十六进制字符(与上一步转换的代码相反)
            if (c[0] >= 0 && c[0] <= 9) {
                c[0] += '0';
            } else {
                c[0] -= 10;
                c[0] += 'a';
            }
            if (c[1] >= 0 && c[1] <= 9) {
                c[1] += '0';
            } else {
                c[1] -= 10;
                c[1] += 'a';
            }

            // 从 c 地址开始读取两个字节,写到 out 
            fwrite(&c, 1, 2, out);
        }
        // 写空格或者换行 保持格式
        idx++;
        if (idx == 4){
            idx = 0;
            fwrite(&enter, 1, 1, out);
        } else {
            fwrite(&space, 1, 1, out);
        }
    }
    return 0;

}

mask的二进制是0000 1111。

到此这篇关于C语言实现十六进制与二进制的相互转换的文章就介绍到这了,更多相关C语言 十六进制二进制互转内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • c++实现获取当前时间(精确至秒,毫秒和微妙)

    c++实现获取当前时间(精确至秒,毫秒和微妙)

    这篇文章主要为大家详细介绍了c++实现获取当前时间(可以精确至秒,毫秒和微妙)的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下
    2023-11-11
  • C++之WSAAsyncSelect模型实例

    C++之WSAAsyncSelect模型实例

    这篇文章主要介绍了C++的WSAAsyncSelect模型,实例讲述了socket与Windows消息机制的用法,需要的朋友可以参考下
    2014-10-10
  • C语言实现超市计价收款系统

    C语言实现超市计价收款系统

    这篇文章主要为大家详细介绍了C语言实现超市计价收款系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++中命名空间的概念及使用详解

    C++中命名空间的概念及使用详解

    这篇文章主要介绍了C++中命名空间的概念及使用详解,使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字就是针对这种问题而出现的,需要的朋友可以参考下
    2023-08-08
  • C/C++连接MySQL数据库详细图文教程

    C/C++连接MySQL数据库详细图文教程

    在实际开发中我们经常需要对数据库进行访问,下面这篇文章主要介绍了C/C++连接MySQL数据库的详细图文教程,文中通过代码以及图文介绍是非常详细,需要的朋友可以参考下
    2024-01-01
  • 利用C语言替换文件中某一行的方法

    利用C语言替换文件中某一行的方法

    大家都知道C语言提供了文件操作,但是替换文件的某一行比较麻烦,下面是我使用的一个方法,现在分享给大家,有需要的朋友们可以参考借鉴。
    2016-09-09
  • vs2019配置Qt5开发环境(图文教程)

    vs2019配置Qt5开发环境(图文教程)

    本文主要介绍了如何使用visual studi2019配置qt5开发环境,以及创建qt项目,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • Qt私有信号实现(private signal)

    Qt私有信号实现(private signal)

    在使用Qt信号槽机制的时候,有时候我们需要一个信号只能由类内发出,而不允许使用该类对象的用户发出,此时就需要私有信号的支持,本文主要介绍了Qt私有信号实现(private signal),感兴趣的可以了解一下
    2023-10-10
  • 详解C++ STL模拟实现vector

    详解C++ STL模拟实现vector

    这篇文章主要为大家详细介绍了C++如何模拟实现STL容器vector,文中的示例代码讲解详细,对我们学习C++有一定帮助,需要的可以参考一下
    2023-01-01
  • C++实现AVL树的基本操作指南

    C++实现AVL树的基本操作指南

    AVL树是高度平衡的而二叉树,它的特点是AVL树中任何节点的两个子树的高度最大差别为1,下面这篇文章主要给大家介绍了关于C++实现AVL树的相关资料,需要的朋友可以参考下
    2022-01-01

最新评论