输入数字n,按顺序打印出从1到最大的n位十进制数

    输入数字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的时候,程序就不会执行了。

    

wKioL1Zee1LzNJoMAAAZSbiStbw540.png

    这是为什么呢?溢出了,我们所求的最大的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).循环条件是相当于数字的最低位开始。看我画的图片。


wKioL1ZeiZijKyg8AAAe0gN8EnU505.png

    所以循环条件是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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值