コンテンツ
演習1:整数値(符号なし)を取得し、そのビットを順番に出力します。
演習2:文字列の長さを見つけるための一時変数の作成を許可しない関数を記述します。
演習3:再帰を使用してnの階乗を見つけます。(オーバーフローに関係なく)
演習4:n番目のフィボナッチ数を見つけます。(オーバーフローに関係なく)
演習6:パラメータ文字列の文字を逆の順序で印刷するのではなく、逆の順序で配置します。
関数宣言:
1.コンパイラーに、関数が何であるか、パラメーターが何であるか、および戻りタイプが何であるかを伝えます。しかし、それは具体的に存在しますか、機能声明は決定しません。2.関数の宣言は、通常、関数を使用する前に表示されます。使用前に宣言を満たすため。3.関数宣言は通常、ヘッダーファイルに配置されます。
内部宣言の方法
関数定義をメイン関数の前に置くと、プログラムは上から下に順番に実行されるため、fun関数を定義すると、fun関数も宣言されます。
定義されたfun関数をmain関数に配置すると、警告が報告されます。
これを回避するには、メイン関数の前に関数を宣言するだけです。
現時点では警告はありません。これを記述する方法は2つあります。括弧内のパラメーターのタイプが明確に示されているか、このタイプの変数が作成されます。
外部機能の使い方
別の.cファイルで関数を使用する場合は、関数を宣言するか、externを追加して直接使用する必要があります。
test.cのtest1.cの関数を使用し、exrrnを使用します
外部関数を宣言および定義する
test.cのtest1.cでfun関数を使用したいと思います。最初に、fun関数を宣言するヘッダーファイルを作成する必要があります。
次に、test1.cでfun関数を定義します
定義後、test.cで参照する場合は、fun関数を定義するヘッダーファイルをtest.cに入力するだけです。
この時点で、test.cのadd関数を通常どおり使用できます。
静的ライブラリファイルのコンパイルと使用
誰かが私たちの関数を使用したいと思っていて、私たちが彼にコードを与えたくない場合は、この時点で静的ライブラリファイルを生成して彼に使用させることができます
静的ライブラリファイルを生成する
他の人に与える関数を静的ライブラリファイルに編集し、最初にプロジェクト名をクリックしてから、[プロパティ]を選択します
一般に、構成タイプを選択してから、静的ライブラリファイルを選択して適用します
Ctrl + F5を押すと、この時点で静的ライブラリファイルが生成されます
ファイルディレクトリに.libファイルがあります
それと.hファイルを送信する必要のあるファイルにコピーします
この時点で、使用する必要のあるプロジェクトで、コピー先の.hファイルを追加し、ヘッダーファイルを参照します。
次に、#pragma comment(lib、 "add.lib")と入力すると、正常に実行できます。
関数の再帰
プログラムがそれ自体を呼び出すプログラミングトリックは、再帰と呼ばれます。アルゴリズムとしての再帰は、プログラミング言語で広く使用されています。プロシージャまたは関数は、その定義または仕様に直接的または間接的に含まれています自分自身を呼び出す通常、大きくて複雑な問題を元の問題と同様の小さな問題に変換して解決する方法。再帰的戦略問題解決プロセスに必要な繰り返し計算を記述するために使用できるプログラムはごくわずかであり、プログラムのコード量が大幅に削減されます。再帰についての主な考え方は次のとおりです。大きなものを小さくする
再帰に必要な2つの条件
制約があります。この制約が満たされると、再帰は続行されません。再帰呼び出しを行うたびに、この制限にどんどん近づいていきます。
演習1:整数値(符号なし)を取得し、そのビットを順番に出力します。
#include<stdio.h>
int fun(int a)
{
if (a > 9)
{
fun(a / 10);
}
printf("%d ", a%10);
}
int main()
{
int a = 1234;
fun(a);
return 0;
}
演習1の思考分析:
演習2:文字列の長さを見つけるための一時変数の作成を許可しない関数を記述します。
#include<stdio.h>
int fun(char * b)
{
if (*b != '\0')
return 1 + fun(b + 1);
else
return 0;
}
int main()
{
char a[] ="abcdef";
printf("%d",fun(a));
return 0;
}
演習3:再帰を使用してnの階乗を見つけます。(オーバーフローに関係なく)
#include<stdio.h>
int fun(int b)
{
if (b <= 1)
return 1;
else
return b*fun(b-1);
}
int main()
{
int a =5;
printf("%d",fun(a));
return 0;
}
演習4:n番目のフィボナッチ数を見つけます。(オーバーフローに関係なく)
#include<stdio.h>
int fun(int b)
{
if (b <=2)
return 1;
else
return fun(b-2)+fun(b-1);
}
int main()
{
int a =10;
printf("%d",fun(a));
return 0;
}
演習5:非再帰的にフィボナッチ数を実装する
#include<stdio.h>
int fun(int x)
{
int a = 1;
int b = 1;
int c = 1;
while (x >= 3) //前俩个数都为 1 1
{
c = a + b;
a = b;
b = c;
x--;
}
return c;
}
int main()
{
int a =10;
printf("%d",fun(a));
return 0;
}
演習6:パラメータ文字列の文字を逆の順序で印刷するのではなく、逆の順序で配置します。
要件:Cライブラリの文字列操作関数は使用できません。
例えば:
#include<stdio.h>
void fun(char *b)
{
if (*b != '\0')
fun(b + 1);
if (*b == '\0')
{
return;
}
printf("%c", *b);
}
int main()
{
char a[] ="abcdefg";
fun(a);
return 0;
}
演習7:ハノイの塔
下から順に、サイズ順に別のポストのディスクを並べ替えます。また、小さなディスクではディスクを拡大することはできず、3つのポスト間で一度に移動できるディスクは1つだけであると規定されています。
Aにプレートがある場合は、Aを直接Cに移動します
Aに2つのプレートがある場合は、Aの最初のプレートをBに移動し、下部のプレートをCに移動してから、BのプレートをCに移動します。
Aに3つのプレートがある場合は、最初のプレートをCに移動し、2番目のプレートをBに移動し、次にCのプレートをBに移動し、次にAの下部にあるプレートをCに移動してから、最初のプレートを上に移動します。 BからBへ。1つはAに移動し、次にBからCに移動し、AからCに移動します。
#include<stdio.h>
void move(char A,char B)
{
printf("%c-%c ", A, B); //移动盘子的函数
}
void Han(int a,char z,char x,char c) //a:盘子的个数 z:其实的柱子,x:经过x进行转移的柱子 c:目的柱子
{
if (a == 1)
{
move(z, c);
}
else
{
Han(a - 1, z, c, x); //如果盘子个数大于1,则先通过第三个柱子把除底部最后一个盘子的其余盘子移动到第二个柱子
move(z,c); // 接着把第一个柱子上最后一个盘子,移动到C,
Han(a - 1, x, z, c);// 把第二根柱子上的盘子,通过第一个柱子移动到第三跟柱子上
}
}
int main()
{
Han(1, 'A', 'B', 'C');
return 0;
}
問題が見つかりました;フィボナッチ数を再帰的に見つけるときに、数が大きすぎると、プログラムがクラッシュします
このとき、プログラムは印刷されません。これは、フィボナッチ数列が計算されるときに、各数値が関数を2回呼び出して、2つのスペースを開くためです。スペースがすべて使い果たされ、まだスペースを開いている場合、この時点で時間プログラムがクラッシュします
上記の問題を解決する方法:1.再帰を非再帰に書き直します。2.非静的ローカルオブジェクトの代わりに静的オブジェクトを使用します。再帰関数の設計では、代わりに静的オブジェクトを使用できます非静的ローカルオブジェクト(つまり、スタックオブジェクト)。これは、再帰的な呼び出しと戻りのたびに非静的オブジェクトを生成および解放するオーバーヘッドを削減するだけであり、静的オブジェクトも保持できます。再帰呼び出しの中間状態を格納します。各呼び出し層からアクセスします。
ヒント:
1.多くの問題は、非再帰形式よりも明確であるという理由だけで、再帰形式で説明されます。2.しかし、これらの問題の反復的な実装は、コードが少し読みにくくなりますが、再帰的な実装よりも効率的であることがよくあります。3.問題が非常に複雑で、繰り返し実装するのが難しい場合、再帰的な実装の単純さは、それがもたらすランタイム開発を補うことができます。ピン。