题目:
给你一个正整数n 请实现函数输出 1~n 位数的最大数。比如n=5,输出1,2,3,4,5 … … 99,100 … … 99999。
我们很容易想到的方法就是先算出这个n位数的最大数, 然后再循环输出好了 。但是你转念又一想,如果n是一个很大的数,那么我们求出的n位最大数 用 int 还是 longlong 是不是都会溢出。这个问题需要我们最主要解决的就是大数问题。
我们一般可以用字符串来表达大数,一共最多 n位数,我们申请一个n+1长度的char类型数组 ,全部赋初值为 0。 然后每一次为字符串加1,在打印出来。所以我们最主要做的就是两件事 ,一是在字符串表达上模拟数字加法, 二是把字符串以数字的形式输出出来。
模拟数字加法:
我们从最后一位数开始分析 我们每次加1 打印 1 2 3直到最后一位数到9,在加1变成10。那么字符串的倒数第二位就变成了1,我们下一次输出是11,又回到了最后1位而倒数第二位的1是不变的。直到最后一位的9又变成了10,倒数第二位再加1变成了2 ,下一次输出又回到了倒数第一位。当倒数第二位的数字变成9 ,倒数第一位的数字也变成了9 加1变成了10, 那么倒数第二位进位也变成了10,即倒数第三位应该变成了1,然后又回到了最后一位开始加1,慢慢又进位。每次进位完成后都会又会回到最后一位开始继续加1输出下一个数字。那么什么时候结束呢 当第一位数字 (i= 0的位置) 需要进位 从9变成10时 结束打印。
输出:
而我们输出的时候也不能是简单的用库函数输出,因为我们的字符串前面还有一堆我们用来填补空位的0,是不能输出的 ,输出的时候找到第一个非零字符开始打印。
#include<iostream>
using namespace std;
bool Increment(char *number);
void PrintfNumber(char *number);
void PrintfToMaxOfNDigits(int n)
{
if(n<=0) return;
char *number = new char[n+1];
memset(number,'0',n);
number[n] = '\0'; //字符串最后一位为'\0
while(!Increment(number)){
//进入模拟数字加法函数
PrintfNumber(number); //打印函数 模拟加法函数 返回false 才会打印
}
delete []number;
}
bool Increment(char *number){
bool isOverflow = false; //记录是否是第一位产生的进位初始值为false
int nTakeOver = 0;
int nLength = strlen(number);
for(int i = nLength - 1;i >= 0;i--){
//如果发生进位那么就会往前走 假如现在字符串为99 进入循环是最后一位9+1=10了 需要进位 最后一位变成0
int nSum = number[i] - '0' + nTakeOver; //nTakerOver=1 i-- 往前走 到了倒数第二位 因为是倒数第二位 只涉及到进位的加1 数字的加1都是需要从最后一位加的
if(i == nLength-1) //而倒数第二位现在也为9 因为进位加1变成了10 则倒数第二位变成了0 又i--到下一次循环的倒数第三位 第三位的数字只有一位
//进位加的 1 则当前字符串变成了100 下一次加1 又从最后一位开始进行 即如果加1不造成最后一位的进位 则不会再次进入循环
//直接打印 但是如果造成进位 还会接连造成前面的进位 那么把发生进位的位置变为0,然后移动到相应的位置进行进位加1的计算
nSum++;
if(nSum >= 10){
if(i == 0) //产生了进位 如果是第一位产生的进位则 标志置为true 结束打印
isOverflow = true;
else
{
nSum = nSum - 10; //产生了进位 最后一位变成了0
nTakeOver = 1; //用来表示发生进位 这个数位的前一位应该加1
number[i] = '0' + nSum; //该位发生进位变成0
}
}
else
{
number[i] = '0' + nSum;
break;
}
}
return isOverflow;
}
void PrintfNumber(char *number){
bool isBeginning0 = true;
int nLength = strlen(number);
for(int i = 0;i < nLength;i++){
if(isBeginning0 && number[i]!='0')
isBeginning0 = false;
if(!isBeginning0)
{
printf("%c",number[i]);
}
}
printf("\t");
}
int main()
{
int n=3;
PrintfToMaxOfNDigits(n);
return 0;
}
如果有的小伙伴的编译器可以行断点调试,那你可以进行调试走一下进位的过程更方便你理解,会比看别人说理解的更深刻。