• 代码意识流——花朵数问题(四)


    本文前一部分的链接
    http://www.cnblogs.com/KBTiller/archive/2011/06/01/2065569.html

    10.考虑求各位数N次方的和
      有两个问题需要考虑,第一是存放各位数N次方的和的变量定义的位置,其次是这个变量的类型。
      变量定义的位置,首先考虑在xunhuan()函数定义形参的地方,把这个函数定义为
        static void xunhuan( const int gssx /*个数上限*/,   
                              const int sz /*关于哪个数字*/,
                                    某类型 和)
        {
        }   

      这样的话在qiongju()函数中应该这样调用
        xunhuan( WEISHU , JINZHI-1 ,(某类型) 0 ) ;
      然而由于这个数据的类型不可能是简单的基本类型,所以如果编译器不支持C99的话,就必须首先在qiongju()函数中定义一个变量,把这个变量初始化为0之后再用这个变量作为实参进行调用:
        extern void qiongju( void )
        {
          某类型 和 = {0} ;  
          xunhuan( WEISHU , JINZHI-1 , 和 ) ;
        }
      除了初始化为0之后做实参,“和”这个变量在qiongju()函数中根本没有其他任何用处,所以在qiongju()函数中定义这个变量恐怕难免给人一种牵强的感觉,当然,如果不太讲究的话,这样写也可以。
      C99中有一种东西叫Compound literal,这种东西的本质就是一种复杂数据类型的常量。如果可以使用这种东东,就可以避免牵强地去定义变量。
      由于C99的实现不是那么普遍,所以还是选择把这个变量定义在xunhuan()内部。这个变量用于递归调用中传递数据,因此必须是static类别。

        static void xunhuan( const int gssx /*个数上限*/, 
                                  const int sz /*关于哪个数字*/) 
        {
           static 某类型 he ;//=0
       
          ……
        }

    11.测试
      先考虑求各位数一次方的和,这时可以把“和”的类型暂时确定为int

    static void xunhuan( const int gssx /*个数上限*/, 
                         const int sz /*关于哪个数字*/)  
    {
       static int he = 0 ;//=0  //static 某类型 he ;//=0
       int he_ = he  ;    //记录累加前的值 
    
       if( sz > 0 ){
          int i;
          for( i = 0 ; i <= gssx ; i++ ){
             printf("%d*%d +" , i , sz );
             he += i * sz  ;             // 每次调用都从he开始累加 
             xunhuan( gssx - i , sz - 1 );
             he = he_ ;                  //恢复原来的值 
          }
       }
       else{
          he += gssx * sz ;
          printf("%d*%d = %d" , gssx , sz , he );
          putchar('\n');//<=>验算<=>记录结果
       }
    }
    
    

      运行结果正确。


    12.一个修正
      突然觉得前面把 #include "0_问题.h" 写在 1_MAIN.h 和 2_穷举.h 中很傻,这条预处理命令应该写在 1_MAIN.c 和 2_穷举.c 中。分别移动一下,然后编译,运行,通过。移动成功

    13.添加新类型
      由于“和”这个变量可能需要存储一个很大的整数值,所以普通的整数类型是不能胜任的,需要自己定义新的类型。设新的类型的名字为 DASHU

    修改 
           

    static void xunhuan( const int gssx /*个数上限*/, 
                         const int sz /*关于哪个数字*/)  
    {
       static DASHU he    ; // =0   待完成  
       DASHU        he_   ; // = he 待完成 
    
       if( sz > 0 ){
          int i;
          for( i = 0 ; i <= gssx ; i++ ){
             printf("%d*%d +" , i , sz );
             //待修改 he += i * sz  ;             // 每次调用都从he开始累加 
             xunhuan( gssx - i , sz - 1 );
             //待修改 he = he_ ;                  //恢复原来的值 
          }
       }
       else{
          //待修改 he += gssx * sz ;
          //待修改 printf("%d*%d = %d" , gssx , sz , he );
          putchar('\n');//<=>验算<=>记录结果
       }
    }   
    

      因为涉及到这种新类型的运算较多,这些运算大多需要通过定义函数来重新定义,因此把这种类型的定义及函数统一写在其他模块。

    修改

    /*2_穷举.h*/
    
    #ifndef QIONGJU_H
    #define QIONGJU_H 
    
                  
    /**************************类型定义**************************/ 
       #include "3_大数.h" 
    
    
    /**************************函数原型**************************/ 
       
       extern void qiongju( void );
    
        
    #endif // QIONGJU_H
    
    
     

      在工程中添加“3_大数.h”源文件,最初的内容为

    /*3_大数.h*/
    
    #ifndef DASHU_H
    #define DASHU_H 
                
    /**************************类型定义**************************/ 
       typedef DASHU ; 
    
    /**************************函数原型**************************/ 
       
         
    #endif // DASHU_H
    
    

      随手编译了一下,居然没有任何错误。(没想到这也能编译,typedef 有这种用法吗?这个编译器太善解人意了)

    14.大数类型

      有很多表示大数的方案。最不可取的大概是用字符串存储各位数字的方案,因为会涉及到字符与数值之间的反复转换。除了输入输出比较容易写,这种方案没有什么优势。
      所以采用用一个int存储一位数的方案,WEISHU位数就构成一个数组,各位数字按从低到高顺序存储(下标为0的元素存储个位)。因为运算不能保证一定不超过WEISHU位,这种数据结构应该能表示溢出,即超过WEISHU位时的表示。这个可以通过使得存储最高位数字的元素大于等于JINZHI来表示。
    这样DASHU类型可以定义为
    typedef struct {
                            int gw_sz[WEISHU] ;//gw_sz[0]为个位,gw_sz[WEISHU-1]为最高位
                           } 
                           DASHU ;             //gw_sz[WEISHU-1]的值大于等于JINZHI表示溢出

      之所用struct 把这个数组包装起来是因为注意到了xunhuan()函数中有这种类型数据的赋值运算。结构体类型的数据可以直接赋值,数组要完成同样的功能写起来就复杂多了。

    修改

    /*3_大数.h*/
    
    #ifndef DASHU_H
    #define DASHU_H 
    
    #include "0_问题.h"             //DASHU用到了WEISHU             
    
    /**************************类型定义**************************/ 
    //gw_sz[0]为个位,gw_sz[WEISHU-1]为最高位
    //gw_sz[WEISHU-1]的值大于等于JINZHI表示溢出
       typedef struct { 
                       int gw_sz[WEISHU] ; 
                      }  
                      DASHU ;          
    
    /**************************函数原型**************************/ 
       
         
    #endif // DASHU_H
    

    然后返回xunhuan()函数改写代码。

    15.改写代码

    static DASHU he    ; // =0   待完成
    现在可以补全了
    static DASHU he = { { 0 } }   ;

    DASHU        he_   ; // = he 待完成    //记录累加前的值
    现在可以直接
    DASHU        he_ = he ;   //记录累加前的值

    //待修改 he = he_ ;                  //恢复原来的值
    现在也可以直接
    he = he_ ;                  //恢复原来的值


    下面要做的事情是改写
    //待修改 he += i * sz  ;
    这需要对DASHU这种类型定义加法运算

  • 相关阅读:
    NodeJS学习笔记之Connect中间件模块(一)
    XML CDATA节点
    6个强大的AngularJS扩展应用
    java使用poi读取ppt文件和poi读取excel、word示例
    Java log4j详细教程
    JAVA8 十大新特性详解
    Express 路由
    基于 Node.js 平台,快速、开放、极简的 web 开发框架。
    Node.js 手册查询-1-核心模块方法
    Node.js 手册查询-2-MongoDB数据库方法
  • 原文地址:https://www.cnblogs.com/KBTiller/p/2068470.html
Copyright © 2020-2023  润新知