C语言------关于整数输入的正序和倒序输出

本文介绍使用C语言实现整数的正序和倒序输出的方法。倒序输出通过按位取余和循环保存实现;正序输出则采用递归方式,将整数转换为字符数组并打印。

定义一个整数类型的输入,然后让它正序输出,倒序输出相信是很多C语言初学入门一定会遇到的经典题目,下面就是我对整数的正序和倒序输出一点小小的总结.

1. 反序(倒序)输出

     反序输出常用的思路就是按位取余,把取出来的值进行循环保存

int main()
{
    int i=12345; //定义一个12345的整数
    int temp=0;//temp作为存储的值

    while(i!=0){
        temp = temp*10 + i%10;
         i/=10;  
     }  //反序取出来

     printf("%d",temp); //打印
    return 0;
}

2, 正序输出

正序输出会用在整形变量正序输出转换成对应的字符数组,或者倒过来.常用思路就是定义一个函数,在函数内递归取余调用自身,实现功能

输入 : 12345

输出 :"12345"

char str(int x)
{
    char a[100];//存放整数转换过来的字符
    int i;   //计数
    if(x/10!=0)
        str(x/10);
    if(x>=0)
        a[i]='0'+x%10;  //整数转换成字符存储,字符都是以整数形式存储
    else
        a[i]='0'+(-x)%10;//整形包括负数
    printf("%c",a[i++]);
}
int main()
{
    int i;
    printf("请输入一个整数:\n");
    scanf("%d",&i);
    str(i);

    return 0;
}


<think>我们在讨论如何将一个整数输出。根据引用内容,有几种常见的方法:方法1:使用数组,将整数的每一位分离存储到数组中,然后逆输出数组(引用[1])。方法2:使用循环数学运算,通过不断取余整除10来逆重组整数(引用[2]引用[4])。方法3:使用递归函数(引用[3])。方法4:处理负数的情况,先输出负号,然后将负数转为数处理(引用[5])。下面我将分别展示这些方法,并给出示例代码。注意:对于负数,我们需要特殊处理(如方法4所示)。但有些方法没有处理负数,我们也可以改进使其支持负数。方法1:数组法步骤:1.输入一个整数(包括负数?原引用[1]没有处理负数,我们可以改进)。2.如果是负数,先输出负号,然后将其转为数处理(但注意:整数的最小值转为数可能会溢出,这里我们假设输入在安全范围内)。3.用循环分离每一位,存入数组。4.然后按数组逆输出(或者存入时就是逆的,输出输出数组即可)。方法2:数学重组法(循环)步骤:1.处理负数:如果是负数,先输出负号,然后取绝对值。2.循环:每次取当前数的最后一位(x%10),然后加到结果变量(result)上,同时将原数除以10(去掉最后一位)。3.注意:在加到最后一位之前,需要将原来的结果乘以10(以提升位数)。方法3:递归法步骤:1.递归函数可以按从高位到低位的顺递归,但输出时从低位开始(即递归到最深层先输出)。2.同样需要处理负数。下面给出每种方法的代码示例,并尽可能处理负数情况(但注意:对于0,需要特殊考虑,因为0的逆还是0,且0没有位数,循环需要至少执行一次)。我们以方法2(数学重组法)为例,注意0的情况:如果输入0,循环会一次都不执行吗?所以需要单独处理0?实际上,在方法2中,如果我们使用do-while循环,可以处理0(但引用[5]使用了do-while,而引用[2][4]使用了while循环,且条件为x!=0)。对于0,while循环条件不满足,所以不会执行,因此结果变量初始为0,最后输出0。所以可以处理0。但是,如果输入是负数,比如-123,我们希望输出-321。方法1:数组法(改进支持负数)注意:数组法在分离数字时,我们使用循环,条件为n!=0(但如果是负数,我们需要先转为数)。另外,0的情况需要单独处理。方法2:数学重组法(改进支持负数)我们可以先判断负数,然后取绝对值,最后重组。但注意:重组后的数字可能溢出(如果逆后的数字超过int范围),但题目没有特别说明,我们假设输入不会导致溢出。方法3:递归法(引用[3]的方法是用递归将整数转换为字符串,然后输出字符串。我们也可以直接递归输出数字,而不存储数组。)下面给出三种方法的代码:方法1:数组法```c#include <stdio.h> #include<stdlib.h>//用于abs函数int main() {intnum,a[20], i, k=0;//数组大小设为20,足够大printf("请输入一个整数:");scanf("%d",&num);//处理0if (num ==0) {printf("0\n");return0;}//处理负数int isNegative =0;if (num <0) {isNegative =1;num =abs(num); //取绝对值}//分离每一位while(num>0){a[k] =num %10; //取最后一位num/=10;k++;}//如果是负数,先输出负号if(isNegative){printf("-");}//输出数组(从0到k-1,因为分离时是从最低位开始,所以顺输出就是逆)for(i=0;i <k;i++){printf("%d",a[i]);}printf("\n");return0; }```方法2:数学重组法```c#include<stdio.h>#include <stdlib.h> //用于abs函数int main() {intn;printf("请输入一个整数:");scanf("%d", &n);//处理0if(n==0){printf("0\n");return0;}intisNegative=0;if(n<0){isNegative=1;n= abs(n);}intresult =0;while (n >0) {result= result*10 +n %10;n/=10;}if(isNegative){printf("-");}printf("%d\n", result);return0;} ```方法3:递归法(直接输出,不存储)递归函数可以这样设计:每次递归传入的数除以10,直到为0,然后回溯时输出每一位。但这样输出的顺就是逆吗?实际上,如果我们先递归再输出,那么输出就是逆(因为先递归到最深层,然后回溯时输出的是最低位,然后倒数第二位...直到最高位)。但是这样输出的数字没有存成一个整数,而是直接输出每一位。注意:递归法同样需要处理负数0。递归函数设计(直接输出): ```c#include <stdio.h>void reversePrint(intn){if (n ==0){return;}printf("%d", n%10);//先输出最后一位reversePrint(n/10);//递归处理剩下的部分}//但是这样输出的是从最低位到最高位?不对,这样输出的是先输出最低位,然后递归处理剩下的(剩下的相当于原数去掉最低位),然后递归中又会输出剩下的最低位(即原数的次低位)...所以输出就是逆的。但是注意,这样输出的数字没有空格分隔,而且递归深度可能会比较大。//但是,这个递归函数在n=0时直接返回,所以如果输入是0,不会输出任何东西。所以需要单独处理0。 //另外,负数处理:我们可以在主函数处理负数,然后递归函数只处理数。 intmain(){int num;printf("请输入一个整数:");scanf("%d",&num);if (num ==0) {printf("0");return0;}if(num<0){printf("-");num =-num; //注意:直接取负,因为num是负数,取负后为。但要注意最小负数取负可能会溢出,这里假设输入范围在安全范围内。}reversePrint(num);printf("\n");return0; }```但是,上面的递归函数有一个问题:递归调用的顺输出当前最低位,然后递归处理剩余部分(即n/10)。这样输出的是逆,但是注意,递归的深度整数的位数相同,如果整数位数很多,可能导致栈溢出。另外,上面的递归函数在输入123时,输出321,确。但是输入100,输出001?我们希望输出1(而不是001)。所以递归函数需要改进:不能简单地在递归前输出,因为前导零的问题。实际上,递归函数应该先递归处理高位,然后再输出当前位,这样才是?不对,我们想要逆输出。所以递归函数应该先输出低位,再处理高位?但这样会导致输出是低位到高位(即逆),但前导零变成了后缀零?比如100,输出001,但我们希望输出1(即001的逆是100,但我们希望输出1,因为001去掉前导零就是1,但逆后100的前导零在最后?所以实际上我们不需要输出前导零,但递归函数无法知道当前位是不是最后面的零(即前导零)。因此,递归函数直接输出每一位的方法不适合处理有尾随零的情况(因为尾随零在逆后变成了前导零,而前导零应该省略,但递归函数在输出时无法判断哪些零是尾随零)。所以,递归法更适合将逆的数字存起来(如引用[3]那样,存成字符串),然后输出字符串。或者使用数组存储,再输出。这里我们展示引用[3]的方法(递归转字符串): ```c#include <stdio.h> //递归函数,将整数n的每一位逆存入字符数组s中(以字符形式)void convert(char s[], intn){inti;if((i= n/10)!=0){convert(s+1,i);//递归处理剩余部分,并且s+1表示下一个字符位置}else {//当n只有一位时,将s指向的位置赋值为字符串结束符*(s+1) ='\0';}*s =n %10+ '0';//将当前位转换为字符}int main() {intnum;charstr[20]= {0};//初始化为0printf("请输入一个整数:");scanf("%d",&num);if (num ==0) {printf("0\n");return0;}int isNegative =0;if(num<0){isNegative=1;num= -num;}//调用递归函数convert(str, num);if (isNegative) {printf("-");}printf("%s\n",str);//输出字符串return0;} ```但是,引用[3]的递归函数有点复杂,而且它存储的是逆的字符串吗?注意:递归函数中,先递归处理剩余部分(n/10),然后再将当前位(n%10)存入s指向的位置。由于递归是先处理高位,再处理低位,所以存入的顺是从低位到高位?不对,递归调用是convert(s+1,i),然后当前位存入s。这样,最高位存在数组的低地址,最低位存在数组的高地址?然后我们在主函数中输出字符串,是从低地址到高地址,也就是先输出最高位?不对,我们希望逆输出,所以这样存储的顺实际上是原数的逆吗?我们分析一下:例如:123第一次调用:n=123,i=12,递归调用convert(s+1,12)第二次调用:n=12,i=1,递归调用convert(s+2,1)第三次调用:n=1,i=0,所以不递归,然后执行*s=1%10+'0'='1',此时s指向的位置是s+2(即第三个字符位置),所以str[2]='1',然后设置*(s+1)='\0'(即str[3]='\0')回溯到第二次调用:s指向的位置是s+1(即str[1]的位置),执行*s=12%10+'0'='2',所以str[1]='2'回溯到第一次调用:s指向str,执行*s=123%10+'0'='3',所以str[0]='3'最后字符串str为:'3','2','1','\0',所以输出是321。确。但是,这个递归函数在只有一位数时,会设置*(s+1)='\0',所以没有问题。但是,如果输入100,则:递归过程:第一次:n=100,i=10 ->递归调用convert(s+1,10)第二次:n=10, i=1->递归调用convert(s+2,1)第三次:n=1 ->设置*(s+3)='\0'(因为第二次调用时s+2,所以第三次s指向s+2的位置,然后设置*(s+1)即s+3为结束符),然后*s='1'(在s+2位置)回溯到第二次:s指向s+1,执行*s=10%10+'0'='0'(所以s+1位置为'0')回溯到第一次:s指向str,执行*s=100%10+'0'='0'(所以str[0]='0')最后字符串:str[0]='0', str[1]='0',str[2]='1', str[3]='\0' ->输出"001",但我们希望输出"1"(因为100的逆是1,但这里输出了001)。所以这种方法没有去掉前导零。因此,递归转字符串的方法也存在前导零问题。实际上,在逆重组整数时,前导零会被自然忽略(因为001就是1)。但在字符串中,我们存储的是字符,所以前导零也被存储了。为了解决前导零问题,我们可以在递归函数中避免存储前导零,但这样会复杂很多。因此,通常我们使用数学重组法(方法2)可以避免前导零问题,因为重组后的整数001就是1。总结:推荐使用数学重组法(方法2)数组法(方法1),因为它们简单且能确处理前导零(数学重组法将数字重组为整数,自然去掉了前导零;数组法在存储时,我们只存储了数字的每一位,然后输出,但数组法输出的每一位,包括中间的0,所以100会输出001,但这不是我们想要的整数形式,所以数组法更适合输出字符串形式的逆,而不适合作为整数输出。因此,数学重组法更符合要求:输出一个整数。所以,如果要求输出后的整数(而不是字符串),则数学重组法更好。因此,我们选择方法2(数学重组法)作为主要方法,并注意处理负数0。但是,数学重组法有一个潜在问题:逆后的整数可能超出int范围(溢出)。例如,输入2147483647,逆后是7463847412,超过了int范围(最大2147483647)。所以,如果输入可能很大,我们可以用longlong来存储结果。改进方法2(使用longlong): ```c#include <stdio.h> #include<stdlib.h>//用于abs函数int main() {longlong n; //输入也用long long,因为可能输入很大printf("请输入一个整数:");scanf("%lld", &n);if(n==0){printf("0\n");return0;}intisNegative=0;if(n<0){isNegative=1;n= llabs(n); //注意:使用longlong的abs}longlong result=0;while(n>0){result =result *10+ n%10;n/=10;}if(isNegative){printf("-");}printf("%lld\n", result);return0;} ```这样,可以处理更大范围的整数(但注意,longlong也有范围,如果逆后超出longlong范围,还是会溢出)。如果要求更高,可以用字符串处理(数组法),然后输出字符串(即逆后的字符串形式,不转换为整数)。因此,根据需求选择:1.如果输入范围不大,用数学重组法(int或long long)。2.如果输入范围可能很大(比如几十位),则用数组法(字符串法)。现在,我们假设输入在longlong范围内,那么使用上面的改进方法2即可。如果用户要求输出字符串形式的逆(即不转换为整数,所以可以处理任意大的数),那么我们可以用数组法(字符串):```c#include <stdio.h> #include<string.h>int main() {charnumStr[100]; //假设最多99位printf("请输入一个整数:");scanf("%s",numStr);//处理负号:如果第一个字符是负号,则先输出负号,然后逆输出剩余部分intstart =0;if (numStr[0] =='-'){printf("-");start =1; //跳过负号}//计算字符串长度intlen =strlen(numStr);//从最后一位开始向前输出(跳过负号的话,最后一位是len-1,开始位置是start)for (int i= len-1; i>= start; i--) {printf("%c", numStr[i]);}printf("\n");return0; }```这种方法可以处理任意大的整数(只要数组足够大),且不会溢出。综上所述,根据不同的需求,我们可以选择不同的方法。现在,我们来回答用户的问题:如何将一个整数输出?总结几种方法:1.数学重组法(适用于整数范围在long long内的情况)2.数组法(存储每一位数字,然后逆输出输出整数形式时注意前导零,但作为整数输出时前导零会被忽略?实际上,数组法输出的是每一位,所以100会输出001,但如果我们用数学重组的思想,将数组中的数字重组为整数,可以避免前导零,但这样又回到了数学重组法)3.字符串法(直接输入为字符串,然后逆输出字符串,可以处理任意大的整数,且不会溢出)因此,如果用户输入的数可能很大,推荐字符串法;如果确定在longlong范围内,数学重组法更直接。下面,我们给出字符串法的代码作为最终推荐(因为它更通用): ```c#include <stdio.h> #include<string.h>int main() {charnum[100];//假设最多99个字符printf("请输入一个整数:");scanf("%s", num);int len= strlen(num);intstart =0;intend =len -1;//检查是否有负号if (num[0]== '-') {printf("-");start=1;//负号后面的数字才需要逆}//逆输出数字部分(从末尾到start)for(inti =end;i >=start;i--){printf("%c",num[i]);}printf("\n");return0; }```注意:这个程输入时,用户可能会输入非数字字符(除了开头的负号),但题目要求是整数,所以我们假设输入是有效的整数。现在,我们根据要求生成相关问题:§§相关问题§§1.如何处理逆输出时前导零的问题?2.如果输入的数字很大(超过long long范围),如何实现逆输出?3.如何用递归方法实现整数的逆输出? 4.逆输出整数时,负数应该如何处理?5.字符串法逆输出整数的优点缺点是什么?</think>### C语言实现整数输出的方法 在C语言中,实现整数输出主要有三种方法,下面我将详细说明每种方法的原理实现代码: #### 方法1:数学运算法(推荐) **原理**:通过循环取余(`%10`)获取最低位数字,然后整除(`/10`)移除最低位,同时将数字累加到新变量实现逆重组。 ```c #include <stdio.h> #include <stdlib.h> // 用于abs() int main() { int n; printf("请输入整数:"); scanf("%d", &n); // 处理负数0 if (n == 0) { printf("0"); return 0; } if (n < 0) { printf("-"); n = abs(n); // 转为数处理 } int reversed = 0; while (n > 0) { reversed = reversed * 10 + n % 10; // 逆重组 n /= 10; // 移除最低位 } printf("%d", reversed); return 0; } ``` **特点**: - 时间复杂度:$O(\log_{10} n)$ - 空间复杂度:$O(1)$ - 直接生成逆整数,无额外存储[^2][^4] #### 方法2:数组存储法 **原理**:将整数的每一位分离存入数组,再逆输出数组元素。 ```c #include <stdio.h> #include <stdlib.h> // 用于abs() int main() { int num, digits[20], count = 0; // 数组存储每位数字 printf("请输入整数:"); scanf("%d", &num); if (num == 0) { printf("0"); return 0; } if (num < 0) { printf("-"); num = abs(num); } // 分离每位数字 while (num > 0) { digits[count++] = num % 10; num /= 10; } // 逆输出 for (int i = 0; i < count; i++) { printf("%d", digits[i]); } return 0; } ``` **特点**: - 直观易理解 - 需额外数组空间[^1] - 适合需要保留中间结果的场景 #### 方法3:递归法 **原理**:通过递归调用先处理高位数字,回溯时输出低位实现逆。 ```c #include <stdio.h> #include <stdlib.h> void reverse_print(int n) { if (n == 0) return; printf("%d", n % 10); // 先输出最低位 reverse_print(n / 10); // 递归处理剩余部分 } int main() { int num; printf("请输入整数:"); scanf("%d", &num); if (num == 0) { printf("0"); return 0; } if (num < 0) { printf("-"); num = abs(num); } reverse_print(num); return 0; } ``` **特点**: - 代码简洁 - 递归深度受位数限制 - 可能引起栈溢出[^3] ### 关键处理细节 1. **负数处理**:先输出负号,再用`abs()`转数处理[^5] 2. **前导零问题**:数学法自动忽略(如100→1),数组法保留零 3. **零的特殊处理**:需单独判断输出"0" 4. **大数溢出**:输入超出`int`范围时建议使用`long long` ### 性能对比 | 方法 | 时间复杂度 | 空间复杂度 | 适用场景 | |------------|------------|------------|------------------| | 数学运算法 | $O(\log n)$ | $O(1)$ | 通用推荐 | | 数组存储法 | $O(\log n)$ | $O(\log n)$ | 需保留中间结果 | | 递归法 | $O(\log n)$ | $O(\log n)$ | 位数较少的情况 | > **提示**:日常使用推荐**数学运算法**,兼顾效率简洁性;若需处理超大整数(超`long long`范围),可改用字符串处理。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值