如何用算法把一个十进制数转为十六进制数-C语言基础

2023-05-16

在这里插入图片描述
这一篇文章要探讨的是“如何用算法实现十进制转十六进制”并不涉及什么特别的知识点。属于C语言基础篇

在翻找素材的时候,发现一篇以前写的挺有意思的代码,这篇代码里面涉及的知识点没有什么好讲的,也没有什么特别的逻辑概念在里面,仅仅只是想要分享一下个人对于编程方面的一些思考和坚持而已。


先看代码:

#include <stdio.h>
#include <string.h>
int Judge(int n);
int Detection(void);

int main(void)
{
	char x[16] = {'0','1','2','3','4','5','6','7','8',
			'9','a','b','c','d','e','f'};//十进制与十六进制对应的数组

	printf("请输入一个十进制的数:");
	int n = Detection();//输入数据检查再赋值
	int k = Judge(n);//检测数组需要的长度
	char y[k];//创建数组储存十六进制数
	memset(y,'\0',sizeof(y));//清空数组

	int i,j;
	j = 0;
	while( n >= 16 )//把转换好的十六进制数依次输入数组
	{
		i = (n % 16);//先是求余
		y[j] = x[i];//把得到的余数转为十六进制数(例如“11”转“b”)
		j++;//数组下标移位
		n /= 16;//求商再赋值给它自己(方便下个循环再除)
		if(n < 16)
			y[j] = x[n];
	}

	//此时数组y内的十六进制数是倒过来储存的
	
	printf("你输入的数转换成十六进制为:0x");//先输出“0x”前缀
	while(j >= 0)//把储存了十六进制数的数组倒着输出
	{
		if(j > 0)//判断是不是最后一个,是的话换行
			printf("%c", y[j]);
		else
			printf("%c\n",y[j]);
		j--;
	}

	return 0;
}

int Judge(int n)//这个函数的作用是用来判断需要定义的数组大小的
{
	int k = 1;
	int m = n;
	while(m > 16)//如果小于16,那么1位就行了
	{
		m /= 16;//如果大于16先除与16
		k++;//加一位
	}
	return k;
}

int Detection(void)//这个是第一篇博客里面的那个代码的封装版,用来保证输入的数为合法
{
	int n;
	while(1)
	{
		if(scanf("%d", &n) != 1 || getchar() != '\n')
		{
			printf("你输入的数据有误,请再输一遍:");
			while(getchar() != '\n');
		}else
			break;
	}
	return n;
}

这篇代码所要实现的功能很简单,就是把十进制转换为十六进制输出,当然也是有前提的,就是不能用那些转换符(例如%x)或者用一些现有的函数,需要自己写一个算法来实现转换。至于这个算法也不难,无非就是了解一下在数学上面如何把十进制转为十六进制,然后把那个过程用代码来实现罢了,网上已经有很多说明了。十进制转其他进制最常用的办法就是不断对其要求的进制数求余,然后余数反转。

大概类似于这个样子的过程(灵魂画师附体)
在这里插入图片描述


这个过程在算法上面具体体现为先获取用户的十进制输入,然后不断的对其与16进行求商求余,把得到的余数反转输出,即为所要求的十六进制数。在这个过程中,由于需要把余数反转输出,没法每求一个余数就输出一个。所以就需要一个数组来存储这些已经求得的余数,然后再反向输出。在这整个输出的过程中,所涉及算法的难度并不大。但如果仅仅只是这样的话,我也没有必要专门写一篇文章来分享这个代码了。
在这里插入图片描述


我在写这个代码的时候,遇到一个问题,是关于数组的。既然我在输出之前需要把余数用数组储存起来,那么我这个数组需要定义多大呢?由于用户的输入并不确定,所以最终所得到的十六进制数也不确定,这样也就没有办法事先知道我需要的数组大小。定义大了浪费空间,定义小了又不够放。当初在做这道题的时候,老师给我们的建议是定义个“char x[20]”就可以了。

我当时的第一反应就是,老师这是在给我们降低难度啊,这么随便的吗?万一用户输入的数据转换为十六进制之后超过20位呢?且不说浪费不浪费空间的问题,你这明显就是存在着bug啊!怎么也得要给个1024吧,20哪里够了。不过后来想想,如今的操作系统也就64位,转换成十六进制的话,也就16个数就可以表示完了,连20都给多了,四舍五入刚好取整嘛。而且也没有bug的存在,也就浪费了4个字节的内存而已。要是我当时意识到这点,我可能就会直接“char x[16]”完事。也就没有后面的什么事了。

不过在当时的我看了来,这简直就是一个要逼死强迫症的bug啊!我可以容许浪费空间,也可以容许效率低下,但是绝不能放任bug不管啊。所以,我那天苦思冥想,最终认识到,我需要的是一个可变数组。这个数组要能够实现我放多少东西进去它就能存多少东西,我拿多少东西出来它就能缩小多少。为了实现这个需求,我上网找了一下可变数组的实现方法。但是不外乎两种情况,一种是在说C语言中没有可变数组另一种就是在用代码实现可变数组。只可惜我当时的技术水平有限,实在是看不懂那些天书,而且那些大佬的代码一长,就不写注释的了,通篇博客就一整篇代码,一点介绍性的文字都没有,别说我当时没那个技术看不懂啊,我就是现在看的懂也没耐心看你这么一整篇没有注释的代码啊!简直神烦(这也是我想要写博客的一个原因)。


所以我当时在这模凌两可的网络环境下面,我认为是有可变数组的,只是藏着某个函数库里面而已,只是属于深度C而已,只是我还没有学到而已,于是那一整个下午我就都在探索可变数组。

直到后来我才知道,在C语言里面,本身就不存在什么可变数组,在C++中倒是存在可变数组的概念,网络上面的所谓可变数组,不过是利用了指针来存储好原数组的内存位置然后当再次需要改变数组大小的时候,在原位置上面创建或者把原数据拷贝到新的内存地址上面再返回新地址的值给原指针而已。说白了,就是假的,假的。根本就不存在什么可变数组。C语言本身就不支持可变数组这个功能。


直到的最后,当然是没有成功啦,本来就是不存在的东西,不过现在想想用储存原数组地址这个方法来实现可变数组用在我这篇代码中或许也很合适,虽然我用的方法是在数据输入之后先判断一下需要的数组大小,然后再创建数组的方法。不过那也是我当时的权宜之计而已,
在这里插入图片描述


有意思的是当初我在不知道C语言中有没有可变数组的时候,曾想过用“指针对于非法内存的访问”来实现可变数组。具体表现可以看下面的代码

int main(void)
{
	int i = 0;
	char a[i];//根本没有分配空间,用“i”代替0是为了防止编译器报警告
	char *c = a;//用一个指针来存储数组“a”的地址值
	int j = 3;
	a[j] = '7';//这里用“j”来代替3是为了防止编译器报警告

	printf("%c ", c[3]);//这里用“c”来代替“a”输出也是为了防止编译器报警告
	printf("\n");

	return 0;
}

在这段代码里面数组“a”我根本没有分配空间给它,但是我却给它第3个位置“a[3]”赋值,居然编译通过了,运行也没有问题。这就是利用了指针对于非法内存的访问来实现的,而且这样也可以满足我的需求,我这个数组即没有大小限制的而且也丝毫不浪费内存,这不就是我想要的可变数组吗?

但别以为这是什么好东西,恰恰相反在编程开发的时候,我们应该要去杜绝这种情况的发生。这段代码在不同的电脑下面或者在不同的程序区域下面运行都有可能不一样,你可以尝试把它封装成一个独立函数,然后试着在另外一篇小规模的代码上面调用试试看,可能在程序的开始调用它,程序就会报段错误,也有可能会在程序的尾部调用它,程序就报段错误了。也有可能整个程序执行完到退出,也没有报段错误。什么时候报段错误,完全取决于CPU在执行你这个程序的过程中什么时候访问到你正在使用的那块非法内存

你的代码一运行就报错不可怕,最可怕的就是这种随机性报错的,你无法准确定位到你的错误位置。想象一下,你代码原本运行的好好的,你突然想给它来个优化,就好像把原本的int形数据改为char形的节省一下空间,或者改一下别的无关痛痒的细节,改完之后吧,你一编译运行,报错了,你就找啊找啊找啊,就是找不到在哪里有错误。
然后你就很不甘心的把代码又改回去,但是你忽略了一个细节,你原本是先定义一个char类型的数据“a”然后再定义一个int类型的数据“b”的,但是你为了好看,你在优化的时候把它们改成了先定义“b”再定义“a”了。但是你在改回去的过程中觉得不可能是这里的问题啊,就没管了,结果编译运行后,还是报错。
这时候你对着整篇代码从头看到尾,又从尾看到头,你看了好几遍,但就是不知道到底是哪里出了问题,明明跟原来的代码一摸一样啊,怎么就还是报错呢?这时候打死你也不会相信,就是因为你改变了那两个变量的定义顺序了,使得整个程序在内存中的储存结构发生了改变,这就造成了程序在运行的过程中访问到了原本不会访问的内存,而那块内存正是你用的非法内存。

所以当时我在把这个思路运用到代码里面的时候,就出现了很多奇奇怪怪的问题,程序有时候行,有时候不行。有的时候甚至会出现同一个代码在我的电脑上面运行还可以一放到别人的电脑上面就有不行了这种情况,更夸张的是有时候上午运行可以,下午运行又报错了。搞了半天,放弃了。直到后来知道了野指针的概念之后,才渐渐知道为什么会出现那种情况。对于野指针的分析,以后有机会我可能还会单独写一篇文章来说明吧,也可能不会。虽然野指针还是挺重要的一个概念的,不过也挺简单,好像也没什么好写的。


好了,就写到这里吧,确实没有什么知识点好说的,只是单纯的想要分享一下以前的一些有趣的事情而已。而且如果你刚好需要做一道编程题叫做”请用算法编程实现十进制数转XX进制数“的时候,这篇代码刚好可以套用嘛!不过不建议抄作业啦!参考参考就可以了,毕竟真没有什么难度的这题,注释代码里面都写明白了,应该也不会存在看不懂的现象,过些天我会尝试性的把这个例子改为用“储存原数组地址来实现可变数组”的方法来实现,然后再更新上来。

最后附上这个例子的精简版代码:

#include <stdio.h>
#include <string.h>
int Judge(int n);
int Detection(void);

int main(void)
{
	char x[16] = {'0','1','2','3','4','5','6','7','8',
			'9','a','b','c','d','e','f'};//十进制与十六进制对应的数组

	printf("请输入一个十进制的数:");
	int n = Detection();//输入数据检查再赋值
	int k = Judge(n);//检测数组需要的长度
	char y[k];//创建数组储存十六进制数
	memset(y,'\0',sizeof(y));//清空数组

	int i,j;
	for(j=0; n > 0; j++)//把转换好的十六进制数依次输入数组
	{
		i = (n % 16);
		y[j] = x[i];
		n /= 16;
	}

	printf("你输入的数转换成十六进制为:0x");
	while(j >= 0)//把储存了十六进制数的数组倒着输出
		printf("%c", y[--j]);
	printf("\n");
	return 0;
}

int Judge(int n)//这个函数的作用是用来判断需要定义的数组大小的
{
	int k;
	for(k=0; n>0; ++k)
		n /= 16;
	return k;
}

int Detection(void)//这个是第一篇博客里面的那个代码的封装版,用来保证输入的数为合法
{
	int n;
	while(1)
	{
		if(scanf("%d", &n) != 1 || getchar() != '\n')
		{
			printf("你输入的数据有误,请再输一遍:");
			while(getchar() != '\n');
		}else
			break;
	}
	return n;
}

零BUG是原则性问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用算法把一个十进制数转为十六进制数-C语言基础 的相关文章

  • sip register超时和invite超时

    sip的register重传与超时 当发送第一个register时候 xff0c 开启定时器 xff0c 超过500ms没有响应 xff0c 重新发送 在发送的register 1s内没有响应 xff0c 在重发 xff0c 一致到32s的
  • 线性地址转物理地址

    二 线性地址转物理地址 前面说了Linux中逻辑地址等于线性地址 xff0c 那么线性地址怎么对应到物理地址呢 xff1f 这个大家都知道 xff0c 那就是通过分页机制 xff0c 具体的说 xff0c 就是通过页表查找来对应物理地址 准
  • H264/H265 PS 流分析

    对于第一帧的第一个包开始为PS头 43 系统头 43 节目映射流 1 Pack start code xff1a 包起始码字段 xff0c 值为0x000001BA的位串 xff0c 用来标志一个包的开始 2 System clock re
  • linux c/c++ 程序崩溃时打印调用栈

    本文章是在总结前人的帖子后实现的 xff0c 经过验证是可以使用的 但是在个别信号下 xff0c 还是不能详细的打印有效信息 void dump void char szLog MAX LOG LEN 61 0 int j nptrs co
  • sip stale

    ii Stale 一个标志 xff0c 用来指示客户端先前的请求因其nonce值过期而被拒绝 如果stale是TRUE xff08 大小写敏感 xff09 xff0c 客户端可能希望用新的加密回应重新进行请求 xff0c 而不用麻烦用户提供
  • C++中模板类的输入输出流重载函数实现

    转 C 43 43 模板类中操作符重载之 34 lt lt 34 和 34 gt gt 34 重载 2011 01 10 17 05 31 分类 xff1a IT与程序 标签 xff1a 字号 大 中 小 订阅 在模板类中输入流 和输出流
  • SIP注册过程

    SIP的注册过程很容易理解 首先我有一个号码 xff0c 但我的号码可以移动的话 xff0c 那服务器如何才能找到我呢 xff1f SIP的注册机制将sip终端的位置报告给注册服务器 这里的注册服务器仅仅是一个逻辑角色 并不一定是独立的物理
  • linux ls命令 目录下文件太多

    在查看一个文件目录下有哪些文件的时候 xff0c 有时候目录下文件太多 所以需要如下命令筛选 ls less 之后按下ctrl 43 F是下一页 xff0c 按下ctrl 43 B是上一页 xff0c 按下q是回去 有时候文件夹内文件数量太
  • protected 构造方法

    使用protected 构造方法 xff0c 是包保护措施 xff0c 出了这个包 xff0c 在别的包里面是不可以new这个对象的 假设class A 的构造函数是protected的 如果在别的包里还想用我这个类的功能 xff0c 只能
  • 简易小工具实现批量打开多个网页

    最近有个需求 xff0c 希望一次性可以打开多个网页 xff0c 网址自由指定 xff0c 这个需求的实现非常简单 xff0c 使用基本的c 43 43 代码调用system函数即可 xff0c 都不需要MFC相关的东西 但是我实测一些工具
  • STM32硬件复位后无法启动

    最近遇到一个很奇怪的问题 xff0c 把STM32的reset脚拉低后再拉高 xff0c 也就是所谓的硬件复位 xff0c 按道理来说 xff0c STM32应该重启才对 xff0c 可是并没有 xff0c 连main函数都没进去 xff0
  • c++ 除号 /

    在c 43 43 中 xff0c 经常会用到整数的除法 xff0c 但是值得注意的是整数的除法是有数据丢失的 整数除法的余数直接被丢弃 xff0c 只取了商的整数部分 不是四舍五入
  • SIP 鉴权 & HTTP 认证

    sip 鉴权是基于摘要签名认证的 具体来说 每一个用户都有一个用户名和密码 用户名和密码在客户端和SIP 服务器的数据库中都有保存 在认证的过程中 客户端将自己的信息 用户名 密码 url 等信息 做一些复杂的MD5 或者SHA256 SH
  • c++中的extern c以使用

    extern C 是c 43 43 可以正确使用c中代码而产生的 xff0c 虽然c 43 43 兼容c xff0c 但是在c 43 43 程序调用c的库时 xff0c 也会产生链接错误 因为c的库中函数的修饰规则与c 43 43 的函数修
  • 【C++】类与结构体的区别

    C 43 43 中结构体 xff08 struct xff09 我们知道C 43 43 中的 struct 对C中的 struct 进行了扩充 xff0c 它不再是只能用来封装不同类型数据的数据结构了 xff0c 而是拥有了更多的功能 xf
  • C++模板类成员函数最好和模板类声明一起放在同一个.h头文件里

    一个完整的C 43 43 程序应包括三部分 头文件 包含结构声明和使用这些结构的函数原型 头文件常包含的内容如下所示 xff1a 1 xff09 函数原型 2 xff09 使用 define或const定义的符号常量 3 xff09 结构声
  • 【VSCode】Visual Studio Code软件使用入门

    说明 这是一篇VS Code IDE软件使用入门文章 xff0c 工欲善其事 xff0c 必先利其器 xff0c 在使用新IDE之前 xff0c 不妨先对其进行一个全面了解 如果你做WPF等桌面端开发 xff0c 目前VSCode还没有好用
  • Elasticsearch 按字段进行分组 aggs 聚合 分组

    ES 按 userName 字段进行分组 统计 34 query 34 34 bool 34 34 must 34 34 range 34 34 operateTime 34 34 gt 34 34 2020 05 18 00 00 00
  • Hutool 操做excel 导出大数据 到excel

    1 hutool的版本 xff1a hutool all 4 5 15 2 POI 的版本 xff1a 3 17 lt dependency gt lt groupId gt org apache poi lt groupId gt lt
  • 使用vue-router携带不同参数多次push到一个页面时请求 不重新触发问题 ,只有第一次触发

    1 vue跳转 this router push path 39 user userDetils 39 query id JSON stringify val id name JSON stringify this searchData n

随机推荐

  • 惯性导航坐标系介绍

    常用坐标系定义 运载体中三维空间运动包含六个自由度 xff0c 既有角运动也有线运动 在地球表面附近 xff0c 运载体的角运动描述一般以当地水平面和地理北向为参考基准 xff1b 线运动的描述通常采用地理经度 纬度和高度表示 xff0c
  • 达梦 DM管理工具

    DM 管理工具是数据库自带的图形化工具 xff0c 可以方便快捷的对数据进行管理 在网络允许的条件下 xff0c 可通过单个管理工具 xff0c 对多个数据实例进行管理 xff0c 方便简化 DBA 对数据库的日常运维操作要求 打开DM管理
  • Windows 下 DM 的安装 和 数据库配置工具使用说明

    步骤 1 xff1a 运行安装程序 用户将 DM 安装光盘放入光驱中 xff0c 插入光盘后安装程序自动运行或直接双击 setup exe 安装程序后 xff0c 程序将检测当前计算机系统是否已经安装其他版本 DM 如 果存在其他版本 DM
  • window 下 达梦数据库的备份和还原

    DM 提供的各种工具进行备份还原与恢复的操作 xff0c 包括 DIsql工具 DMRMAN 工具 图形化客户端管理工具 MANAGER 和 CONSOLE DIsql 工具用于执 行联机的数据备份与数据还原 xff0c 包括数 归档备份据
  • Linux下与Windows的文件共享

    有三种方法 安装VMware Tools xff08 在虚拟机 gt 重新安装VMware Tools xff09 通过Winscp软件 xff08 前提Windows能ping通linux xff0c 和关防火墙 xff09 本文介绍 x
  • 关于大小端的经典问题

    源代码如下 xff1a span class hljs preprocessor include lt stdio h gt span span class hljs keyword int span main span class hlj
  • 关于#define宏的生命周期

    我们一起来看一段代码 xff1a span class hljs preprocessor include lt stdio h gt span span class hljs preprocessor define X 3 span sp
  • 关于char的溢出问题

    现在看下面的问题 span class hljs keyword int span main span class hljs keyword char span number 61 span class hljs number 129 sp
  • exit()和_exit()的区别

    exit c源代码 xff1a span class hljs preprocessor include span span class hljs preprocessor include span span class hljs keyw
  • ubuntu16.04下u盘的自动挂载(脚本)

    一般固定的u盘在 dev sdxx 的形式 先在 mnt下建一个usb目录用于挂载 1 在 etc udev rules d下创建10 usb rules文件 xff0c 内容如下 xff1a SUBSYSTEM 61 61 34 bloc
  • arp欺骗

    ARP工作的过程 原理及现象 ARP全称是地址解析协议 xff08 address resolution potocol xff09 xff0c 是在仅仅知道主机的IP地址时确定其物理的地址的一种协议 ARP协议的工作过程 场景 xff1a
  • LeetCode中stdout结果是正确的,输出没有

    没有返回值 xff0c 加一行return
  • gstreamer学习(一) gstreamer-rtsp-server环境安装

    gstreamer rtsp server环境安装 Linux环境下 两种方式 xff1a 第一种方式 xff0c 通过官网安装 xff08 如果是Linux环境 xff0c 可以直接通过软件包工具进行安装 xff09 xff0c 点击进入
  • 用C++打开指定网址

    用C 43 43 打开指定网址原理 system 命令 就像这样 xff1a span class token macro property span class token directive hash span span class t
  • 项目遇到的各种异常抛出及解决方法

    项目遇到的各种异常抛出及解决方法 xff1a 1 java lang NumberFormatException xff1a 类型格式异常 第一次遇到的异常抛出原因及解决方法 xff1a 项目运行没有问题 xff0c 各种接口能正常查询出数
  • 【STC8学习笔记】STC8A8K64S4A12精准延时函数设置

    在设置单片机精准的延时函数的时候 xff0c 给大家一个方法 xff0c STC ISP有一个延时函数计算器 xff0c 可以计算出想要的延时 我的例程也是基于这个软件生成的 xff0c 我生成一个1ms和1us出来 xff0c 剩下的我再
  • vc版本与vs版本对应关系

    vc版本与vs版本对应关系 最近在整理之前代码 xff0c 用cmake编译一直报错 xff0c 忘记了opencv3 1 0不支持vs2019 xff0c 所以在这里总结下vc版本与vs版本对应关系 VC版本号 VS对应版本 vc6 VC
  • cmake编译依赖opencv的c++库

    前面一篇主要讲了c 43 43 项目怎么在本地配置opencv过程 xff0c 这种方式缺点就是只能在开发着本地环境编译 xff0c 换台电脑就会出现环境配置问题 接下来主要讲解 xff0c 使用cmake编译 xff0c 生成一个依赖op
  • c++ stl 迭代器iterators(traits编程技法)

    文章目录 1 1 迭代器设计思维 stl关键所在1 2 迭代器是一种smart pointer1 3 迭代器相应型别 xff08 associated types xff09 1 4 traits编程技法 stl源代码门匙1 4 1 val
  • 如何用算法把一个十进制数转为十六进制数-C语言基础

    这一篇文章要探讨的是 如何用算法实现十进制转十六进制 并不涉及什么特别的知识点 属于C语言基础篇 在翻找素材的时候 xff0c 发现一篇以前写的挺有意思的代码 xff0c 这篇代码里面涉及的知识点没有什么好讲的 xff0c 也没有什么特别的