蓝桥杯基础-016-Hexadecimal_To_Octal

本文介绍了一种从16进制字符串转换为8进制字符串的算法实现,通过查找表进行二进制辅助转换,并去除前导零。该方法适用于大范围的数值转换,避免了使用受限的整数类型。

题意

输入 n (行)

输入 n 个 16进制字符串  && 1 <= hex_chs.lehgth <= 10000 -> 16^(10000 - 1) -近似> 16^10000 -> 2^40000 >> 2^31(int) or 2^63(long) -> 中间数不能用整型->char[ ] 

分别每行输出 1 个 8进制字符串 

(结合16进制 = 4 bits , 8进制 = 3 bits -> 中间数取binary_chs)

代码

import java.awt.AlphaComposite;
import java.util.Scanner;

public class Main {

	static char[] HexAlphabet = {'0','1','2','3','4',
				     '5','6','7','8','9',
				     'A','B','C','D','E','F'
								 };
	static String[] HexBin = {  "0000","0001","0010","0011",
				    "0100","0101","0110","0111",
				    "1000","1001","1010","1011",
				    "1100","1101","1110","1111",
							};
	static char[][] OctBin = {  {'0','0','0'},{'0','0','1'},{'0','1','0'},{'0','1','1'},
				    {'1','0','0'},{'1','0','1'},{'1','1','0'},{'1','1','1'},
							};
	public static void main(String[] args) {

		
		Scanner keyin = new Scanner(System.in);
		int n = keyin.nextInt();
		while (n-- > 0) {
			String hex_str = keyin.next();
			char[] hex_chs = hex_str.toCharArray();
			char[] bin_chs = hexChsToBinaryChs(hex_chs);
			char[] oct_chs = binChsToOctalChs(bin_chs);
			System.out.println(String.valueOf(oct_chs));
		}
	}
	public static int chsSearch(char[] target){
		for (int i = 0; i < OctBin.length; i++) {
			int j;
			for (j = 0; j < target.length; j++) {
				if( OctBin[i][j] != target[j] )
					break;
			}
			if(j == target.length)
				return i;
		}
		return -1;
	}
	public static char[] binChsToOctalChs(char[] bin_chs){
		if( bin_chs.length % 3 >= 1){
			bin_chs = ("0"+String.valueOf(bin_chs)).toCharArray();
			if( bin_chs.length % 3 == 2){
				bin_chs = ("0"+String.valueOf(bin_chs)).toCharArray();
			}
		}
		char[] oct_chs = new char[bin_chs.length/3];
		for (int i = bin_chs.length - 3; i >= 0 ; i -= 3) {
			char[] oct_section = { bin_chs[i],bin_chs[i+1],bin_chs[i+2] };
			int sub_oct_digit = chsSearch(oct_section);
			oct_chs[i/3] = HexAlphabet[sub_oct_digit];
		}
		int cnt_head_zero = 0;
		while(oct_chs[cnt_head_zero] == '0'){
			cnt_head_zero++;
		} 
		char[] erase_head_zero_oct_chs = new char[ oct_chs.length - cnt_head_zero];
		for (int i = 0; i < erase_head_zero_oct_chs.length; i++) {
			erase_head_zero_oct_chs[i] = oct_chs[i + cnt_head_zero];
		}
		return erase_head_zero_oct_chs;
	}
	public static char[] hexChsToBinaryChs(char[] hex_chs){
		char[] bin_chs = new char[hex_chs.length*4];
		for (int i = bin_chs.length - 4; i >= 0; i -= 4) {
			int sub_hex = binSearch(HexAlphabet, hex_chs[i/4]);
			System.arraycopy(HexBin[sub_hex].toCharArray(), 0,bin_chs, i , 4);
		}
		return bin_chs;
	}

	public static int binSearch(char[] src,char target){
		int low = 0,high = src.length - 1,mid = 0;
		do {
			mid = (low + high)/2;
			if(target == src[mid]) 
				return mid;
			else if(target > src[mid])
				low = mid + 1;
			else
				high = mid - 1;
		} while (low <= high);
		return -1;
	}
}


Summary

【两转两Search后去Zero】

i)两Search两转 -> binSearch

  hex_chs + 构造HexAlphabet对照表( HexAlphabet和OctalAlphabet部分可以通用) +HexBin -> 用于 hexChsToBinaryChs 

  bin_chs  + HexAlphabet + HexBin -> 用于 binChsToOctalChs

ii) 去Zero

 在binChsToOctalCh中,将bin_chs -> oct_chs 后

iii)输出 ->sysout { String.valueOf(octal_chs) }

<think>嗯,用户问的是关于 add_definitions(-D__STDC_FORMAT_MACROS) 这个命令的作用。我需要先回忆一下CMake中的add_definitions函数是用来干嘛的。对了,这个命令是用来添加编译器定义的,也就是在编译时传递-D选项。 那-D__STDC_FORMAT_MACROS具体是做什么的呢?我记得这个宏和C99标准中的格式化输出有关,特别是inttypes.h里的宏,比如PRIu64这种。在C99之前或者某些旧版的编译器里,可能需要定义这个宏才能使用这些格式宏,否则可能会报错或者找不到定义。 用户可能是在编译过程中遇到了相关的问题,比如使用了%PRIu64这样的格式字符串,但编译器提示找不到定义。这时候就需要在编译时定义这个宏,让头文件展开这些格式宏。所以使用add_definitions来添加这个定义,确保代码能够正确编译。 另外,我需要确认不同编译器下的兼容性。比如GCC和Clang可能默认支持C99,但有些旧版本可能需要显式开启C99模式,或者需要定义这个宏。而MSVC可能情况不同,可能需要其他处理方式。这时候可能需要根据不同的编译器做条件判断,或者建议用户使用更现代的标准,比如C11,可能会有更好的兼容性。 还有用户可能的深层需求是解决编译错误,所以除了给出这个命令的解释,还应该提供使用示例,以及可能的替代方案,比如使用target_compile_definitions来更精准地为目标添加定义,或者设置CMAKE_C_STANDARD来指定C标准版本,避免手动定义宏的必要。 还需要提醒用户,如果项目同时包含C和C++代码,可能需要分别在CXX_FLAGS和C_FLAGS中添加,或者使用更细粒度的CMake命令。此外,检查inttypes.h是否被正确包含,以及是否有其他相关的宏需要定义,比如__STDC_CONSTANT_MACROS等。 总结下来,回答应该包括这个命令的作用、为什么需要它、使用场景、示例代码、替代方案以及注意事项。确保用户不仅知道怎么用,还能理解背后的原因,并根据自身情况调整配置。</think>以下是关于`add_definitions(-D__STDC_FORMAT_MACROS)`的完整解释: --- ### 一、命令作用 `add_definitions(-D__STDC_FORMAT_MACROS)`是CMake中用于向编译器传递预处理器定义的指令,具体功能: 1. 定义`__STDC_FORMAT_MACROS`宏 2. 激活C99标准中的**格式化输出宏**(如`PRIu64`) 3. 使`inttypes.h`头文件中的跨平台格式化字符串可用 --- ### 二、为什么需要这个定义? 在C/C++开发中会遇到以下场景: 1. 当使用`uint64_t`等固定宽度整数类型时 2. 需要跨平台格式化输出(如:`printf("%" PRIu64, value)`) 3. 某些旧编译器(如GCC 4.x)默认不暴露这些宏 **未定义时的典型错误**: ```cpp error: expected ')' before 'PRIu64' printf("value=%" PRIu64 "\n", value); ``` --- ### 三、使用场景示例 #### 1. C代码中需要格式化输出64位整数 ```cpp #include <inttypes.h> int main() { uint64_t num = 123456789; printf("Decimal: %" PRIu64 "\n", num); // 需要PRIu64宏定义 printf("Hexadecimal: %" PRIx64 "\n", num); return 0; } ``` #### 2. CMakeLists.txt配置 ```cmake # 最低CMake版本要求 cmake_minimum_required(VERSION 3.10) project(example) # 添加全局定义 add_definitions(-D__STDC_FORMAT_MACROS) # ← 核心配置 add_executable(main main.c) ``` --- ### 四、现代替代方案(推荐) #### 1. 设置C标准版本(CMake 3.1+) ```cmake set(CMAKE_C_STANDARD 99) # 自动包含相关宏定义 set(CMAKE_CXX_STANDARD 11) ``` #### 2. 针对特定目标设置 ```cmake target_compile_definitions(my_target PRIVATE __STDC_FORMAT_MACROS ) ``` --- ### 五、平台差异说明 | 编译器 | 是否需要定义 | 说明 | |------------|-------------|--------------------------| | GCC ≥5 | 否 | 默认支持C99 | | Clang | 否 | 通常默认开启 | | MSVC | 无效 | 需用`%llu`代替 | | 嵌入式编译器 | 可能需要 | 检查具体工具链文档 | --- ### 六、相关宏扩展 如果需要完整支持C99类型,可能需要同时定义: ```cmake add_definitions( -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS ) ``` --- ### 七、验证是否生效 在代码中添加验证代码: ```cpp #ifdef __STDC_FORMAT_MACROS printf("Macros enabled\n"); #else #error "Format macros not enabled!" #endif ``` --- ### 八、最佳实践建议 1. 优先使用`target_compile_definitions()`替代全局`add_definitions()` 2. 新项目建议直接设置`CMAKE_C_STANDARD=11`或更高 3. 跨平台项目建议配合**configure检查**: ```cmake check_symbol_exists(PRIu64 "inttypes.h" HAVE_INTTYPES_MACROS) ``` --- 该定义主要解决历史遗留兼容性问题,现代编译环境通常不需要手动定义,但理解其原理对处理旧代码库仍非常重要。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值