C言語は登場すると、その豊富な機能、高い表現力、柔軟性と利便性、応用範囲の広さから急速に世界中に普及し、推進されました。
C言語は実行効率が高いだけでなく移植性にも優れており、アプリケーションソフトウェアやドライバ、OSなどの開発に利用できます。
C 言語は他の多くの高級言語の元祖言語でもあるため、プログラミングの世界に入るには C 言語の学習が必須コースとなります。
こんにちは世界
#include<stdio.h>
int main()
{
/*在双引号中间输入Hello World*/
printf("Hello World");
return 0;
}
注: 最新の C 標準では、main 関数の前の型はint
使用できません。void
C言語の具体的な構造
簡単に言えば、C プログラムはいくつかの头文件
合計で構成されます函数
。
#include <stdio.h>
これは前処理コマンドであり、その機能は、C プログラムが正式にコンパイルされる前に、何らかの前処理作業を行う必要があることを C 言語コンパイル システムに通知することです。
-
函数
これは、コード ロジックを実装する小さなユニットです。
必須のメイン機能
C プログラムには、main
関数というメイン関数が 1 つだけあります。
C プログラムは main 関数内のコードを実行するものであり、 main 関数はC 言語の唯一の入り口であるとも言えます。
-
main の前のint はmain 関数の型です。
-
printf()
これはフォーマット出力関数です。ここでの機能は、指定された情報を画面に出力することであることに注意してください。 -
returnは関数の戻り値で、関数の種類によって戻り値も異なります。
-
\n
エスケープ文字内の改行です。(注: C プログラムは main 関数から実行する必要があります)
良い習慣の規範
-
説明またはステートメントは 1 行を占めます。たとえば、ヘッダー ファイルをインクルードし、実行可能ステートメントの最後には改行が必要です。
-
関数本体内のステートメントは明確にインデントする必要があります。通常、Tab キーを 1 回押すと 1 つのインデントが作成されます。
-
括弧はペアで記述し、削除する必要がある場合はペアで削除する必要があります。
-
実行可能ステートメントの最後にはセミコロンが必要です。
-
コード内の記号はすべて英語の半角記号です。
プログラム解説・注意事項
コメントはプログラマ向けに書かれており、コンピュータ向けではありません。
C 言語でコメントするには 2 つの方法があります。
複数行のコメント:
/* 注释内容 */
単一行コメント:
//注释一行
名前付き C (識別子)
(A~Z,a~z)
C 言語では、識別子には文字、数字(0~9)
、アンダースコアの文字列を使用でき_
、最初の文字は文字またはアンダースコアでなければならないと規定されています。識別子を使用する場合は、次の点に注意してください。
識別子の長さは 8 ビットを超えないことが最善です。これは、C の一部のバージョンでは、識別子の最初の 8 ビットが有効であり、2 つの識別子の最初の 8 ビットが同じ場合、それらは同じであるとみなされます。識別子。
-
識別子では大文字と小文字が厳密に区別されます。たとえば
Imooc
、 と はimooc
2 つの異なる識別子です。 -
「名前を見て意味がわかる」識別子には中国語を使うのではなく、意味のある英単語を選ぶのがベストです。
-
C 言語では識別子をキーワードにすることはできません。C 言語のキーワードについて詳しく知りたい。
変数と代入
変数とは変更可能な変数であり、それぞれの変数には名前(識別子)が付けられます。変数はメモリ内の特定の記憶ユニットを占有します。変数は使用する前に定義する必要があり、変数名と変数値は2 つの異なる概念です。
変数定義の一般的な形式は次のとおりです。 データ型 変数名。
同じ型の複数の変数: データ型変数名、変数名、変数名...;
注: 連続代入は定義で許可されていないint a=b=c=5;
ため不正です。
変数に値を代入するには 2 つの方法があります。
-
代入する前に宣言する
-
宣言の同時代入
基本的なデータ型
C 言語では、データ型は次のように分類できます。
-
基本的なデータ型
-
データ型を構築する
-
ポインタ型
-
空の型の 4 つのカテゴリ
最も一般的に使用される整数型、実数型、および文字型(char、int、float、double):
整数データは、小数点のない数値 (int、short int、long int、unsigned int、unsigned short int、unsigned long int) を指します。
注記:
-
int
short int
long int
コンパイル環境により取得される範囲が異なります。 -
ここで
short int
、 と はlong int
少なくとも表に記載されている範囲ですが、int
表内の値は 16 ビット コンパイル環境で記載された値の範囲です。 -
また、C言語の値の範囲は
int
占有バイト数に依存し、コンパイラごとに規定が異なります。 -
ANSI 標準定義は
int
2 バイトを占め、TC はint
2 バイトを占める ANSI 標準に基づいています。ただし、VC では 1 つがint
4 バイトを占有します。
浮動小数点データは、小数を含む数値を指します。
人間の体重 (単位: キログラム)、商品の価格、円周率など、浮動小数点データで表現するのに適した情報が生活の中にはたくさんあります。
精度の違いにより、次の 3 つのタイプ (float、double、long double) に分類されます。
注: C 言語には文字列変数はなく、文字列は文字配列内にのみ存在できます。これについては後で説明します。
フォーマットされた出力ステートメント
書式設定された出力ステートメントは、プレースホルダ出力とも呼ばれ、書式設定された種類と指定された位置に従ってコンピュータからのさまざまな種類のデータを表示します。
その形式は次のとおりですprintf("输出格式符",输出项)
。
出力ステートメントに通常の文字が含まれる場合、次の形式を使用できます。
printf("普通字符输出格式符", 输出项);
注:フォーマット シンボルの数は、変数、定数、または式の数と 1 対 1 で対応する必要があります。
不変定数
プログラムの実行中に値が変化しない量を定数と呼びます。
mtianyan: C 言語の定数は直接定数と記号定数に分けられます。
-
直接定数はリテラル量とも呼ばれ、次のように説明なしで直接使用できます。
-
整数定数: 13、0、-13。
-
実定数: 13.33、-24.4。
-
文字定数: 'a'、'M'
-
文字列定数: 「imooc が大好きです!」
-
C 言語では、記号定数と呼ばれる識別子を使用して定数を表すことができます。シンボリック定数は使用する前に定義する必要があり、その一般的な形式は次のとおりです。
#define 标识符 常量值
#include <stdio.h>
#define POCKETMONEY 10 //定义常量及常量值
int main()
{
// POCKETMONEY = 12; //小明私自增加零花钱对吗?
printf("小明今天又得到%d元零花钱\n", POCKETMONEY);
return 0;
}
記号定数は変更できません。
自動型変換
データ型の自動変換は、異なるデータ型を
操作する場合に発生し、コンパイル時に自動的に完了する場合があります。
char
int
型付きデータから型付きデータへの変換は、ASCII
コード内の対応する値に従います。
注記:
小さいバイトは大きいバイトに自動的に変換できますが、大きいバイトは小さいバイトに自動的に変換できません
char は int に変換でき、int は double に変換でき、char は double に変換できます。しかし、それを元に戻すことはできません。
キャスト
強制は、型変換操作を定義することによって実現されます。その一般的な形式は次のとおりです。
(データ型) (式)
その機能は、式の演算結果を型指定子で示された型にキャストすることです。
強制を使用する場合は、次の問題に注意してください。
-
データ型と式の両方を括弧で囲む必要があり、のように
(int)(x/2+y)
記述すると、 Shape(int)x/2+y
に変換され、分割されて加算されます。x
int
2
y
-
変換後、元のデータの型や変数値は変更されず、この操作では一時的な変換のみが行われます。
-
強制変換後の演算結果は丸め原則に従いません。
符号の計算
C 言語の演算子:
※ 算术运算符
※ 赋值运算符
※ 关系运算符
※ 逻辑运算符
※ 三目运算符
算術演算子
C 言語の基本的な演算子:
除算演算に注意してください。
除算する 2 つの数値が両方とも整数の場合、結果も整数となり、;のように小数部分が省略されます
8/3 = 2
。
2 つの数値のうちの 1 つが 10 進数の場合、結果は次のような 10 進数になります
9.0/2 = 4.500000
。
mtianyan: 剰余演算に注意してください:
この演算は、次のような2 つの整数を使用する剰余演算にのみ適しています
10%3 = 1
。
mtianyan: 注: 10.0%3 は間違っています。演算後の符号は、次
(-10)%3 = -1;
のように係数の符号に依存します。10%(-3) = 1;
mtianyan: %%
これが%
シンボルであることを示します。
注: C 言語にはべき乗演算子がなく×, ÷
、等号算術記号は使用できません。
インクリメント演算子とデクリメント演算子
-
自己インクリメント演算子は です
++
。その機能は、変数の値を 1 ずつ自己インクリメントすることです。 -
自己デクリメント演算子は であり
--
、その機能は変数の値を 1 だけデクリメントすることです。
これらはループ内でよく使用されます。インクリメント演算子とデクリメント演算子は次の形式になります。
代入演算子
C言語の代入演算子は単純代入演算子と複合代入演算子に分かれます。
単純な代入演算子の=
シンボル、複合代入演算子について話しましょう。
複合代入演算子は、=
単純な代入演算子の前に他の演算子を追加することによって形成されます。
例えば
+=、-=、*=、/=、%=
分析: 整変数 a を定義し、それに値 3 を割り当てます。この式は 、変数 a と 5 を加算して、それを a に割り当てることとa += 5;
同じです。a = a+5;
注:複合演算子では、演算子と等号の間にスペースは入れません。
関係演算子
C 言語の関係演算子:
関係式の値は真
合計であり、 假
C プログラムでは整数1
の合計で表されます0
。
注:>=, <=, ==, !=
このような記号の間にスペースを入れることはできません。
論理演算子
C言語の論理演算子:
論理演算値にも 2 種類あり真
、假
C 言語では整数 1 と 0 で表されます。その評価ルールは次のとおりです。
-
AND演算
&&
演算に関係する両方の変数が true の場合、結果は true になり、それ以外の場合は false になります。例: 5>=5 && 7>5、演算結果は true です。
-
OR演算
||
操作に関係する 2 つの変数のうち 1 つが true である限り、結果は true になります。両方の量が false の場合、結果は false になります。例: 5>=5||5>8、演算結果は true です。
-
操作ではありません
!
演算に関与する変数が true の場合、結果は false になり、演算に関与する変数が false の場合、結果は true になります。例: !(5>8)、演算結果は true です。
三項演算子
C 言語の三項演算子: ?:
、その形式は次のとおりです。
表达式1 ? 表达式2 : 表达式3;
実行プロセスは次のとおりです。
まず式1の値が真かどうかを判定し、真の場合は式2を実行し、偽の場合は式3を実行します。
#include <stdio.h>
int main()
{
//定义小编兜里的钱
double money =12.0 ;
//定义打车回家的费用
double cost =11.5 ;
printf("小编能不能打车回家呢:");
//输出y小编就打车回家了,输出n小编就不能打车回家
printf("%c\n",money>=cost?'y':'n' );
return 0;
}
事業者競合の優先比較
各種演算記号の順序:
優先度 1 は優先度が最も高く、優先度 10 は優先度が最も低くなります。
分岐構造の単純な if 文
C言語における分岐構造文内の文if条件
。
単純な if ステートメントの基本構造は次のとおりです。
if(表达式)
{
执行代码块;
}
そのセマンティクスは次のとおりです。式の値が true の場合は次のステートメントを実行し、それ以外の場合はステートメントを実行しません。
注:if()
後ろにセミコロンはありません。直接記述してください。{}
分岐構造の単純な if-else 文
単純なif-else
ステートメントの基本構造は次のとおりです。
セマンティクスは次のとおりです。式が true と評価された場合はコード ブロック 1 が実行され、それ以外の場合はコード ブロック 2 が実行されます。
知らせ:
if()
その後にセミコロンはありません。{} だけを書きます。else の後にはセミコロンはなく、{} だけを書きます。
分岐構造内の複数の if-else ステートメント
C 言語のif-else
複数のステートメントの構造は次のとおりです。
セマンティクスは次のとおりです。式の値を順番に判断し、特定の値が true の場合は対応するコード ブロックを実行し、そうでない場合はコード ブロック n を実行します。
注:特定の条件が true の場合、分岐構造の他のステートメントは下方向に実行されません。
分岐構造のネストされた if-else 文
C 言語のネストされたステートメントif-else
。ネストされたif-else
ステートメントの意味はif-else
、ステートメントの中にステートメントを記述することですif-else
。その一般的な形式は次のとおりです。
ループ構造のwhileループ
特定の動作を繰り返し実行することを、業界の人は「サイクル」と呼びます 。
C言語には3つのループ構造があります。まずC言語のwhileループの構造を見てください。
式はループ条件を表し、実行コード ブロックはループ本体です。
while ステートメントのセマンティクスは次のとおりです。式の値を計算し、
真(非0)
値が等しい場合にループ本体のコード ブロックを実行します。
-
while文の式は一般に関係式や論理式であり、式の値がfalseの場合はループ本体は実行されず、そうでない場合はループ本体が常に実行されます。
-
ループ本体内のループ変数の値を変更することを忘れないでください。変更しないと、無限ループ (無限の実行) が発生します。
-
ループ本体に複数のステートメントが含まれる場合は、ステートメントを
{}
括弧で囲んで複合ステートメントを形成する必要があります。
ループ構造のDo-whileループ
C 言語のループの一般的な形式はdo-while
次のとおりです。
do-while ループ ステートメントのセマンティクスは次のとおりです。
まずループ内の実行コードブロックを実行し、while 内の式が true かどうかを判定し、true の場合はループを継続し、false の場合はループを終了します。したがって、do-while ループはループ ステートメントを少なくとも 1 回実行する必要があります。
注: mtianyan:do-while
構造ステートメントを使用する場合は、while 括弧の後にセミコロンが必要です。
ループ構造のforループ(1)
C 言語のfor ループの一般的な形式は次のとおりです。
その実行プロセスは次のとおりです。
-
式 1 を実行してループ変数を初期化します。
-
判定式 2 は、値がtrue (0 ではない)の場合、for ループ本体内のコード ブロックを実行してから下方向に実行し、値がfalse (0)の場合、ループを終了します。
-
式 3、(i++) およびループ変数を操作するその他のステートメントを実行します。
-
for ループ内のコード ブロックを実行した後、2 番目のステップを実行します。最初のステップの初期化は 1 回だけ実行されます。
-
ループが終了し、プログラムは下方向に実行を続けます。
注: for ループ内の2 つのセミコロンを記述する必要があります。
ループ構造のforループ(2)
for ループ内:
-
式 1 は、変数の初期値を制御するために使用される1 つ以上の代入ステートメントです。
-
式 2 は、ループを終了するタイミングを決定する関係式です。
-
式 3 はループ変数のステップ値で、各ループ後にループ変数がどのように変化するかを定義します。
-
これら 3 つの部分はセミコロンで区切られます
;
。
for ステートメントを使用するときは、次の点に注意する必要があります。
-
for ループ内の「式 1、2、3」は空であってはなりませんが、2 つのセミコロンを
(;;)
デフォルトにすることはできません。 -
「式1(ループ変数に初期値を代入)」を省略すると、ループ変数に初期値を代入しないことになります。
-
「式2(ループ条件)」を省略し、他の処理を行わず、常にループが実行されます(無限ループ)。
-
「式3(ループ変数の増減)」を省略し、他の処理を行わず、常にループが実行されます(無限ループ)。
-
式 1 は、ループ変数の初期値を設定するための代入式であっても、他の式であってもよい。
-
式 1 と式 3 は、単純な式にすることも、カンマで区切った複数の式にすることもできます。
-
式 2 は関係式や論理式が一般的ですが、数値式や文字式でもよく、その値が 0 以外であればループ本体が実行されます。
-
各式の変数は、 for ループの前に定義する必要があります。
数の百、十、一を取得する方法
-
百の位: 整数型なので小数部切り捨てで
num/100
取得できます 。int
たとえば、765/100
結果は次のようになります。7
-
十の位:
num%100/10
.765%100
get first65
、65/10
getなど6
-
1 桁:
num%10
。765%10
得る5
3種類のループ構造の比較
while、do-while、for の 3 つのループは、特定の使用場面で次のように異なります。
ループの数がわかっている場合は、 for ループを使用する方が適しています。
-
while または do-while ループは、ループの数が不明な場合に適しています。
-
1 回ループしないことが可能な場合は、while ループの使用を検討してください。
-
少なくとも 1 回ループする場合は、do-while ループの使用を検討する必要があります。
-
しかし本質的には、while、do-while、for ループは交換可能です。
ループ構造内の複数のループ
複数のループとは、ループ構造のループ本体に出現するループ構造です。
実際の開発では、通常、最大3 つの重いサイクルが使用されます。
ループ層が増えると実行時間が長くなり、プログラムが複雑になるため、通常は複数のループを 2 ~ 3 層で十分です。さらに、異なるループをネストすることもできます。
複数のループの実行中、外側のループがループ、内側のループが子ループになります。
親ループに入ると、子ループはループから抜け出すまで完全に実行される必要があります。親ループは次回に入り、子ループは実行を続けます...
mtianyan: 三角形の星の積み重ねを印刷します。
#include <stdio.h>
int main()
{
int i, j, k;
for(i=1; i<5; i++)
{
/* 观察每行的空格数量,补全循环条件 */
for(j=i; j<5; j++)
{
printf(" "); //输出空格
}
/* 观察每行*号的数量,补全循环条件 */
for( k=0;k<2*i-1;k++)
{
printf("*"); //每行输出的*号
}
printf("\n"); //每次循环换行
}
return 0;
}
forループを使用して9×9の乗算表を出力します。
#include <stdio.h>
int main()
{
// 定义相乘数字i,j以及结果result
int i, j, result;
for(i=9;i>=1;i--)
{
for(j=1;j<=i;j++)
{
printf("%d*%d=%d ",i,j,result=i*j);
}
printf("\n");
}
return 0;
}
endステートメントのbreakステートメント
そして、サイクルが5回になったら、トレーニングを継続せずに中止する必要があります。C 言語では、break
ステートメントを使用してこれを行うことができます。
ステートメントを使用するときは、次の点に注意してくださいbreak
。
ループ構造を持たない単一の if-else ステートメントでは、break を使用できません。
-
マルチレベル ループでは、break ステートメントは現在のループからのみ抜け出します。
end ステートメントの continue ステートメント
そして、サイクルが5回になると、トレーニングを中断しても継続する必要があります。C では、continue
これは次のステートメントを使用して実行できます。
continue ステートメントの機能は、このサイクルを終了し、次のサイクルを開始することです。
Break ステートメントと continue ステートメントの違いは次のとおりです。
Break は現在のループ全体から抜け出すこと、Continue はこのループを終了して次のループを開始することです。
分岐構造のswitch文
switch ステートメントの構造は次のとおりです。
mtianyan: switch
発言する際には次の点にも注意する必要があります。
-
case 以降の各定数式の値は同じにすることはできません。同じでない場合はエラーが発生します。
-
case 節の後にBreak ; がない場合は、 break ; に遭遇するまで実行され、その後 switch ステートメントが飛び出します。
-
スイッチの背後にある式ステートメントは、整数型または文字型のみにすることができます。
-
case の後には、{} 括弧なしで複数のステートメントを使用できます。
-
各caseとdefault句の順序は、プログラムの実行結果に影響を与えることなく変更できます。
-
default
条項は省略できます。
mtianyan: switch と if ステートメントの適用 (計算は西暦で行われます)
#include <stdio.h>
int main()
{
/* 定义需要计算的日期 */
int date = 0;
int year = 2008;
int month = 8;
int day = 8;
switch(month)
{
case 12:date+=30;
case 11:date+=31;
case 10:date+=30;
case 9:date+=31;
case 8:date+=31;
case 7:date+=30;
case 6:date+=31;
case 5:date+=30;
case 4:date+=31;
case 3:
if((year%4==0&&year%100!=0)||year%400==0)
{
date+=29;
}
else
{
date+=28;
}
case 2:
date+=31;
case 1:
date+=day;
printf("%d年%d月%d日是该年的第%d天",year,month,day,date);
break;
default:
printf("error");
break;
}
return 0;
}
正: continue はループ本体内でのみ使用できます。
悪名高いgoto文
C言語にもこのような文があり、これはgoto
ステートメントであり、goto文は無条件分岐文です。
goto ステートメントの使用形式は次のとおりです。
goto 语句标号;
自作関数
stdio.h
C言語は、出力関数の提供など、多数のライブラリ関数を提供します。
カスタム関数の一般的な形式は次のとおりです。
知らせ:
-
[]
含まれる内容は省略可能、データ型の説明は省略され、デフォルトは関数型ですint
。関数がパラメータなしの関数であることを示す場合はパラメータが省略され、関数がパラメータのない関数であることを示す場合はパラメータが省略されません。パラメータ付き関数; -
関数名は識別子の命名規則に従います。
-
mtianyan: カスタム関数は
main
できるだけ関数の前に置きます。メイン関数の後に置きたい場合は、メイン関数の前にカスタム関数を宣言する必要があります。宣言形式は次のとおりです。
[数据类型说明] 函数名称([参数]);
関数呼び出し
カスタム関数を使用する必要がある場合は、それを呼び出す必要があるため、それを呼び出すときは関数呼び出しと呼ばれます。
C 言語では、関数呼び出しの一般的な形式は次のとおりです。
函数名([参数]);
知らせ:
パラメータなしで関数を呼び出す場合、
[]
インクルードを省略できます。
-
[]
定数、変数、その他の構造化データや式を指定でき、複数のパラメータはカンマで区切られます。
参加あり 参加なし
関数パラメータを必要としない関数はパラメータなし関数と呼ばれ、関数内で関数パラメータが必要な関数はパラメータ化関数と呼ばれます。
パラメータを含む関数とパラメータを持たない関数の一般的な形式は次のとおりです。
パラメーター付き関数とパラメーターなし関数の唯一の違いは、関数 ()
内に追加のパラメーター リストがあることです。
-
パラメータを持つ関数はより柔軟であり、メイン関数にパラメータが渡される限り、n の変化に応じて出力内容を自由に変更できます。
-
ただし、引数なし関数の出力は比較的固定されており、変更する必要がある場合はカスタム メソッドでループ変数の値を変更する必要があります。
mtianyan: 正式参加実績パラメータ
関数パラメータは、仮パラメータと実パラメータに分けられます。
-
仮パラメータは関数名や関数本体を定義する際に使用されるパラメータで、関数呼び出し時に渡されるパラメータを受け取ることが目的です。
言ったことは言ったが行動しなかったシャオミンのように。
-
引数は、関数が呼び出されたときに関数に渡されるパラメータです。
Xiaogangが実際に行動できるように。
関数パラメータと実パラメータには次の特性があります。
-
仮パラメータは、呼び出し時にのみメモリ ユニットを割り当て、呼び出しが終了すると、割り当てられたメモリ ユニットを直ちに解放します。したがって、仮パラメータは関数内でのみ有効です。
関数呼び出しが終了して呼び出し関数に戻った後は、仮パラメータ変数は使用できなくなります。
-
実際のパラメータは、定数、変数、式、関数などです。
実際のパラメータがどのような種類の量であるかに関係なく、関数が呼び出されるとき、それらの値は仮パラメータに転送できるように、明確な値を持っている必要があります。したがって、実パラメータはあらかじめ代入などの方法で明確な値を求めておく必要があります。
-
パラメータを渡すとき、実際のパラメータと仮パラメータは数量、型、順序において厳密に一致している必要があります。そうでない場合は、型の不一致エラーが発生します。
関数の戻り値
関数の戻り値とは、関数が呼び出された後、関数本体内のプログラムセグメントを実行して取得され、呼び出し元の関数に返される値を指します。
関数の戻り値は次の点に注意する必要があります。
-
関数の値は、
return
ステートメントを通じて呼び出し元の関数にのみ返すことができます。
return ステートメントの一般的な形式は次のとおりです。
return 表达式 或者为:return (表达式);
-
関数値の型は、関数定義内の関数の型と一致している必要があります。
注: この 2 つが矛盾する場合、関数の戻り値の型が優先され、型変換が自動的に実行されます。
-
戻り値の型が の 、値を返さない
void
関数。
知らせ:
void
関数には実行コード ブロックを含めることができますが、値を返すことはできません。
mtianyan:
void
function 内にステートメントがある場合return
、そのステートメントは関数を終了することしかできません。その形式は次のとおりです。return;
再帰関数 (1)
再帰とは、関数がその本体内でそれ自体を呼び出すことです。
再帰関数を実行すると、それ自体が繰り返し呼び出され、呼び出すたびに新しいレベルに入ります。
再帰関数には終了条件が必要であることに注意してください
再帰関数(2)
5 の階乗の例を分析し、計算プロセスを見てみましょう。
プログラムが 5 の階乗を計算する場合、最初に再帰を実行し、n=1 または n=0 の場合に 1 を返し、次にプッシュバックして計算して戻ります。再帰関数には終了条件が必要であることがわかります。
再帰関数の特徴:
-
関数の各レベルには呼び出し時に独自の変数がありますが、5 の階乗の計算などの関数コードはコピーされません。変数は再帰的になるたびに異なります。
-
各呼び出しは 1 回戻ります。たとえば、5 の階乗を計算する場合、再帰ごとに次回に戻ります。
-
再帰関数では、再帰呼び出しの前のステートメントは、すべてのレベルで呼び出される関数と同じ実行順序になります。
-
再帰関数では、再帰呼び出し後のステートメントの実行順序は、呼び出される各関数の実行順序と逆になります。
-
再帰関数には終了ステートメントが必要です。
再帰を一文で要約: 自己呼び出しと完了ステータス
タスク
サルは初日に N 個の桃を摘み、その時点で半分を食べましたが、満足できなかったので、さらに 1 個食べました。翌日、彼は残りの桃を半分食べ、さらにもう1個食べました。その後は、前日の半分と残りの1個を毎日食べます。10日目に食べようと思ったら桃が1個しか残っていませんでしたが、初日は何個収穫したのでしょうか?そして、1 日に残る桃の数を逆順に出力します。
#include <stdio.h>
int getPeachNumber(int n)
{
int num;
if(n==10)
{
return 1;
}
else
{
num = (getPeachNumber(n+1)+1)*2;
printf("第%d天所剩桃子%d个\n", n, num);
}
return num;
}
int main()
{
int num = getPeachNumber(1);
printf("猴子第一天摘了:%d个桃子。\n", num);
return 0;
}
再帰的なデモ。
5人が一緒に座っていますが、5人目の人は何歳ですか? 4人目より2歳年上だそうです。4人目の年齢を聞くと、3人目より2歳年上だそうです。3人目の人に尋ねて、彼は2人目の人より2歳年上だと言います。2人目の人に尋ねて、彼は1人目の人より2歳年上だと言います。最後に最初の人に聞いてみたら、10歳だそうです。5人目は何歳ですか?
プログラム分析:
再帰的手法を使用すると、再帰はバックトラックと再帰の 2 つの段階に分割されます。5 人目の年齢を知りたい場合は、4 人目の年齢を知る必要があり、以下同様に 1 人目 (10 歳) まで、その後プッシュバックする必要があります。
#include <stdio.h>
int dfs(int n) {
return n == 1 ? 10 : dfs(n - 1) + 2;
}
int main()
{
printf("第5个人的年龄是%d岁", dfs(5));
return 0;
}
ローカルとグローバル
C言語の変数はスコープの範囲に応じてローカル変数とグローバル変数の2種類に分けられます。
-
ローカル変数は内部変数とも呼ばれます。ローカル変数は関数内で定義されます。この変数のスコープは関数内に制限されており、関数を終了した後にこの変数を使用することは違法です。変数は複合ステートメント内でも定義できますが、その有効範囲は複合ステートメントの範囲内のみです。
-
グローバル変数は外部変数とも呼ばれ、関数の外部で定義される変数です。これはどの関数にも属さず、ソース プログラム ファイルに属します。対象範囲はソースプログラム全体です。
変数ストレージクラス
mtianyan: C 言語は変数のライフサイクルに従って分類されており、静的ストレージ モードと動的ストレージ モードに分けることができます。
-
静的ストレージ方式: プログラムの実行中に固定ストレージ領域を割り当てる方式を指します。グローバル変数など、プログラムの実行中に存在する変数は、静的記憶領域に格納されます。
-
動的ストレージ方式: プログラムの実行中に必要に応じてストレージスペースを動的に割り当てる方式を指します。動的記憶域に格納される変数は、プログラム動作の必要に応じて確立および解放され、通常は関数の仮パラメータ、自動変数、関数が呼び出されたときのフィールド保護および戻りアドレスなどが含まれます。
C 言語のストレージ クラスは、次の 4 つのカテゴリに分類されます。
-
自動(オート)、
-
静的、
-
登録する
-
外部(外部)。
1. キーワード auto で定義された変数は自動変数であり、auto は省略可能ですが、auto を記述しない場合は暗黙的に動的格納方式に属する「自動格納カテゴリ」に指定されます。のように:
2. static で変更された変数は静的変数であり、関数内で定義されている場合は静的ローカル変数、関数外で定義されている場合は静的外部変数と呼ばれます。以下は静的ローカル変数です。
注: 静的ローカル変数は静的ストレージ カテゴリに属します。ストレージ ユニットは静的ストレージ領域に割り当てられ、プログラムの実行中は解放されません。静的ローカル変数にはコンパイル時に初期値が割り当てられます。初期値は 1 回だけ割り当てられます; ローカル変数が定義されている場合 初期値がその時点で割り当てられていない場合、静的ローカル変数の場合は、初期値 0 (数値変数の場合) または null 文字 (文字変数の場合) が割り当てられます。コンパイル時に自動的に割り当てられます。
3. C言語では効率を上げるために、ローカル変数の値をCPU内のレジスタに入れることができますが、この変数を「レジスタ変数」と呼び、キーワードregisterで宣言します。例えば:
mtianyan: 注: レジスタ変数として使用できるのは、ローカル自動変数と仮パラメータのみです。コンピュータ システム内のレジスタの数は制限されており、任意の数のレジスタ変数を定義することはできません。ローカル静的変数はレジスタ変数として定義できません。
4. extern で宣言した変数は外部変数です 外部変数とは、関数の後に定義した変数を関数から呼び出すことができることを意味します。のように:
組み込み関数と外部関数
-
C言語では、他のソースファイルから呼び出すことができない関数を内部関数と呼びます。内部関数はstaticキーワードで定義されるため、静的関数とも呼ばれます。形式は static [データ型] 関数名([パラメータ
] ) -
ここでの静的とは関数のスコープの制限であり、関数はそれが配置されているソース ファイル内でのみ使用できるため、同じ関数名の内部関数が異なるファイルに存在しても問題はありません。
-
C 言語では、他のソースファイルから呼び出すことができる関数を外部関数と呼びます。外部関数は extern キーワードで定義され、 extern [データ型] 関数名 ([パラメータ]) の形式で定義されます
。 -
C 言語では、関数のスコープが指定されていない場合、システムはデフォルトでその関数を外部関数とみなすと規定しているため、外部関数を定義する必要がある場合は extern を省略することもできます。
静的変数は一度だけ割り当てられます
外部機能演習
こんにちはC
#include <stdio.h>
#include "test.c" //引用test.c文件
extern void printLine() //这里定义的方法对吗?
{
printf("**************\n");
}
int main()
{
say();
return 0;
}
test.c
#include <stdio.h>
void printLine();
static void say(){
printLine();
printf("I love imooc\n");
printf("good good study!\n");
printf("day day up!\n");
printLine();
}
hello.c の場合、test.c ファイルが直接導入されます。その後、test.c では導入されていない静的メソッド Say() を testc で呼び出すことができ
、宣言を通じて別のソース ファイルで公開されているメソッドを呼び出すことができます。
複合トレーニング
北京のタクシー料金規則は次のとおりです。
-
1キロあたりの単価は2.3元
-
初乗り料金は13元(3キロ含む)
-
タクシーご利用時間は、夕方23時(税込)~翌日朝5時(税別)までで、キロ単価の20%が加算されます。
-
燃油特別付加運賃は乗車ごとに1元かかります。
シャオミンさんは毎日、仕事の行き帰りにタクシーを利用しなければならず、会社と自宅の間の距離は 12 キロメートルです。
Xiao Ming の毎日のタクシー料金の合計を計算する小さなプログラムを作成してください。
#include <stdio.h>
float taxifee(int clock,int miles)
{
float money;
if(miles<=3)
{
money=14;
printf("费用为14\n");
}
else
{
if(clock>=23 || clock<5)
{
money=13+1+2.3*(miles-3)*1.2;
printf("夜间车费为:%f\n",money);
}
else
{
money=13+1+2.3*(miles-3);
printf("日间车费为:%f\n",money);
}
}
return money;
}
int main()
{
printf("打的总费用:%.1f\n",taxifee(9,12)+taxifee(18,12));
return 0;
}
アレイ初体験
プログラムにもコンテナが必要ですが、コンテナは少し特殊で、プログラム内で同じデータ型で固定サイズの連続したメモリ空間で、配列という素敵な名前が付いています。配列は固定サイズとして理解でき、配置されるアイテムは同じ種類のショッピング バッグであり、
ショッピング バッグ内のアイテムは特定の順序で配置されます。
配列を宣言する方法を見てみましょう。
数据类型 数组名称[长度];
配列を宣言するだけでは機能しません。配列がどのように初期化されるかを見てみましょう。初期化について言えば、C 言語には 3 つの形式の配列初期化があります。
-
データ型配列名[長さ n] = {要素 1, 要素 2...要素 n};
-
データ型配列名[] = {要素1, 要素2...要素n};
-
データ型 ArrayName[length n]; ArrayName[0] = 要素 1; ArrayName[1] = 要素 2; ArrayName[n-1] = 要素 n;
配列にデータを入れた後、配列内の要素を取得するにはどうすればよいでしょうか?
配列要素を取得する場合: 配列名 [要素に対応する添字];
例: 配列を初期化するには int arr[3] = {1,2,3};
、arr[0] が要素 1 になります。
知らせ:
-
配列の添字はすべて0 で始まります。
-
配列が初期化されるとき、配列内の要素の数は宣言された配列の長さを超えることはできません。
-
mtianyan: 最初の初期化方法が使用される場合、要素の数が配列の長さよりも小さい場合、冗長な配列要素は 0 に初期化されます。
-
宣言後に配列が初期化されていない場合、静的(static)型、外部(extern)型の配列要素の初期値は0となり、自動(auto)型の配列の要素の初期値は不定となります。 。
配列トラバーサル
配列は、指定された位置にある要素を毎回手動で取得するのではなく、循環的な方法で各要素を走査できます。たとえば、配列を走査するには for ループを使用します。
次の点に注意してください。
-
配列の境界外へのアクセスを避けるのが最善であり、ループ変数は配列の長さを超えてはなりません。
-
C 言語の配列長は一度宣言すると固定され変更できません。また、C 言語には配列長を計算する方法がありません。
C言語には配列の長さをチェックする仕組みがない、または配列が範囲外であるため、コンパイルしてエディタに渡すことはできますが、結果は不確かなので、範囲を超えないほうが良いですまたは配列の長さを変更します。
C言語で配列の長さを取得する
int length = sizeof(arr)/sizeof(arr[0]);
関数パラメータとしての配列
配列では、配列全体を関数パラメーターとして使用することも、配列内の要素を関数パラメーターとして使用することもできます。
-
配列全体が関数パラメータとして使用されます。つまり、配列名が関数に渡されます。次に例を示します。
配列内の要素は関数パラメータとして使用されます。つまり、配列内のパラメータは関数に渡されます。次に例を示します。
関数パラメータとして配列を使用する場合は、次の点に注意してください。
-
配列名が関数の引数として渡される場合、受け取りパラメーターとして関数定義の配列型パラメーターで長さを指定することも、長さを指定しないこともできます。
-
配列要素が関数の引数として渡される場合、配列要素の型は仮パラメータのデータ型と一致している必要があります。
mtianyan: 配列の応用 (1) [バブルソート]
昇順ソートを例に挙げると、バブルソートの考え方は、隣接する要素をペアごとに比較し、すべての数値がソートされるまで大きい数値を後ろに置くというものです。小学校で並ぶときと同じように、大きさごとに並び、クラスメイトを引っ張り出して後ろの人と比べます。
#include <stdio.h>
int main()
{
double arr[]={1.78, 1.77, 1.82, 1.79, 1.85, 1.75, 1.86, 1.77, 1.81, 1.80};
int i,j;
printf("\n************排队前*************\n");
for(i=0;i<10;i++)
{
if(i != 9)
printf("%1.2f, ", arr[i]); //%1.2f表示小数点前一位,小数点后精确到两位
else
printf("%1.2f", arr[i]); //%1.2f表示小数点前一位,小数点后精确到两位
}
for(i=8; i>=0; i--)
{
for(j=0;j<=i;j++)
{
if( arr[j]>arr[j+1]) //当前面的数比后面的数大时
{
double temp; //定义临时变量temp
temp=arr[j];//将前面的数赋值给temp
arr[j]=arr[j+1]; //前后之数颠倒位置
arr[j+1]=temp;//将较大的数放在后面
}
}
}
printf("\n************排队后*************\n");
for(i=0;i<10;i++)
{
if(i != 9)
printf("%1.2f, ", arr[i]); //%1.2f表示小数点前一位,小数点后精确到两位
else
printf("%1.2f", arr[i]); //%1.2f表示小数点前一位,小数点后精确到两位
}
return 0;
}
配列の応用(2) 【配列検索機能】
私たちは買い物に行き、買い物袋を持って帰るとき、買い物かごの中の商品を一つ一つ確認して、不足していないか、買いたいものはすべて揃っているかを確認します。
その後、プログラムに適用すると、配列検索関数を使用してデータが存在するかどうかを確認し、存在する場合は要素の添え字を返すことができます。
#include <stdio.h>
int getIndex(int arr[5],int value)
{
int i;
int index;
for(i=0;i<5;i++)
{
/* 请完善数组查询功能 */
if(arr[i]==value)
{
index=i;
break;
}
index=-1;
}
return index;
}
int main()
{
int arr[5]={3,12,9,8,6};
int value = 8;
int index = getIndex(arr,value); //这里应该传什么参数呢?
if(index!=-1)
{
printf("%d在数组中存在,下标为:%d\n",value,index);
}
else
{
printf("%d在数组中不存在。\n",value);
}
return 0;
}
文字列と配列
C 言語では、文字列データ型を直接定義する方法はありませんが、配列を使用して必要な文字列を定義できます。一般に、次の 2 つの形式があります。
-
文字列名[長さ] = "文字列値";
-
文字列名[長さ] = {'文字1','文字2',...,'文字n','\0'};
知らせ:
-
[]内の長さは省略可能です。
-
2 番目の方法を使用する場合、最後の要素は '\0' である必要があります。'\0' は文字列の終わりを意味します。
-
2 番目の方法を使用する場合、配列に中国語を書き込むことはできません。
文字列を出力する場合は、 :printf(“%s”,字符数组名字);
または; を使用しますputs(字符数组名字)
。
mtianyan: 文字列関数
一般的に使用される文字列関数は次のとおりです (strlen、strcmp、strcpy、strcat、atoi)。
文字列関数を使用する場合は、次の点に注意してください。
strlen() は文字列の長さを取得します。文字列の長さに「\0」は含まれません。また、漢字と文字の長さは異なります。例えば:
strcmp() は、文字列を ASCII コードに変換して比較します。返された結果は 0 で、s1 と s2 の ASCII コードが等しいことを意味します。返された結果は 1 で、s1 の ASCII コードが等しいことを意味します。返された結果は -1 で、s1 の ASCII コードが s2 の ASCII コードより小さいことを示します。次に例を示します。
strcpy() でコピーした後、元の文字列は上書きされ、文字列定数はコピーできません。次に例を示します。
strcat を使用する場合、s1 と s2 が指すメモリ空間は重複できません。また、s1 には、次のようなコピーされる文字列を収容するのに十分な空間が必要です。
多次元配列
多次元配列の定義形式は以下のとおりです。
データ型 配列名 [定数式1] [定数式2]...[定数式n];
num という名前とデータ型 int の 2 次元配列が定義されています。このうち、最初の[3]は、買い物の際にカテゴリに格納されるショッピングと同じように、1次元目の添え字の長さを示し、2番目の[3]は、2次元目の添え字の長さを示します。各ショッピング バッグ内の要素。
多次元配列の初期化は 1 次元配列の初期化と似ており、次の 2 つのタイプがあります。
-
データ型配列名 [定数式1] [定数式2]...[定数式n] = {{ value1,..,valuen},{value1,..,valuen},. ..,{value1,. .,値n}};
-
データ型 ARRAYNAME[CONSTEX1][CONSTEX2]...[CONSTEXn]; ARRAYNAME[SUB1][SUB2]...[SUBN] = 値;
多次元配列を初期化するときは、次の点に注意してください。
-
最初のタイプの初期化を使用する場合、配列宣言で列の次元を指定する必要があります。mtianyan: システムは配列内の要素の合計数に応じてスペースを割り当てるため、要素の合計数と列の次元がわかっている場合は、行の次元が直接計算されます。
-
2 番目のタイプの初期化を使用する場合、配列宣言で行と列の両方の次元を指定する必要があります。
2次元配列を定義する場合、行数は指定できませんが、列数は指定する必要があります。
2 次元配列を定義する場合、行数は指定できませんが、列数は指定する必要があります。
多次元配列の走査
多次元配列も走査用に存在し、1 次元配列の走査と同様にループも必要です。違いは、多次元配列では入れ子になったループを使用する必要があることです。
注: 多次元配列の各次元の添字は境界を超えることはできません。
複合トレーニング:
#include <stdio.h>
#define N 10
//打印分数
void printScore(int score[])
{
int i;
printf("\n");
for(i=0;i<N;i++)
{
printf("%d ",score[i]);
}
printf("\n");
}
//计算考试总分
int getTotalScore(int score[])
{
int sum = 0;
int i;
for(i=0;i<N;i++)
{
sum+=score[i];
}
return sum;
}
//计算平均分
int getAvgScore(int score[])
{
return getTotalScore(score)/N;
}
//计算最高分
int getMax(int score[])
{
int max = -1;
int i;
for(i=0;i<N;i++)
{
if(score[i]>max)
{
max = score[i];
}
}
return max;
}
//计算最低分
int getMin(int score[])
{
int min =100;
int i;
for(i=0;i<N;i++)
{
if(score[i]< min)
{
min = score[i];
}
}
return min;
}
//分数降序排序
void sort(int score[])
{
int i,j;
for(i=N-2;i>=0;i--)
{
for(j=0;j<=i;j++)
{
if(score[j]<score[j+1])
{
int temp;
temp = score[j];
score[j] = score[j+1];
score[j+1]=temp;
}
}
}
printScore(score);
}
int main()
{
int score[N]={67,98,75,63,82,79,81,91,66,84};
int sum,avg,max,min;
sum = getTotalScore(score);
avg = getAvgScore(score);
max = getMax(score);
min = getMin(score);
printf("总分是:%d\n",sum);
printf("平均分是:%d\n",avg);
printf("最高分是:%d\n",max);
printf("最低分是:%d\n",min);
printf("----------成绩排名---------\n");
sort(score);
return 0;
}