输入数字n,按顺序打印出从1到最大的n位十进制数,热锅按照先找到最大的数,然后循环输出,当n很小的时候,程序是不会有什么问题的。当n很大的时候这种情况就是在按照这种思路来实现就会出现问题,那么就需要找出一种大数相加的办法。
一.首先实现上面思路
#include<stdio.h> void find_maxnum(int n) { if(n<=0) { return; } int num = 1; int i = 0; while (i++ < n) { num *= 10; } for (i = 1; i < num; i++) { printf("%d\t", i); } } int main() { int n = 0; scanf("%d", &n); find_maxnum(n); system("pause"); return 0; }
测试当n=1-14的时候,程序可以执行,当n=15的时候,程序就不会执行了。
这是为什么呢?溢出了,我们所求的最大的n位数是不是用整型(int)或者长整型(long int)都会溢出,这就是这道题的陷阱,那我们怎么做才能规避这个问题。
二.在字符串模拟数字加法的解法
用字符串表示大数的时候,最直观的就是字符串里面的每个字符都是‘0’到‘9’之间的某个字符,用来表示数字中的一位,。因为数字最大是n位,因此我们需要一个长度为n+1的字符串(字符串的最后一位是‘\0‘)。当实际数字不够n位的时候,在字符串前半部分补0。只需要做两件事情,一是在字符串表达的数字上模拟加法,二是把字符串表达的数字打印出来。
void print(int n) { if (n <= 0) { return; } char *number = (char *)malloc((n + 1)*sizeof(char)); memset(number, ‘0‘, n); number[n] = ‘\0‘; while (!incerment(number)) { print_num(number); } free(number); number = NULL; }
1).开辟一块(n+1)大小的char类型的空间,将前面n块空间置为‘0’;
2).将(n+1)的地方置为‘\0‘;需要注意的是,代码number[n]访问的就是开辟的第(n+1)的空间,因为数组是从0开始。
int incerment(char* number) { assert(number); int flag = 0; int ntackover = 0; int nlen = strlen(number); for (int i = nlen - 1; i >= 0; i--) { int nsum = number[i] - ‘0‘ + ntackover; if (i == nlen - 1) { nsum++; } if (nsum >= 10) { if (i == 0) { flag = 1; } else { nsum = nsum - 10; ntackover = 1; number[i] = ‘0‘ + nsum; } } else { number[i] = ‘0‘ + nsum; break; } } return flag; }
1).判断指针的有效性。设置标记flag。
2).循环条件是相当于数字的最低位开始。看我画的图片。
所以循环条件是for(int i = nlen - 1;i<=0;--i);
3).当进入循环首先当前i是个位还是高位,比如现在打印到9再一次进入到循环中,给9+1变成10,那么就会进入到if(num>=10)的条件中,此时i=0进入else,将nsum-10让,然后将给字符串把‘10’保存进去。之后再次进入循环,i变成0;number[0]就相当于10位数的十位,然后给10位加1。将结果交给打印函数。
void print_num(char *number) { assert(number); int flag = 1; int nlen = strlen(number); for (int i = 0; i < nlen; ++i) { if (flag && number[i] != ‘0‘) { flag = 0; } if (!flag) { printf("%c", number[i]); } } printf("\t"); }
1).将要打印的字符串进入打印函数,首先算出字符串的长度,设置标志位判断要打印的字符串首字符是否是有效数字,如果是‘0’那么再一次进入循环直到找到有效位。只有当flag为0的时候才会打印。
以上就是本人在学习过程中的一些经验总结。当然,本人能力有限,难免会有纰漏,希望大家可以指正。
本文出自 “做一个小小小司机” 博客,请务必保留此出处http://10799170.blog.51cto.com/10789170/1718844
原文:http://10799170.blog.51cto.com/10789170/1718844