递归形式的itoa及reverse函数的实现

     源自《The C Programming Language》P75 pr4-12, 4-13:

     编写递归版本的itoa及reverse函数

     代码: 

View Code
1 #include <stdio.h>
2 #include <string.h>
3
4 void printd(int n);
5 void itoa(int n, char s[]);
6 void reverse(char s[]);
7
8 //int end;
9 //int beg;
10
11 #define MAXLINE 100
12
13 int main()
14 {
15 int num;
16 //int beg;
17 //int end;
18 char str[] = "strncpy";
19 char line[MAXLINE] = {'\0'};
20
21 num = -1254;
22 //beg = 0;
23 //end = strlen(str) - 1;
24 printd(num);
25 printf("\n");
26 itoa(num, line);
27 printf("%s\n", line);
28 //reverse(str, beg, end);
29 reverse(str);
30 printf("%s\n", str);
31
32 return 0;
33 }
34
35 void printd(int n) //函数printd:递归调用本身将int型数据转换成字符串型数据,并打印,但不能处理最大负数的情况
36 {
37 if(n < 0)
38 {
39 putchar('-');
40 n = -n;
41 }
42 if(n / 10)
43 printd(n / 10);
44 putchar(n % 10 + '0');
45 }
46
47 /***************************************************************************
48 自定义函数:itoa(递归形式),对比于参考函数
49 ****************************************************************************
50 void reverse(char s[]) //函数reverse:递归调用本身处理字符串反转
51 {
52 char tmp;
53
54 if(beg < end)
55 {
56 tmp = s[beg];
57 s[beg] = s[end];
58 s[end] = tmp;
59 ++beg;
60 --end;
61 reverse(s);
62 }
63 else
64 return;
65 }
66 ***************************************************************************/
67
68 /***************************************************************************
69 参考函数:itoa(递归形式)
70 ***************************************************************************/
71 #include <math.h>
72 void itoa(int n, char s[])
73 {
74 static int i;
75
76 if(n / 10)
77 itoa(n / 10, s);
78 else
79 {
80 i = 0;
81 if(n < 0)
82 s[i++] = '-';
83 }
84 s[i++] = abs(n) % 10 + '0';
85 s[i] = '\0';
86 }
87
88 /***************************************************************************
89 参考函数:reverse(递归形式)
90 ***************************************************************************/
91 void reverse(char s[]) //这样定义函数reverse的目的:保持reverse函数的用户接口一致
92 {
93 void reverser(char s[], int i, int len);
94
95 reverser(s, 0, strlen(s));
96 }
97
98 void reverser(char s[], int i, int len) //真正实现翻转功能的函数:reverser
99 {
100 int c;
101 int j; /*如果将形参定义以static int的形式定义于本函数内,将出现问题*/
102
103 j = len - (i + 1);
104 if(i < j)
105 {
106 c = s[i];
107 s[i] = s[j];
108 s[j] = c;
109 reverser(s, ++i, len);
110 }
111 }

  分析:

   1,  itoa函数中,将局部变量i定义为静态局部变量,这样当递归调用itoa函数时,不会重复的定义变量i了,例如:第一次

          调用itoa函数,定义了static int i; , 这样第二次调用itoa函数时,就不会再定义变量i了,而是直接使用第一次itoa函数

          中的i的值

   2,  reverse函数这样定义的目的:保持reverse函数的用户接口一致,即只需要传递一个参数(待处理的字符串)

   3,  而参考函数reverser的实现方式比自己实现的reverse函数要好,我编写的reverse函数中使用到全局变量beg,end,

          这样安全性不高,内聚度也不高;反之参考的reverser函数将变量beg,end作为reverser的形参,这样就不存在上述

          问题了,并且作为形参的另一个好处:如果不作为形参,而是在reverser定义beg,end,这样,又必须将其定义为

          静态局部变量,并且因为静态局部变量的初始化形式必须是常量表达式,如果定义成static int end = strlen(s) - 1;

          形式将出错,而不这样定义的话,那又无法使用静态局部变量beg, end

   4,  在递归函数中定义的静态局部变量的初始化时,注意:

          正确:

          void fun()

          {

                  static int n = 2;

                   ...

                   fun();

          }

          如上所示的定义并初始化方式是正确的,并符合设计者的思路;

          错误:

          void fun()

          {

                  static int n;

                  n = 2;

                   ...

                  fun();

          }

          这种定义方式编译器虽然不会报错,并且也能运行,但逻辑上有问题,不能达到设计者的要求,

          虽然n是static int 型变量,但每次fun函数递归调用自己时,n的值并不能保持上次的值,因为

          在每次进入fun函数后,n的值都会被赋予2,这样定义的静态局部变量n就没有任何意义了

posted on 2011-06-16 01:33  将军之盾  阅读(613)  评论(0编辑  收藏  举报