回文数|逻辑非” 运算符|函数封装
回文数Palindrome number
这绝对是我目前写过最久的程序!
题目:
回文数的形成。任取一个十进制整数,将其倒过来后与原来的整数相加,得到一个新的整数后,重复以上步骤,最终可得到一个回文数,请编程验证。
**输入格式要求:”%ld” 提示信息:”please enter a number optionaly:” “The generation process of palindrome:\n” “ input error, break.\n”
**输出格式要求:” [%d]: %ld+%ld=%ld\n” “Here we reached the aim at last !\n”
程序运行示例如下:
please enter a number optionaly:345
The generation process of palindrome:
Here we reached the aim at last !
代码实现:
1 | |
中途遇到的问题:
%ld是什么? 全称是 “long decimal”,用于**整数类型
long**(长整型)的输入输出。int和long有什么区别?**
int**:通常占 4 字节(32 位),可表示的范围约为 -21 亿~+21 亿(-2³¹ ~ 2³¹-1)。
例如:
int最大能精确存储 2147483647,超过这个数就会 “溢出”(结果错误)。**
long**:至少占 4 字节(32 位系统),64 位系统中通常占 8 字节,可表示的范围约为 -922 亿亿~+922 亿亿(-2⁶³ ~ 2⁶³-1)。
例如:8 字节的
long能轻松存储像 123456789012345 这样的大整数,而int会溢出。内存占用不同
int:固定 4 字节(几乎所有系统)。long:32 位系统中 4 字节,64 位系统中 8 字节(目的是利用更大的内存空间扩展表示范围)。什么时候用
int?什么时候用long? 用
int:处理普通大小的整数(比如年龄、数量、10 亿以内的数),更节省内存,效率略高。 用
long:处理超过int范围的大整数(比如身份证号、天文数字、大金额),避免溢出错误。1
2
3
4
5
6
7
8
9
10
11#include <stdio.h>
int main() {
int a = 2147483647; // int 的最大值
long b = 2147483648; // 超过 int 范围,必须用 long
printf("int 最大值+1: %d\n", a + 1); // 溢出,结果错误(变成-2147483648)
printf("long 存储大整数: %ld\n", b); // 正确输出 2147483648
return 0;
}简单说:
int是 “普通整数”,long是 “大整数”,根据需要存储的数值大小选择即可。
最后写的我头皮发麻,浑身燥热,饥渴难耐…….不过还好,自己还是把这个几把代码写出来了
看看AI是怎么写的把!
AI的代码:
1 | |
解读:
- 将反转数字和判断回文数封装到两个函数中,使代码可读性强
- 封装到两个独立函数,避免循环嵌套的时候出现变量需不断重新归零,或避免在主函数中定义过多变量,降低大妈可读性
看看是怎么实现的把:
反转数字:
1 | |
这个里面的的reversed不是在主函数中已经定义了吗,还需要定义?
在 C 语言中,变量的作用域(即变量能被访问的范围)是由定义它的位置决定的。
reversed变量在 主函数(main) 和reverse_num函数 中是完全独立的两个变量,原因如下:- 变量的 “作用域” 不同
- 在
reverse_num函数中定义的long reversed = 0;,其作用域 仅限于reverse_num函数内部。离开这个函数后,这个变量就不存在了,其他函数(包括main函数)无法直接访问它。 - 主函数(
main)中如果定义了reversed变量(比如你可能在main里写了long reversed;),它的作用域 仅限于main函数内部。reverse_num函数无法访问main中的这个变量。
- 为什么需要在
reverse_num中重新定义?
reverse_num函数的功能是 “计算一个数字的反转数”,这个过程需要一个临时变量来存储反转后的结果(比如从 0 开始,逐步拼接原数字的每一位)。这个临时变量只在函数内部使用,和main函数中可能存在的reversed变量没有任何关系。
即使两个变量名字相同,由于作用域不同,它们会被编译器视为 两个完全独立的变量(可以理解为 “同名不同人”),各自占用不同的内存空间,互不影响。
num /= 10是什么意思?num /= 10等价于num = num / 10reversed = reversed * 10 + num % 10中将”取最后一位数字”整合到递推中,使代码更简洁函数独立封装的好处
- 避免循环嵌套,导致reverse_num在上一次循环中的值,运用在了下一次循环
reversed = reversed * 10 + num % 10的第二个reverse中(每一次循环reverse的初始值都要为0),当然实现方法就是在每一个循环的开头重新定义reverse的初始值‘0’
- 避免循环嵌套,导致reverse_num在上一次循环中的值,运用在了下一次循环
判断是否为回文数:
1 | |
return num == reverse_num(num)是什么意思?这行代码的作用是判断一个数是否为回文数,并返回判断结果。
==是 “等于” 运算符,用于比较左右两边的值是否相等,相等则返回1(真),不相等则返回0(假)。reverse_num(num)会计算num的反转数(例如num=345时,反转数是543)。
因此:
- 如果
num和它的反转数相等(比如num=888,反转数也是888),则num == reverse_num(num)为1,函数返回1(表示是回文数)。 - 如果不相等(比如
num=345,反转数是543),则返回0(表示不是回文数)。
这里的
!is_palindrome(original)的感叹号!是什么意思?由于这里循环继续进行的条件是original不是回文数,而
is_palindrome(original)判断不是回文数会返回0从而终止循环所以这里需要反转一下:
感叹号
!是 “逻辑非” 运算符,作用是取相反的布尔值(真变假,假变真)。is_palindrome(original)的返回值是:- 如果
original是回文数,返回1(真); - 如果不是回文数,返回
0(假)。
因此
!is_palindrome(original)的意思是:- 当
original不是 回文数时,条件为真(1),循环继续执行(继续相加反转数); - 当
original是 回文数时,条件为假(0),循环停止。
- 如果
简单明了地呈现循环条件,避免使用if中的条件判断和break使代码更复杂,同时也避免了非要使用if来打破循环时if语句不知道放哪的烧脑与尴尬
单独列出特殊情况
1 | |