「C言語/制御文」の版間の差分

削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
→‎分岐文: cleanup
タグ: 2017年版ソースエディター
Ef3 (トーク | 投稿記録)
タグ: 2017年版ソースエディター
1 行
== 条件分岐 ==
「もし明日が晴れだったら、出かけよう。晴れでなかったら、出かけないでいよう。」のように、何かの条件によって処理が分かれることを条件分岐といいます。
 
C言語では条件分岐の為に、選択文( ''Selection statements'' )が用意されています。
 
=== if文 ===
==== 具体例 ====
if文( ''if statement'' )は、もっと単純な選択文です。
「もし明日が晴れだったら、出かけよう。晴れでなかったら、出かけないでいよう。」のように、何かの条件が満たされたどうかで結果が変わることを条件分岐という。
 
C言語では条件分岐には、if文(イフぶん)を用いる。ifは「イフ」と読みます。if(イフ)とは日本語の「もしも ~ ならば」の意味です。
 
たとえば、プログラムでは「もし変数aが4だったら、変数gには15を代入しなさい」は、
<syntaxhighlight lang="C">
if (a == 4)
g = 15;
</syntaxhighlight>
のように記述されるします
 
C言語では、「もし変数aが4だったら、変数gには15を代入しなさい。」のように、条件分岐は関数文として扱われる。
 
条件が満たされる場合のことを'''真'''(しん)という。条件が満たされない場合のことを'''偽'''(ぎ)という。
 
<syntaxhighlight lang="C">
if (a == 4)
</syntaxhighlight>
 
と書かれた場合、もしaが <var>4</var> なら条件が満たされているで、「真」である。もし値は 1,<var>a</var> 74でら、条件が満たされてないの、「偽」ば0ある
if 文は条件式が 0 でなけでば、続く文を実行し、0 であれば実行しません。
 
;if文の例:<syntaxhighlight lang="C">
 
<syntaxhighlight lang="C">
#include <stdio.h>
 
int main(void) {
int a = 4;
{
printf("aは%dです。\n", a);
int a = 4;
if (a == 4) {
int g = 15;
printf("aは4である。\n");
printf("gは%dです。\n", g);
int g = 15;
}
printf("gは%dである。\n",g);
}
return 0;
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="text">
aは4です。
gは15です。
</syntaxhighlight>
このように、if文の条件式(上記のプログラムの場合は <code>a==4</code>)が満たされるときには中カッコ{}の内容が実行されます。
 
なお、条件式を書くときの等号は、<code>==</code>になります。条件式における等号は、<code>=</code>ではありません(C言語では、ひとつだけのイコール記号<code>=</code>は演算子です。)。
;実行結果
aは4である。
gは15である。
 
 
このように、if文の条件式(上記のプログラムの場合は <code>a==4</code>)が満たされるときには中カッコ{}の内部が実行される。
 
なお、条件式を書くときの等号は、<code>==</code>になる。条件式における等号は、<code>=</code>ではない。(C言語では、ひとつだけのイコール記号<code>=</code>は代入記号の意味である。)
 
 
もし、条件式を変更すると、・・・
 
<syntaxhighlight lang="C">
#include <stdio.h>
 
int main(void) {
int a = 6;
{
printf("aは%dです。\n", a);
int a=4;
if (a ==6 4) {
int g = 15;
printf("aは4である。\n");
printf("gは%dです。\n", g);
int g=15;
printf("gは%dである。\n",g);
}
 
return 0;
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="text">
 
aは6です。
;実行結果
</syntaxhighlight>
なにも表示されずに終了する。条件式が偽なので、if文の{}内部を実行しない。
if文の外の文は実行されますが、if文の内側は実行されません。
 
 
==== よくある間違い ====
* ==演算子と=演算子の誤用
if文でよくある間違いの1つに、
==演算子の代わりに=演算子を誤って用いることがあります
=演算子は左辺に右辺を代入した後その値を返すため、右辺が0の場合は偽となり、右辺が0以外の場合は真となります。
コンパイルエラーとはなりませんが、予期しない結果を引き起こします<ref>clang や gcc であれば、コマンドラインオプション -Wparentheses で警告されるようになります。</ref>。
右辺が0の場合は偽となり、右辺が0以外の場合は真となる。
コンパイルエラーとはならないが、予期しない結果を引き起こす。
<syntaxhighlight lang="C">
if (i = 0)
printf("iは0");
</syntaxhighlight>
上の例では、式「i=0」の評価結果はiの値によらず偽となってprintf関数の文は常に実行されません。
上の例では、
式「i=0」の評価結果はiの値によらず偽であり、
printf関数の文は常に実行されない。
 
* 誤った;の付加
if文でよくある間違いの1つに、if文の後に誤った;を付加することがある。
if文の後に誤った;を付加することがある。
<syntaxhighlight lang="C">
if (i == 0);
printf("iは0");
</syntaxhighlight>
上の例では、if文の式が真の時に実行される文がなく、printf関数の文は常に実行されます<ref>clang では、コマンドラインオプション -Wempty-body で警告されるようになります。</ref>。
上の例では、
if文の式が真の時に実行される文がなく、
printf関数の文は常に実行される。
 
 
==== if文の書式 ====
if文には次の2通りの形式がある。
* if形式
 
;if形式:<syntaxhighlight lang="C">
if ( )
</syntaxhighlight>
;if-else形式:<syntaxhighlight lang="C">
 
if形式では、条件式が真の場合には文を実行し、
偽の場合には文を実行せずif文の次の文に制御を移す。
 
* if-else形式
 
<syntaxhighlight lang="C">
if (式)
1
else
2
</syntaxhighlight>
どちらの形式でも、文1は、式の比較が0に等しくない場合に実行されます。
if-else形式では、式の比較値が0に等しい場合、文2が実行される。
 
; 制約事項
if-else形式では、制御式の論理値が真の場合は最初の文だけを実行し、
: if文の制御式は、スカラー型でなければなりません。
偽の場合は2番目の文だけを実行する。
; スカラ型
ラベルを通して最初の文に制御が到達した場合、2番目の文は実行しない。
: 算術演算型とポインタ型の総称
: アグリゲート型
: 配列型と構造体型の総称
 
* 懸垂if
elseだけを単独で使用しようとても、コンパイル時にエラーになる。elseの単独利用は出来ない。
if文もまた文であるため、上の2つの形式を組み合わせて次のように連続して記述することもできます。
 
elseは、必ずその直前にif文をともなう。
 
* if-else if-...-else形式
上の2つの形式を組み合わせて次のように連続して記述することもできる。
 
<syntaxhighlight lang="C">
if (式)
else if (式)
else if (式)
.
.
.
.
else
</syntaxhighlight>
elseは、構文で許可されている場合、字句的に最も近い先行詞と関連付けられます。
 
if文に限りませんが、文はブロック(複合文; ''Compound statement'' )であってもかまいません。
elseは上の2つの形式で許されるifのうち、そのelseの前で最も近い位置にあるifと対応する。
;if文の使用例:<syntaxhighlight lang="C">
#include <stdio.h>
 
int main(void) {
なおif文に限らないが、一般に文はブロックであってもかまわない。
printf("数値を入力してください。:\n");
<syntaxhighlight lang="C">
int i;
//例 if文の使用例
scanf("%d", &i);
#include<stdio.h>
if (i == 0)
 
printf("入力値は0\n");
int main(void)
else if (i == 1)
{
printf("数値を入力してください。:値は1\n");
else
int i;
printf("入力値は0,1以外\n");
scanf("%d", &i);
if(i==0)
printf("入力値は0\n");
else if(i==1)
printf("入力値は1\n");
else
printf("入力値は0,1以外\n");
}
</syntaxhighlight>
 
;まとめ
if文とは、選択文の内の1つであり、式(制御式)の論理値に従って、指定する文(副文)を実行するかどうか選択する。
:if文とは、選択文の内の1つであり、式(制御式)の論理値に従って、指定する文(副文)を実行するかどうか選択します。
if文には、if形式、if-else形式の2通りの形式があり、またそれらを組み合わせてもよい。
:if文には、if形式、if-else形式の2通りの形式があり、またそれらを組み合わせてもよい。
 
なお、WindowsのVisual C++系のコンパイラではscanfが使うことが出来ず<ref>MSVCでscanfどの非推奨とマークされている関数を使いたい場合、#pragma warning(disable : 4996)をソースコードの非推奨とマークされている関数を使う前に書ことで使うことが出来ます。</ref>、上記のコードのままではエラーになるので、かわりにscanf_sという関数を使用します<ref>逆に、BSDのlibcやglibcには scanf_s のような境界チェックインタフェース(C11 Annex K)は用意されていません。</ref>
 
<syntaxhighlight lang="c">
195 ⟶ 170行目:
: [ツール] -> [オプション] -> [デバッグ] -> [デバッグの停止時に自動的にコンソールを閉じる]
を無効にします。
}}<!--
* 参考文献サイト
:Yahoo知恵袋『c言語実行画面がすぐ消えてしまう 僕はvisual stu』 [https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13159333633] 2018年7月2日に閲覧
 
(※ ウィンドウズのVisual C では、コード実行終了後にウィンドウがすぐ消えてしまうのが標準設定になっている。なので<code>system("pause")</code>などを使う必要がある。これは標準入出力には入ってないので、<code>#include <stdlib.h></code>でインクルードしないといけない。)
-->
==== if文の書き換え ====
if文は、0が偽、0以外が真であることを用いて、次のように簡潔に書き換えることができます
<syntaxhighlight lang="C">
if (i != 0)
213 ⟶ 184行目:
</syntaxhighlight>
 
C99では、stdbool.h が導入され上記のコードは次の様に書くことができます
<syntaxhighlight lang="C">
#incude <stdbool.h>
228 ⟶ 199行目:
==== if文のネスト ====
if文の中にif文を入れることを、ネストまたは入れ子という。
;if文のネストの使用例:<syntaxhighlight lang="C">
//例 if文のネストの使用例
#include <stdio.h>
 
int main(void) {
printf("数値を入力してください。:");
{
int i;
printf("数値を入力してください。:");
scanf("%d", &i);
int i;
scanf if ("%d",0 <= &i);
if (0i <= i10)
printf("入力値は0以上10以下");
if(i <= 10)
printf("入力値は0以上10以下");
}
</syntaxhighlight>
;if文のネストの使用例(境界チェックインタフェース版):<syntaxhighlight lang="c">
 
WindowsのVisual C系コンパイラでは、scanfが利用できないので上記のコードはエラーになり利用できません。Visual C では、代わりに scanf_s という関数を使用します。
 
<syntaxhighlight lang="c">
//例 if文のネストの使用例
// Visual C 用
#include <stdio.h>
 
261 ⟶ 225行目:
</syntaxhighlight>
 
なお、上の(非Visual C系のコードの)例は &&演算子 を用いて、次のように簡潔に書き換えることができます
 
;if文で&&演算子を用いる。:<syntaxhighlight lang="C">
// 例 if文で&&演算子を用いる。
#include <stdio.h>
 
int main(void) {
printf("数値を入力してください。:");
{
int i;
printf("数値を入力してください。:");
scanf("%d", &i);
int i;
if (0 <= i && i <= 10)
scanf("%d", &i);
printf("入力値は0以上10以下");
if(0 <= i && i <= 10)
printf("入力値は0以上10以下");
}
</syntaxhighlight>
279 ⟶ 241行目:
 
==== if文での文字列の比較 ====
C言語のif文で、ある文字列変数が、指定する文字列に等しいかどうかを判定するには、<code>==</code> ではなく、<code>strcmp</code>を使う。
strcmpを使うために <code>#include <string.h></code> で string.h をインクルードします。
<code>strcmp</code> 関数は文字列どうしを比較して、一致したときに(1ではなく)0を返す標準ライブラリ関数です。
 
;コード例:<syntaxhighlight lang="C" highlight="7,11" line>
<code>==</code> ではなく、<code>strcmp</code>をつかわなければいけない。
#include <stdio.h>
なお、strcmpを使うためには <code>#include <string.h></code> で string.h をインクルード(導入)する必要がある(しないとエラーになる)。
#include <string.h>
 
int main(void) {
なお <code>strcmp</code> 関数は文字列どうしを比較して、一致したときに(1ではなく)0を返す組み込み関数である。
char a[30] = "taro";
 
if (strcmp(a, "taro") == 0) {
printf("太郎だった \n");
}
 
if (strcmp(a, "taro") != 0) {
;コード例
printf("太郎でない \n");
<syntaxhighlight lang="C">
}
#include <stdio.h>
#include <string.h>
 
int main(void)
{
char a[30]="taro";
if( strcmp(a, "taro") == 0){
printf("太郎だった \n");
}
if( strcmp(a, "taro") != 0){
printf("太郎でない \n");
}
}
</syntaxhighlight>
 
 
;実行結果
太郎だった
 
 
下記のようなにも書ける。
----
;コード例:<syntaxhighlight lang="C" highlight="7,11" line>
下記のようなコードでも書ける。
 
;コード例
<syntaxhighlight lang="C">
#include <stdio.h>
#include <string.h>
 
int main(void) {
char a[30] = "taro";
{
 
char a[30] = "taro";
if (!strcmp(a, "taro")) {
printf("太郎だった \n");
if( !strcmp(a, "taro") ){
}
printf("太郎だった \n");
 
}
if (!!strcmp(a, "taro")) {
printf("太郎でない \n");
if( ! !strcmp(a, "taro") ){
}
printf("太郎でない \n");
}
}
 
</syntaxhighlight>
 
;実行結果
太郎だった
 
{{コラム|C言語では文字列は第一級オブジェクトではない|
 
C言語では、Fortran のように配列全体のコピー(=配列の代入)や四則演算はできません。
* 備考
このことを以って、配列はC言語の[[W:第一級オブジェクト|第一級オブジェクト]]ではないと言われます。
JavaScriptなど他のプログラム言語では文字列の比較の際に <code>==</code> を使えるものもあるが、しかしC言語はそうなっていないので、混同しないようにしよう。(よくやるミスで、C言語なのに文字列の比較で <code>==</code> を使ってバグになる。 )
文字列も文字の配列(に番兵として '\0' で終端したもの)なので、配列と同様に文字列も第一級オブジェクトではありません。
<!-- C言語の書籍で、市販の入門書では、あまりstrcmpについて書かれてないですが、しかしJavaScriptなど近代的な言語では文字列どうしの比較が出来て当然なので、対応のため本wikiでも入門レベルの単元で strcmp を紹介します。 -->
文字列の代入や比較、結合には <string.h> で定義された、標準ライブラリ関数<ref>過去の編集で、標準ライブラリ関数を誤って組み込み関数と表記していましたが、C言語に組み込み関数はありません。</ref>を使う必要があります。
 
}}
なお、C言語のif文などの論理式で、文字列の比較で <code>==</code> を使っても、コンパイラはエラーを返さないので、注意しよう。コンパイルされるが、意図した通りの動作になっていないので、初心者だとバグの発見が遅れやすい。
 
 
文字列の比較にかぎらず、C言語では、文字列の処理はやや特殊であり、<code>=</code> や <code>==</code> などのイコール記号が使えないか、使えたとしても初心者の意図する動作にならない。
 
文字列の取扱に関しては、C言語では str○○ のような名称の組み込み関数がいくつか用意されているので、C言語での文字列処理では、str○○ などの組み込み関数を使う必要がある。
 
=== switch文 ===
369 ⟶ 310行目:
 
(イメージ)
switch(a) {
case 1: 文m1 ; break ;
case 2: 文m2 ; break ;
378 ⟶ 319行目:
のような記法になります。
 
まず、実行したい関数の前に、それぞれcaseという文でラベルをつけます。
 
パソコンがswitch文に遭遇したときに、どのcaseに移動するかを決めます。
 
「case」ってのは、単に移動先を示している目印です。
 
switch文に遭遇したときに、どのcaseに移動するかを決めます。
 
C言語の仕組みとして、もしbreakがないとそのまま次の文を実行します。
389 ⟶ 327行目:
つまり、
 
switch {
:case 1: 文m1 ;
:case 2: 文m2 ;
398 ⟶ 336行目:
というコードなら、もしa=2なら、実行されるのは、文m2だけでなく、さらに文m3や文m4も実行してしまいます。
 
このような仕組み(つまりbreak文がないかぎり、次の関数を実行してしまう)のことを'''フォールスルー'''( ''fall through'' ) と呼びます。
 
{{コラム|フォールスルー|
ほかのプログラム言語では、switch文においてフォールスルーが廃止されている場合もあります。
たとえばグーグルの開発した「Go言語」というプログラム言語では、原則的にフォールスルーは行わないようになっています。
例外的に現在実行中のcaseの下にある次のcaseを実行したい場合にだけ「fallthrough」というキーワードを付け加えるという仕組みをとっています(もちろん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)文を用意し転換教育がスムースに行われるよう配慮されています。
}}
 
switch文とは、選択文の内の1つであり、整数式(制御式)の値に従って、指定するいくつかの文からいずれかを実行するかどうか選択します。
単に、昔のC言語の開発者が、こういう仕組みで作ったままのものが、いまだに残っているだけです。
switch文には、制御式と、ブロック(スイッチ本体)の中に、任意の個数のcaseラベルと、高々1つのdefaultラベルが含まれます。
switch文は、制御式の値と等しい整数定数式の値を持つcaseラベルへ制御を移します。
等しい値を持つcaseラベルがなければ、defaultラベルへ制御を移します。
defaultラベルもなければ、ブロックの次の文に制御を移します。
 
break文はswitchブロックの次の文に制御を移します。
ですから、ほかのプログラム言語では、switch文においてフォールスルー的な動作が廃止されている場合もあります。たとえばグーグルの開発した「Go言語」というプログラム言語では、原則的にフォールスルーは行わないようになっており、例外的に現在実行中のcaseの下にある次のcaseを実行したい場合にだけ「fallthrough」というキーワードを付け加えるという仕組みです。(もちろんC言語には「fallthrough」キーワードはない。)
同一のswitch文のブロックの中に、同一の整数定数式の値を持つcaseラベルがあってはなりません。
 
C言語を知りGo言語やSwift言語を学ぶ人は、switch分がディフォルトではフォールスルーしないことに気がつかづ混乱することがある。Rubyではこの混乱を避けるためswitch/case文ではなく、case/when(then)文を用意し転換教育がスムースに行われるよう配慮した。
 
ともかく、C言語のフォールスルーを原則とする仕組みは、単なるローカル・ルールですので、悩む必要はありません。
 
 
また、このフォールスルーの動作からも分かるように、C言語における「case」は、単に移動先を示しているだけの目印です。単なるラベルです。caseの動作実態は「case」という名前とは違って、case文だけでは条件分岐をしてくれません。
 
:※ 単なる「ラベル」と言うが、そもそも「ラベル」とは何かというと、じつはアセンブリ言語に「ラベル」という機能があって、そのアセンブリ言語の「ラベル」機能がこういう機能(アセンブリ言語の「ジャンプ」命令(というのがある)の移動先の目印になるのが「ラベル」機能)なのである。
 
さて、C言語における case 処理では、 break文などを補うことにより、適切な条件分岐を プログラマーが構築する必要があります。
 
 
switch文とは、選択文の内の1つであり、整数式(制御式)の値に従って、指定するいくつかの文からいずれかを実行するかどうか選択する。
switch文には、制御式と、ブロック(スイッチ本体)の中に、任意の個数のcaseラベルと、高々1つのdefaultラベルが含まれる。
switch文は、制御式の値と等しい整数定数式の値を持つcaseラベルへ制御を移す。
等しい値を持つcaseラベルがなければ、defaultラベルへ制御を移す。
defaultラベルもなければ、ブロックの次の文に制御を移す。
 
break文はswitchブロックの次の文に制御を移す。
同一のswitch文のブロックの中に、同一の整数定数式の値を持つcaseラベルがあってはならない。
 
switch文の記述は次のようになっている。
*switch-case-...-default文
;形式:<syntaxhighlight lang="C">
switch (整数式) {
case 整数定数式:
443 ⟶ 371行目:
</syntaxhighlight>
 
;switch文の使用例:<syntaxhighlight lang="C">
#include <stdio.h>
 
int main(void) {
break文の書き忘れに注意してください。なお、あえてbreak文を書かなくてもよく、その場合をフォールスルーと呼びます。
printf("一桁の数値を入力してください。:");
 
int i;
<syntaxhighlight lang="C">
scanf("%d", &i);
//例 switch文の使用例
switch (i) {
#include<stdio.h>
case 2:
 
case 3:
int main(void)
case 5:
{
case 7:
printf("一桁の数値を入力してください。:");
printf("入力値は一桁の素数\n");
int i;
break;
scanf("%d", &i);
default:
switch (i){
printf("入力値は一桁の素数ではない\n");
case 2:
break;
case 3:
}
case 5:
case 7:
printf("入力値は一桁の素数\n");
break;
default:
printf("入力値は一桁の素数ではない\n");
break;
}
}
</syntaxhighlight>
 
 
==== 発展的な話題 ====
for文などとswtich文とを組み合わせて、配列の順位ごとの初期化する例。番号ごとに代入できます。
switchの場合わけに使った変数を、それぞれのcase内で利用する事もできる。
 
;[https://paiza.io/projects/p6-CS51SWQ9La0qaZlI0ig?language=c for文との組み合わせ使用例]:<syntaxhighlight lang="C">
この変数をcase内でも使うことで、たとえば下記のようにfor文などとswtich文とを組み合わせて、配列の番号ごとに代入などを出来る。
 
 
;コード例
<syntaxhighlight lang="C">
//例 switch文の使用例
#include <stdio.h>
#include <string.h> // strcpy を使うので忘れないように
 
int main(void) {
// 商品リスト
struct product_list {
char name[32]; // 商品名
int price; // 価格
};
 
struct product_list drinks[10]; // 構造体配列の宣言
// 商品リスト
struct syouhin_list {
char syouhinmei[32]; // 商品名
int kakaku; // 価格
};
 
for (int i = 0; i <= 2; i = i + 1) {
struct syouhin_list nomimono[10]; // 構造体配列の宣言
switch (i) {
 
forcase (int0: drinks[i] = 0;(struct iproduct_list){ <="牛乳", 2120 }; i = i + 1) { break;
case 1: drinks[i] = (struct product_list){ "オレンジジュース", 240 }; break;
 
case 2: drinks[i] = (struct product_list){ "野菜ジュース", 190 }; break;
switch (i) {
default : case 0:break;
strcpy(nomimono[i].syouhinmei, "牛乳");
nomimono[i].kakaku = 120;
break;
case 1:
strcpy(nomimono[i].syouhinmei, "オレンジジュース");
nomimono[i].kakaku = 240;
break;
case 2:
nomimono[i].kakaku = 190;
strcpy(nomimono[i].syouhinmei, "野菜ジュース");
break;
}
}
}
 
for (int temp = 0; temp <= 2; temp = temp + 1) {
printf("商品『%s』の値段は%d 円\n", nomimonodrinks[temp].syouhinmeiname, drinks[temp].price);
}
nomimono[temp].kakaku);
}
}
</syntaxhighlight>
;実行例:<pre>
 
 
実行例
<pre>
商品『牛乳』の値段は120 円
商品『オレンジジュース』の値段は240 円
525 ⟶ 427行目:
</pre>
 
上記のコードでは、構造体(こうぞうたい; ''structure''というものを使っている。構造体について詳しくは『[[C言語/構造体・共用体]]』で習う
{{See also|C言語/構造体・共用体}}
 
上記コードでは、forで0,1,2を巡回しているので、すべてのcaseが実行される事になります
 
 
このようにわざわざswitch文を使って代入する事のメリットは、配列の順番を入れ替えたい場合、たとえば「野菜ジュース」と「オレンジジュース」の順番を入れ替えたい場合に、コピーペーストでコードをそのまま移動すれば終わるという長所がある。
 
いっぽう、もし配列に数字を直接入れてしまうと、たとえば
:<syntaxhighlight lang="C">
strcpy(nomimono[2].syouhinmei, "野菜ジュース");
drinks[2] = (struct product_list){ "野菜ジュース", 190 };
</syntaxhighlight>
のように、配列番号2番などとコードを入れ替えてしまうと、順番を入れ替える際に、番号を書き直す手間が発生してしまう。
 
 
上記コード例では、個々の番号のデータを名称と価格の2種類だけのデータなので、まだ入れ替えの作業数は少ないが、もし、もっとデータ種類の多いデータを扱っている場合だと、直接代入の方式のコードだと、入れ替えの負担が膨大になってしまい、事実上は入れ替えが不可能になりかねない。
 
なので、switch文などを使って、入れ替えなどの編集しやすくする事で、長所がある<ref>構造体は第一級オブジェクトであることを利用し、複合リテラルを使った代入にリファクタリングしたので有り難みが薄れてしまいましたが、元は
:<syntaxhighlight lang="C">
case 2:
nomimono[i].kakaku = 190;
strcpy(nomimono[i].syouhinmei, "野菜ジュース");
break;
</syntaxhighlight>の様に構造体配列の要素の要素を1つ1つ埋めていたので保守性に問題が有りました。
<!--
:<syntaxhighlight lang="C">
struct product_list drinks[] = {
{ "牛乳", 120 },
{ "オレンジジュース", 240 };
{ "野菜ジュース", 190 },
};
for (int i = 0; i < sizeof drinks / sizeof drinks[0]; i++) {
/* ... */
}
-->
</syntaxhighlight>
</ref>。
 
== 繰り返し文 ==