C码字练习.07.指针,递归与函数 - 北方连萌

C码字练习.07.指针,递归与函数

函数基本结构

例1.打印(1)

#include<stdio.h>
void chline(char, int, int); //在声明函数时至少输入形式参数的型
int main(void)
{
   int x, m, n;

   scanf("%c %d %d", &x, &m, &n);
   chline(x, m, n); //函数调用
   return 0;
}

void chline(char a, int row, int col) //定义函数时要完整输入形参的型和名
{
   int i, j;

   for (i = 1; i <= row; i++)
   {
      for (j = 1; j <= col; j++)
      {
         printf("%c ", a);
      }
      printf("\n");
   }
}
h 3 4
h h h h 
h h h h 
h h h h 

例2.打印(2)

#include<stdio.h>
void repo(char);
int main(void)
{
   char a;
   
   while ((a = getchar()) != EOF)
   {
      repo(a);
   }
   
   return 0;
}

void repo(char a)
{
   if (a >= 65 && a <= 90)
   {
      printf("%d ", a - 64);
   }
   else if (a >= 97 && a <= 122)
   {
      printf("%d ", a - 96);
   }
   else
   {
      printf("-1 ");
   }   
}
aaa bbb AAA BBB
1 1 1 -1 2 2 2 -1 1 1 1 -1 2 2 2 -1 ^Z

例3.四则运算

#include<stdio.h>
double harmonic_nean(double, double); //在声明函数时至少输入形式参数的型
int main(void)
{
   double m, n;

   scanf("%lf %lf",&m, &n);
   printf("%lf\n", harmonic_nean(m, n)); //函数调用
   return 0;
}

double harmonic_nean(double a, double b) //定义函数时要完整输入形参的型和名
{
   return 1.0 / ((1.0 / a + 1.0 / b) / 2.0);
}
1 2
1.333333

测字符串长度

注意使用strlen()函数前先include<string.h>头文件

#include<stdio.h>
#include <string.h>
int main(void)
{
   printf("The length of |aaaaaaa| is %d.", strlen("aaaaaaa"));

   return 0;
}
The length of |aaaaaaa| is 7.

条件运算符 ? :

这是C中唯一的三元运算符
最简单的用法就是比大小
以下imin()和imax()函数示例

#include<stdio.h>
int imin(int a, int b);
int imax(int a, int b);
int main(void)
{
   printf("%d is bigger.\n", imax(232, 3423));
   printf("%d is smaller.\n", imin(232, 3423));
   return 0;
}

int imin(int a, int b)
{
   return (a < b) ? a : b;
}

int imax(int a, int b)
{
   return (a > b) ? a : b;
}
3423 is bigger.
232 is smaller.

另外,将函数定义放在主程序前面也可,此时函数定义也是声明可以省略一些空间,不影响运行

#include<stdio.h>
int imin(int a, int b)
{
   return (a < b) ? a : b;
}

int imax(int a, int b)
{
   return (a > b) ? a : b;
}
int main(void)
{
   printf("%d is bigger.\n", imax(232, 3423));
   printf("%d is smaller.\n", imin(232, 3423));
   return 0;
}
3423 is bigger.
232 is smaller.

指针与函数

指针"*"可看作寻址"&"的逆运算,如

a = &b; //把变量b的地址赋给变量a(b所在房间命名为a),注意地址是常量不可被赋值(即不可在左)
c = *a; //把地址a指向的变量值赋给c(在a房间内者命名为c)

此时毫无疑问

b == c;

以下程序中的函数(副程序)通过调整指针对主程序施加影响,回传值不要
此时函数可以不仅限单独作用或给主程序回传一个值,而可以实现更多功能

例1

#include<stdio.h>
void larger_of(double * a, double * b);
//double a表示双精度浮点型变量a
//double * a表示地址a指向一个双精度浮点型变量(a房间里有一个double型变量)
void interchange(double *, double *);
int main(void)
{
   double m, n;

   printf("Enter a pair of numbers (separating with a space): ");
   scanf("%lf %lf", &m, &n);
   interchange(&m, &n);
   printf("Result of interchange: %.2f %.2f\n",m, n);
   larger_of(&m, &n); //把地址(实参&m,&n)传给函数,此函数中是给形参a,b
   printf("The bigger one: %.2f\n", m);

   return 0;
}

void larger_of(double * a, double * b)
{
   if (*a < *b) //如果a房间中的数小于b房间中的数
   {
      *a = *b; //让b房间的数覆盖原来a房间的数
   }
   else //否则
   {
      *b = *a; //让a房间的数覆盖原来b房间的数
   }
}

void interchange(double * a, double * b)
{
   double temp;
   temp = *a; //把a房间的数先叫作temp
   *a = *b; //让b房间的数覆盖a房间的数
   *b = temp; //让原来a房间的数覆盖b房间的数
}
Enter a pair of numbers (separating with a space): 88.55 88.45
Result of interchange: 88.45 88.55 //此时看似交换了数,实际交换了数所在的房间
The bigger one: 88.55

例2

#include<stdio.h>
void sort_3(double * a, double * b, double * c);
void interchange(double * a, double * b);
int main(void)
{
   double a, b, c;
   printf("Enter 3 numbers (separating with spaces):\n");
   while (scanf("%lf %lf %lf", &a, &b, &c) == 3)
   {
      sort_3(&a, &b, &c); //此处传入的是地址
      printf("Sorting result:\n");
      printf("%.0f %.0f %.0f\n\n", a, b, c);
      printf("Enter 3 numbers (separating with spaces):\n");
   }
   return 0;
}

//以下交换方法仅对3数排序有效,更多数的排序参照冒泡(循环)和快排(递归)
void sort_3(double * a, double * b, double * c)
{
   if (*a > *c)
      interchange(a, c); //此处传入的也是地址
   if (*b > *c)
      interchange(b, c);
   if (*a > *b)
      interchange(a, b);
}

void interchange(double * a, double * b)
{
   double temp;
   temp = *a;
   *a = *b;
   *b = temp;
}
Enter 3 numbers (separating with spaces):
1 2 3
Sorting result:
1 2 3

Enter 3 numbers (separating with spaces):
1 3 2
Sorting result:
1 2 3

Enter 3 numbers (separating with spaces):
2 1 3
Sorting result:
1 2 3

Enter 3 numbers (separating with spaces):
2 3 1
Sorting result:
1 2 3

Enter 3 numbers (separating with spaces):
3 1 2
Sorting result:
1 2 3

Enter 3 numbers (separating with spaces):
3 2 1
Sorting result:
1 2 3

Enter 3 numbers (separating with spaces):
quit

循环与递归

整数指数幂

循环版

#include<stdio.h>
double power_z(double a, int b);
int main(void)
{
   double a;
   int b;

   printf("%f\n", power_z(2, 1));
   printf("%f\n", power_z(2, 5));
   printf("%f\n", power_z(2, -2));
   printf("%f\n", power_z(2, 0));
   printf("%f\n", power_z(0, 44));
   printf("%f\n", power_z(1.1, 44));
   printf("%f\n", power_z(1.1, -44));
   printf("%f\n", power_z(-2, 3));
   printf("%f\n", power_z(-2, -3));
   printf("%f\n", power_z(-1.1, -43));
   printf("%f\n", power_z(-1.1, 0));
   printf("%f\n", power_z(0, 0));
   
   
   return 0;
}

double power_z(double a, int b)
{
   if (b > 0)
   {
      int i;

      if (a == 0)
      {
         return 0;
      }
      else
      {
         double e = 1;
         
         for (i = 0; i < b; i++) //使用循环进行累乘
         {
            e *= a;
         }
         return e;
      }
   }
   if (b == 0)
   {
      if (a != 0)
      {
         return 1;
      }
      else
      {
         printf("Result for 0 to the power of 0 is undefined.\n");
         printf("It will be processed as 1.\n");
         return 1;
      }
   }
   if (b < 0)
   {
      int j, c;

      c = -b;
      if (a == 0)
      {
         return 0;
      }
      else
      {
         double f = 1;

         for (j = 0; j < c; j++)
         {
            f *= a;
         }
         return 1 / f;
      } 
   }
}
2.000000
32.000000
0.250000
1.000000
0.000000
66.264076
0.015091
-8.000000
-0.125000
-0.016600
1.000000
Result for 0 to the power of 0 is undefined.
It will be processed as 1.
1.000000

递归版

递归即是在某函数中调用其自身
为了防止无限递归的状况(像两面镜子互相照对方)
会在调用之前设定一个判断,限定递归次数

返回值的型 函数名A(参数的型 参数)
{
   “递”部分的语句;
   if(判断条件)
      含有函数名A(参数)的语句;
   “归”部分的语句;
   ...
   return 返回值;
}

处理流程大致如下

主程序调用第1级的函数

执行第1级“递”部分的语句

到条件语句时判断为真

第1级的函数调用第2级的函数

...

执行第n - 1级“递”部分的语句

到条件语句时判断为真

第n - 1级的函数调用第n级的函数

执行第n级“递”部分的语句

到条件语句时判断为假


执行第n级“归”部分的语句

第n级返回值传回第n - 1级

执行第n - 1级“归”部分的语句

...

第2级返回值传回第1级

执行第1级“归”部分的语句

第1级的返回值传回主程序

递归与循环的相似之处可以看作是
第1~n轮循环中的每一次都执行完前半就进行下一轮
不满足判断条件后再按第n~1的顺序执行每一轮的后半
惟每调用一次函数就要多创建一次实参,过多次递归将会大量消耗内存

求整数指数幂的函数可改写如下:

#include<stdio.h>
double power_z(double a, int b);
int main(void)
{
   double a;
   int b;

   printf("%f\n", power_z(2, 1));
   printf("%f\n", power_z(2, 5));
   printf("%f\n", power_z(2, -2));
   printf("%f\n", power_z(2, 0));
   printf("%f\n", power_z(0, 44));
   printf("%f\n", power_z(1.1, 44));
   printf("%f\n", power_z(1.1, -44));
   printf("%f\n", power_z(-2, 3));
   printf("%f\n", power_z(-2, -3));
   printf("%f\n", power_z(-1.1, -43));
   printf("%f\n", power_z(-1.1, 0));
   printf("%f\n", power_z(0, 0));
   
   
   return 0;
}

double power_z(double a, int b)
{
   if (b > 0)
   {
      int i;

      if (a == 0)
      {
         return 0;
      }
      else
      {
         double e = 1;
         
         if (b > 0) //递归次数设限
         {
            e = a * power_z(a, b - 1); //调用自身,且使每次“递”都要接近次数限制(以渐化式形式)
         }
         
         return e;
      }
   }
   if (b == 0)
   {
      if (a != 0)
      {
         return 1;
      }
      else
      {
         printf("Result for 0 to the power of 0 is undefined.\n");
         printf("It will be processed as 1.\n");
         return 1;
      }
   }
   if (b < 0)
   {
      int j, c;

      c = -b;
      if (a == 0)
      {
         return 0;
      }
      else
      {
         double f = 1;

         if (c > 0)
         {
            f = a * power_z(a, c - 1);
         }
         
         return 1 / f;
      } 
   }
}
2.000000
32.000000
0.250000
1.000000
0.000000
66.264076
0.015091
-8.000000
-0.125000
-0.016600
1.000000
Result for 0 to the power of 0 is undefined.
It will be processed as 1.
1.000000

斐波那契数列

循环版

Fortran写法:

见此

#include<stdio.h>
int fibonacci(int);
int main(void)
{
   int i;

   for (i = 1; i <= 20; i++)
      printf("%d ", fibonacci(i));
   
   return 0;
}

int fibonacci(int aim)
{
   int a[10000], k;

   a[0] = 0;
   a[1] = 1;
   for(k = 2; k < aim + 1; k++)
      a[k] = a[k - 1] + a[k - 2];

   return a[aim];

}
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

递归版

#include<stdio.h>
int fibonacci(int);
int main(void)
{
   int i;

   for (i = 1; i <= 20; i++)
      printf("%d ", fibonacci(i));
   
   return 0;
}

int fibonacci(int aim)
{
   int a;
   
   if (aim >= 3)
      a = fibonacci(aim - 1) + fibonacci(aim - 2);
   else if (aim == 1 || aim == 2)
      a = 1;

   return a;
}
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

10进制→2或8进制

递归在“归”的部分是反着来的特点,使之适合于这种结果取反的问题

#include<stdio.h>
#include<ctype.h>
int to_base_n(int, int);
int main(void)
{
   double b;
   char ch;
   
   b:
   printf("Please enter a decimal number greater than 0 (decimal part will be cut automatically): ");
   while(scanf("%lf", &b) != 1 || b <= 0)
   {
      printf("Please enter a decimal number greater than 0 (decimal part will be cut automatically): ");
      while (getchar() != '\n')
      {
         continue;
      }
   }
   a:
   printf("Please choose a positional numeral system:\n");
   printf("------------------------------------------\n");
   printf("      a) binary             b) octal\n");
   printf("------------------------------------------\n");
   fflush(stdin);
   ch = getchar();
   switch (ch)
   {
   case 'a':
      printf("Result:");
      to_base_n((int)b, 2);
      printf("\n");
      fflush(stdin);
      break;
   case 'b':
      printf("Result:");
      to_base_n((int)b, 8);
      printf("\n");
      fflush(stdin);
      break;
   default:
      goto a;
   }
   c:
   printf("Enter next number? (y/n)\n");
   switch (getchar())
   {
   case 'y':
      goto b;
   case 'n':
      break;
   default:
      printf("y or n, please.\n");
      fflush(stdin);
      goto c;
   }
   printf("Bye.\n");
   
   return 0;
}

int to_base_n(int i, int n)
{
   if (i >= n)
   {
      printf("%d", i - to_base_n(i / n, n) *n);
      //余数 = 本次被除数 - 下次被除数(即本次的商) * 除数
   }
   else if (i >= 0 && i < n)
   //被除数比除数小时,不再求余,而把被除数直接摆在开头
   {
      printf("%d", i);
   }
   
   return i;
}
Please enter a decimal number greater than 0 (decimal part will be cut automatically): q
Please enter a decimal number greater than 0 (decimal part will be cut automatically): .
Please enter a decimal number greater than 0 (decimal part will be cut automatically): -7
Please enter a decimal number greater than 0 (decimal part will be cut automatically): -1.1
Please enter a decimal number greater than 0 (decimal part will be cut automatically): 2.2
Please choose a positional numeral system:
------------------------------------------
      a) binary             b) octal
------------------------------------------
b
Result:2
Enter next number? (y/n)
y
Please enter a decimal number greater than 0 (decimal part will be cut automatically): 42
Please choose a positional numeral system:
------------------------------------------
      a) binary             b) octal
------------------------------------------
a
Result:101010
Enter next number? (y/n)
b
y or n, please.
Enter next number? (y/n)
y
Please enter a decimal number greater than 0 (decimal part will be cut automatically): 42
Please choose a positional numeral system:
------------------------------------------
      a) binary             b) octal
------------------------------------------
b
Result:52
Enter next number? (y/n)
n
Bye.

添加新评论

电子邮件地址不会被公开,评论内容可能需要管理员审核后显示。