「C言語/制御文」の版間の差分
削除された内容 追加された内容
→発展的な話題: 直接構造体の配列を初期化すればよいし、いまは初期化リスト中で [2] = (struct product_list){ "野菜ジュース", 190 } の様に順位を指定した初期化も出来る。 タグ: 2017年版ソースエディター |
敬体に統一。 タグ: 2017年版ソースエディター |
||
2 行
== 条件分岐 ==
「
C言語では条件分岐の為に、選択文が用意されています。
21 行
たとえば、プログラムでは「もし変数aが4だったら、変数gには15を代入しなさい」は、
:<syntaxhighlight lang=
if (a == 4)
g = 15;
27 行
と記述します。
:<syntaxhighlight lang=
if (a == 4)
</syntaxhighlight>
34 行
if 文は条件式が 0 でなければ、続く文を実行し、0 であれば実行しません。
;if文の例:<syntaxhighlight lang=
#include <stdio.h>
55 行
もし、条件式を変更すると、・・・
:<syntaxhighlight lang=
#include <stdio.h>
78 行
=演算子は左辺に右辺を代入した後その値を返すため、右辺が0の場合は偽となり、右辺が0以外の場合は真となります。
コンパイルエラーとはなりませんが、予期しない結果を引き起こします<ref>clang や gcc であれば、コマンドラインオプション -Wparentheses で警告されるようになります。</ref>。
:<syntaxhighlight lang=
if (i = 0)
printf("iは0");
85 行
* 誤った;の付加
if文でよくある間違いの1つに、if文の後に誤った;を付加することがあ
:<syntaxhighlight lang=
if (i == 0);
printf("iは0");
93 行
==== if文の書式 ====
if文には次の2通りの形式があ
;if形式:<syntaxhighlight lang=
if ( 式 ) 文
</syntaxhighlight>
;if-else形式:<syntaxhighlight lang=
if ( 式 ) 文1 else 文2
</syntaxhighlight>
どちらの形式でも、文1は、式の比較が0に等しくない場合に実行されます。
if-else形式では、式の比較値が0に等しい場合、文2が実行され
; 制約事項
118 ⟶ 114行目:
if文もまた文であるため、上の2つの形式を組み合わせて次のように連続して記述することもできます。
:<syntaxhighlight lang=
if ( 式 )
文
else if ( 式 )
文
else if ( 式 )
文
else
文
133 ⟶ 128行目:
if文に限りませんが、文はブロック(複合文; ''Compound statement'' )であってもかまいません。
;if文の使用例:<syntaxhighlight lang=
#include <stdio.h>
153 ⟶ 148行目:
;まとめ
:if文とは、選択文の内の1つであり、式(制御式)の論理値に従って、指定する文(
:if文には、if形式、if-else形式の2通りの形式があり、またそれらを組み合わせてもよい。
Visual C/C++ では、scanf が「非推奨とマークされている関数」にあたり、設定によってはビルドに失敗します。⇒ [https://docs.microsoft.com/ja-jp/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4996?view=msvc-160 コンパイラの警告 (レベル 3) C4996]
これを回避するには、ソースコードに <syntaxhighlight lang=
ここでは scanfの境界検査インターフェース版のscanf_sを使った実装を紹介します<ref>逆に、BSDのlibcやglibcには scanf_s のような境界チェックインタフェース(C11 Annex K)は用意されていません。</ref>(scanf_sの3つめの引数 1は、記憶するデータの個数で、第1引数がスカラオブジェクトを指している場合、それは1要素の配列であるとみなされます。<ref name="jtc1-sc22-wg14-n1570-k.3.5.3.2">{{cite book
| url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
166 ⟶ 161行目:
| publisher = ISO/IEC}}</ref>なので第3引数の値は 1 です。<ref>過去の版で 10 とされていましたが、正しくは 1 です。</ref>)
;境界検査インターフェース版:<syntaxhighlight lang=
#include <stdio.h>
192 ⟶ 187行目:
を無効にします。
}}
<syntaxhighlight lang="C">▼
</syntaxhighlight>▼
<syntaxhighlight lang="C">▼
</syntaxhighlight>▼
==== if文のネスト ====
if文の中にif文を入れることを、ネストまたは入れ子という。
;if文のネストの使用例:<syntaxhighlight lang=
#include <stdio.h>
235 ⟶ 205行目:
}
</syntaxhighlight>
;if文のネストの使用例(境界チェックインタフェース版):<syntaxhighlight lang=
#include <stdio.h>
253 ⟶ 223行目:
なお、上の入れ子のifの例は &&演算子 を用いて、次のように簡潔に書き換えることができます。
;ネストしたif文を&&演算子で置き換え
#include <stdio.h>
274 ⟶ 244行目:
<code>strcmp</code> 関数は文字列どうしを比較して、一致したときに(1ではなく)0を返す標準ライブラリ関数です。
;コード例:<syntaxhighlight lang=
#include <stdio.h>
#include <string.h>
int main(void) {
const char a[
if (strcmp(a, "taro") == 0) {
} else {
▲ printf("太郎でない \n");
}
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
▲</syntaxhighlight>
;コード例:<syntaxhighlight lang="C" highlight="7,11" line>▼
</syntaxhighlight>▼
{{コラム|C言語では文字列は第一級オブジェクトではない|
323 ⟶ 272行目:
=== switch文 ===
==== 基本 ====
▲switch文とbreak 文とを使って、場合分け(複数個の「場合」のある場合)をできます。
たとえば
372 ⟶ 319行目:
例外的に現在実行中のcaseの下にある次のcaseを実行したい場合にだけ「fallthrough」というキーワードを付け加えるという仕組みをとっています(2022年10月時点のC言語には「fallthrough」キーワードはありません<ref name="fallthrough">C++には fallthrough というアトリビュートが有り、ISO/IEC/JTC1/SC22/WG/14 に [http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2408.pdf N2408 The fallthrough attribute]として提案され、C23に追加される予定です。</ref>)。
C言語を知りGo言語やSwift言語を学ぶ人は、switch文がディフォルトではフォールスルーしないことに気がつかづ混乱することがあ
[[Ruby]]ではこの混乱を避けるためswitch/case文ではなく、case/when(then)文を用意し転換教育がスムースに行われるよう配慮されています。
}}
385 ⟶ 332行目:
同一のswitch文のブロックの中に、同一の整数定数式の値を持つcaseラベルがあってはなりません。
switch文の記述は次のようになってい
*switch-case-...-default文
;形式:<syntaxhighlight lang=
switch (整数式) {
case 整数定数式:
文
break;
︙
default:
文;
400 ⟶ 345行目:
</syntaxhighlight>
;switch文の使用例:<syntaxhighlight lang=
#include <stdio.h>
424 ⟶ 369行目:
</syntaxhighlight>
== 繰
繰
| url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf
| title = N2596 working draft — December 11, 2020 ISO/IEC 9899:202x (E)
| page = 125, §6.8.5 ''Iteration statements''
| publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}}</ref>。
繰
ループ本体もまた、繰
繰
構文
448 ⟶ 393行目:
| page = 125, §6.8.5.1 ''The while statement''
| publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}}</ref>。
;形式:<syntaxhighlight lang="C">▼
while ( 式 )
文
</syntaxhighlight>
;while文の使用例:<syntaxhighlight lang=
#include <stdio.h>
469 ⟶ 407行目:
i++;
}
}
</syntaxhighlight>
0 1 2 3 4
▲</syntaxhighlight>
=== do-while文 ===
479 ⟶ 420行目:
| page = 125, §6.8.5.2 ''The do statement''
| publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}}</ref>。
do
文
492 ⟶ 427行目:
</syntaxhighlight>
;do文の使用例:<syntaxhighlight lang=
#include <stdio.h>
501 ⟶ 436行目:
i++;
} while (i < 5);
}
▲</syntaxhighlight>
0 1 2 3 4
</syntaxhighlight>
523 ⟶ 460行目:
: 省略された式-2は、非ゼロの定数によって置き換えます。
;[https://paiza.io/projects/1WZmT-1GXcpN9fJO1umqNw?language=c for文の使用例]:<syntaxhighlight lang=
#include <stdio.h>
537 ⟶ 474行目:
==== for文とスコープ ====
先の「for文の使用例」の変数 i のスコープは
:<syntaxhighlight lang=
for (int i = 0; i < 5; i++)
printf("%d ", i);
546 ⟶ 483行目:
==== for文のネスト ====
for文の中にfor文を入れることを、ネストまたは入れ子という。
;for文のネストの使用例。九九を表示します
#include <stdio.h>
566 ⟶ 503行目:
!while文!!do文!!for文
|-
|style="vertical-align:top"|<syntaxhighlight lang=
while (1)
文
</syntaxhighlight>
|style="vertical-align:top"|<syntaxhighlight lang=
do
文
while (1);
</syntaxhighlight>
|style="vertical-align:top"|<syntaxhighlight lang=
for (;;)
文
</syntaxhighlight>
|}
いずれのコードも、継続条件は常に非ゼロの整数(あるいは、非ゼロの整数とみなされ
無限ループを用いる場合、後述する break br文を用いるなどして適切にループから脱出できるようにする必要があります。
;無限ループを使った例:<syntaxhighlight lang=
#include <stdio.h>
606 ⟶ 543行目:
:※註 過去の版では、scanf の戻り値をチェックしていませんでしたが EOF を返す可能性があり、これを無視すると、それこそ'''無限ループ'''になってしまうので、戻り値も必ずチェックしましょう。また、この部分は return 文による脱出の例にもなっています。
;境界検査インターフェース版 無限ループ:<syntaxhighlight lang=
#include <stdio.h>
656 ⟶ 593行目:
goto文は、可変的に変更された型を持つ識別子のスコープ外から、その識別子のスコープ内にジャンプしてはなりません<ref name="jtc1-sc22-wg14-n2596-6.8.6.1"/>
;goto文の形式:<syntaxhighlight lang=
goto 識別子 ;
</syntaxhighlight>
;ラベル文の形式:<syntaxhighlight lang=
識別子 :
</syntaxhighlight>
;[https://paiza.io/projects/KhbOJ-86RYOk0V_up6nyjQ?language=c 例]:<syntaxhighlight lang=
#include <stdio.h>
690 ⟶ 627行目:
上の例であれば、
;return文を使いgoto文をなくした例:<syntaxhighlight lang=
#include <stdio.h>
718 ⟶ 655行目:
;コード例
:{|
|<syntaxhighlight lang=
while (/* ... */) {
/* ... */
726 ⟶ 663行目:
}
</syntaxhighlight>
|<syntaxhighlight lang=
do {
/* ... */
734 ⟶ 671行目:
} while (/* ... */);
</syntaxhighlight>
|<syntaxhighlight lang=
for (/* ... */) {
/* ... */
745 ⟶ 682行目:
:上のコード例での continue は、goto continと同等です<ref>2番目の例のcontin:ラベルに続くのは、NULL文です。1つ目と3つ目の例のnull文は、ラベルによって暗示されてます。</ref>。
;形式:<syntaxhighlight lang=
continue;
</syntaxhighlight>
;[https://paiza.io/projects/IM89XiUvAXhyRY6_KHv7hA?language=c continue文の使用例]:
:<syntaxhighlight lang=
#include <stdio.h>
int main(void) {
// 1から14までの整数の中で、3の倍数以外を表示します
for (int i = 1; i <= 14; i++) {
if (i % 3 == 0) {
787 ⟶ 724行目:
break文は、switch本体またはloop本体の中以外に現れてはいけません。
break文の記述は次のようになってい
;形式:<syntaxhighlight lang=
break;
</syntaxhighlight>
;例:<syntaxhighlight lang=
#include <stdio.h>
#include <math.h>
812 ⟶ 749行目:
=== for文の中のif文のbreak ===
<!--[[File:Destination Break Programming in If sentence in For sentence.svg|thumb|600px|break 文の移動先の説明図]]-->
<syntaxhighlight lang=
for (・・・) {
for (・・・) {
839 ⟶ 776行目:
式を持つreturn文は、戻り値の型がvoidである関数の中に現れてはなりません。式を伴わないreturn文は、戻り値の型がvoidである関数の中でのみ現れます<ref name="jtc1-sc22-wg14-n2596-6.8.6.4"/>。
;形式:<syntaxhighlight lang=
return 式;
</syntaxhighlight>
;[https://paiza.io/projects/-WEWEhXg14BxtL3A9tMsiA?language=c 例]:<syntaxhighlight lang=
#include <stdio.h>
849 ⟶ 786行目:
int main(void) {
int i = function(); //関数functionを呼び、返却値をiに代入します
printf("iの値は%d。", i);
}
858 ⟶ 795行目:
論理型とはデータ型の内の1つで、真(true)か偽(false)かの2種類の論理値をとります。
JISX3010:2003(ISO/IEC 9899:1999)において(いわゆる「C99」に相当のJIS)、論理型はキーワード_Boolを用いて宣言されます。
偽は0 , 真は1 (及び0以外) を用いて表現され
<ref>『JISX3010:2003』p.32「6.3.1.2 論理型」</ref>
|