C语言经典例75-反转整数

本文详细解析了如何通过编程实现整数的反转操作,利用除余分解数的方法,逐步取出整数的每一位并进行反转,最终输出反转后的整数值。

1 题目

输入一个整数n,并将其反转后输出。

2 分析

反转一个整数可以想象成逆置字符串,只不过在这里是以数的形式,如1234,反转后4321,这里可以采用除余分解数的方法,也就是当n不为0时,将其取余,取出最低位的数字然后再乘10加上这个余数,然后再将n除以10,这样循环结束后,整数n就完成了逆置。

3 实现

#include <stdio.h>

int main() 
{
	int n; // 要反转的数
	int reverse = 0; // 反转后的数,初始为0
	int remainder; // 余数
	printf("请输入整数n:");
	scanf("%d", &n);
	while (n != 0) {
		remainder = n % 10; // 分解出最低位
		reverse = reverse * 10 + remainder; // 将最低位连接起来
		n = n / 10;
	}
	printf("反转后为:%d", reverse);
}

4 运行结果

请输入整数n:12345
反转后为:54321
<think>我们正在回答用户关于C语言实现反转整数的问题 注意:用户要求反转整数如输入123,输出321;输入-123,输出-321;输入120,输出21(去除前导零) 同时,需要考虑整数溢出的问题(反转后可能超出int范围) 思路: 1. 使用循环,每次取原数的最后一位(通过取模10),然后添加到新数的后面(新数乘以10再加上这位) 2. 原数每次去掉最后一位(通过除以10) 3. 注意处理负数:可以先记录符号,然后转为正数处理,最后再还原符号 4. 关键点:在构建新数时,要检查是否溢出。因为int的范围是[-2^31, 2^31-1](32位系统),所以当新数在乘以10和加一位之前,要判断是否可能溢出。 具体步骤: 假设输入为x - 如果x为0,直接返回0。 - 设置一个标志位记录是否为负数,如果是负数则先转为正数(注意:直接转正可能会溢出,但是题目输入是整数,并且反转后溢出也要返回0,所以可以先处理溢出问题,或者用更大的类型?) - 但是题目要求用C语言,且一般要求不使用long类型(如果要求只能使用int,则需要在计算过程中判断溢出) 由于题目没有明确要求,我们可以使用long long来避免中间溢出,但是这样可能不符合某些严格条件(如要求只能用int)。这里我们考虑两种方法。 方法一:使用long long(简单,避免溢出判断复杂) 步骤: long long res = 0; int sign = (x>0)?1:-1; long long x_temp = (long long)x; // 先转换为long long,然后取绝对值 x_temp = (x_temp<0)?-x_temp:x_temp; // 取绝对值 while(x_temp!=0){ res = res*10 + x_temp%10; x_temp /= 10; } // 加上符号 res *= sign; // 检查反转后的数是否在int范围内 if (res > INT_MAX || res < INT_MIN) return 0; else return (int)res; 方法二:完全使用int(需要在每一步判断溢出) 步骤: int res = 0; while(x!=0){ int pop = x%10; // 取最后一位 x /= 10; // 正数溢出判断:如果res > INT_MAX/10 或者 res等于INT_MAX/10且pop>7(因为INT_MAX=2147483647,所以最后一位最多7) // 负数溢出判断:如果res < INT_MIN/10 或者 res等于INT_MIN/10且pop<-8(INT_MIN=-2147483648,最后一位是-8) if (res > INT_MAX/10 || (res == INT_MAX/10 && pop > 7)) return 0; if (res < INT_MIN/10 || (res == INT_MIN/10 && pop < -8)) return 0; res = res*10 + pop; } 但是注意:方法二中,我们每次取余得到的数字,对于负数取余,在C语言中,如果被除数是负数,余数也是负数(或取决于编译器,但标准规定商向0取整,所以余数与被除数同号)。这样我们在循环中处理负数时,每一步的余数都是负数,所以直接加上去就可以。 然而,在方法二中,我们并没有事先将负数转为正数,而是直接处理。这样在循环中x会向0靠近(-123,第一次取余得到-3,然后x变成-12,然后下一次取余得到-2,再下一次-1,最后x变为0)。这样构建的res也是负数。 但是,方法二在处理负数时,需要注意:我们初始的x是负数,那么每一步的pop也是负数。那么判断溢出时,我们使用INT_MIN,并且条件为pop<-8(因为INT_MIN的最后一位是8,但注意我们取余得到的是负数,所以当res==INT_MIN/10且pop=-9,那么就会溢出吗?不,因为INT_MIN=-2147483648,如果我们有一个pop=-9,那么我们需要res*10+pop = -214748364*10-9 = -2147483649,这比INT_MIN(-2147483648)更小,所以溢出。因此条件应该是pop<-8,因为当res等于INT_MIN/10(即-214748364)时,加上一个pop(负数),如果pop<-8,那么就会小于-2147483648,即溢出。 但是,我们也可以将负数转为正数处理,这样只需要判断正数溢出。但是这样有一个问题:负数的最小值(-2147483648)转为正数是2147483648,但int最大值是2147483647,所以这个正数会溢出。因此,为了安全,我们可以在开始把负数用一个long变量转正,或者用方法二直接处理。 这里我们选择方法二,避免使用long类型,完全用int实现。 代码步骤: int reverse(int x) { int rev = 0; while (x != 0) { int pop = x % 10; x /= 10; // 检查是否溢出 if (rev > INT_MAX/10 || (rev == INT_MAX/10 && pop > 7)) return 0; if (rev < INT_MIN/10 || (rev == INT_MIN/10 && pop < -8)) return 0; rev = rev * 10 + pop; } return rev; } 但是,上述代码在x为负数时,pop是负数,所以rev也是负数。在循环过程中,rev会越来越小(负数绝对值变大)。所以我们需要在每一步检查是否会小于INT_MIN。 注意:INT_MAX=2147483647,INT_MIN=-2147483648 测试用: 正数:输入123,输出321 负数:输入-123,输出-321 末尾为0:输入120,输出21 溢出:输入1534236469,反转后为9646324351,大于INT_MAX,返回0 但是,上述代码已经可以处理这些情况。 因此,我们按照方法二编写代码。 注意:由于C语言整数除法是向0取整,所以负数取余会得到负数,这样处理是符合我们逻辑的。 我们编写代码: </think>### C语言实现反转整数的方法 反转整数的核心思路是**逐位提取数字并反向重组**,需要注意处理**负数**、**末尾0**和**整数溢出**问题。以下是完整实现: #### 算法步骤 1. **处理符号**:记录正负号后转为正数处理 2. **反转操作**: - 通过 `% 10` 获取末位数字 - 通过 `/ 10` 移除末位数字 - 反转数 = 反转数 × 10 + 新末位 3. **溢出检测**: - 正数上限:$2^{31}-1 = 2147483647$ - 负数下限:$-2^{31} = -2147483648$ 4. **符号还原**:恢复原始符号 #### 代码实现 ```c #include <limits.h> // 包含INT_MAX和INT_MIN定义 int reverse(int x) { int rev = 0; while (x != 0) { int pop = x % 10; // 获取末位数字 x /= 10; // 移除末位 // 正数溢出检查(rev*10 > INT_MAX/10 或 末位>7) if (rev > INT_MAX/10 || (rev == INT_MAX/10 && pop > 7)) return 0; // 负数溢出检查(rev*10 < INT_MIN/10 或 末位<-8) if (rev < INT_MIN/10 || (rev == INT_MIN/10 && pop < -8)) return 0; rev = rev * 10 + pop; // 反转重组 } return rev; } ``` #### 关键点解析 1. **负数处理**: - C语言的取模运算会保留符号,如 $-123 \% 10 = -3$ - 无需单独处理符号,计算过程自动保留负号 2. **溢出防护**: ```c // 在 rev = rev*10 + pop 前检查: if (rev > INT_MAX/10) return 0; // 超过最大允许值 if (rev < INT_MIN/10) return 0; // 低于最小允许值 ``` 当 `rev` 恰好等于 `INT_MAX/10` 时,需检查新增的 `pop` 是否会导致溢出(正数>7或负数<-8)[^1] 3. **末尾0处理**: - 如输入 `1200`,计算过程: ``` 1200 % 10 = 0 → rev=0 120 % 10 = 0 → rev=0 12 % 10 = 2 → rev=2 1 % 10 = 1 → rev=21 ``` 自动消除前导零 #### 测试用 | 输入 | 输出 | 说明 | |-------------|----------|----------------------| | `123` | `321` | 正常正数 | | `-123` | `-321` | 正常负数 | | `120` | `21` | 末尾0消除 | | `1534236469`| `0` | 反转后溢出返回0 | | `-2147483648` | `0` | 边界值溢出检测 | > ⚠️ **注意事项**:当反转结果超出 `[-2^{31}, 2^{31}-1]` 范围时,函数返回0作为错误标识[^2] --- 相关问题 1. 如何处理反转后浮点数(如123.45→54.321)? 2. 如果不允许使用`%`运算符,如何实现整数反转? 3. 如何扩展此方法反转字符串或链表? 4. 反转整数在密码学中有哪些实际应用? [^1]: 因 `INT_MAX=2147483647`,当 `rev=214748364` 时,若再加 `pop>7` 会导致超过上限值。 [^^2]: 32位整型范围限制为 $[-2147483648, 2147483647]$。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值