[2] が正解。間違いやすいのは [6] でしょうか。
[2] [6]
[2] と [6] の違いは、[2] は条件のチェックを先に行うことです。
だから、その条件が満たされなければ、
実行文は 1 回も実行されない可能性もあります。
(while 文と do while 文の関係に似ています)。
目次へ
これは問題ありません。
これは問題があります。 実は、C 言語の文法的にはエラーではないのですが、 意図した動作にはなりません。 問題のコードだと、[実行文 1] のみが for 文の対象となってループになりますが、 [実行文 2]、[実行文 3] は、 その for 文が終わった後に 1 回ずつだけ実行されてしまいます。
これは問題ありません。 C 言語はフリーフォーマットですから、 改行を入れる、入れないは問題ありません。
改行が入っていないと for 文自体がどこまで書かれていて、 実行文がどこなのかが見にくいだろうということで、 多くの本では改行を入れて書くことが多いようですが、 書かなくても問題はありません。
実は私も、むしろ全体を見やすくするために、 短い for 文は改行を入れずに書くことが最近は結構あります。
これも問題ありません。
あまり詰まっていると区切りなどが見にくいだろうということで、 多くの本ではスペースを適当に入れて書くことが多いようです。
また、 「for は関数名ではないので、関数と区別するために for と ( の間にスペースを入れる」という流儀も割と使われています。
ただ、私は、むしろ全体を見やすくするために、 スペースをあまり入れずに (全然入れないわけではないですが) 書くことが最近は結構あります。
これも問題ありません。
特に for 文の条件等が長い場合は、エディタ画面を越える程長い行にする位なら、 適当な位置で改行する方が見やすいかもしれません。
ただ、[初期値] が長すぎる場合は、 例えば [初期値] の設定は for 文の前に書いてしまうとか、 [増分式] が長すぎる場合は、それを for 文ブロックの一番最後に書くとか、 単独の式として書くことで、長すぎる状態を回避することはできます。
問題ありません。無限ループ用に実際こういう式が使われることがあります。
これはエラーとなります。 for 文のカッコの中には ; で区切られた 3 つの部分が必要なので、 それぞれの部分がなくても、; は必要です。
これはエラーとなります。 丸かっこ ( ) でなければなりません。
(02/25 2011)
for 文を使わずに書くと以下のようになります:
printf("[%d]\n", 1);
printf("[%d]\n", 2);
printf("[%d]\n", 3);
もちろん、次も正解です。
int j;
j = 1;
printf("[%d]\n", j); j = 2;
printf("[%d]\n", j); j = 3;
printf("[%d]\n", j);
厳密に言えば、最も正しいのは以下のような感じでしょうか。
int j;
j = 1;
printf("[%d]\n",j); /* [1] */ j = j+1; /* j == 2 */
printf("[%d]\n",j); /* [2] */ j = j+1; /* j == 3 */
printf("[%d]\n",j); /* [3] */ j = j+1; /* j == 4 */
もちろん /* */ の部分 (C のコメント) は書かなくて結構です。
C 言語では「=」は等号ではなく「右辺の値を左辺に代入する」、
という意味ですので、「j = j+1;」は、
現在の j の値に 1 足した値をあらためて j に代入する、
つまり j の値を 1 増やすということを意味しています。
なお、これだと一番最後の「j = j+1;」は無駄になってますが、 for 文では実際にそれが行われています。
(02/25 2011; 02/28 2011, 04/20 2013 修正)for 文を使わずに書くと以下のようになります:
printf("[%d]\n", 4);
printf("[%d]\n", 5);
printf("[%d]\n", 6);
for 文が終わった後では longname の値は 7 になっています。
longname に対する式も書けば、これは、
「for 文の意味: その 3」の解答
と同様に、実際には
int longname;
longname = 4;
printf("[%d]\n", longname); longname ++; /* longname == 5 */
printf("[%d]\n", longname); longname ++; /* longname == 6 */
printf("[%d]\n", longname); longname ++; /* longname == 7 */
のようなことが行われています。
C 言語では 「longname ++;」は、「longname = longname+1;」とほぼ同じ意味で、
longname の値を 1 増やしています。
毎回 longname ++ が行われた後で条件の判定が行われていますが、
最後の longname ++ が行われた後の条件の判定で偽
(longname < 7 ではない) となるために for 文は終了しています。
よって、logname の値は 7 になるわけです。
(02/25 2011; 02/28 2011, 04/20 2013 修正)
まず、「k += 2」ですが、これは、「k = k+2」を意味しています。 C では「=」は代入なので、 これで k の値が 2 増やされる (2 足した値があらためて k に代入される) ことになります。 なお、for 文の「k += 2」は、 もちろん「k = k+2」と書いても構いませんし、全く同じ結果になります。
for 文を使わずに書くと以下のようになります:
printf("[%d]\n", 2);
printf("[%d]\n", 4);
printf("[%d]\n", 6);
printf("[%d]\n", 8);
k の式も入れて書けば、以下のようになります。
int k;
k = 2;
printf("[%d]\n", k); /* [2] */ k = k+2; /* k == 4 */
printf("[%d]\n", k); /* [4] */ k = k+2; /* k == 6 */
printf("[%d]\n", k); /* [6] */ k = k+2; /* k == 8 */
printf("[%d]\n", k); /* [8] */ k = k+2; /* k == 10 */
もちろん、「k = k+2」は「k += 2」と書いても結構です。
これを見てわかる通り、最後の k の値は 10 になっています。
k == 8 になったときは、まだ条件は真なので
[実行文] である printf() が実行されて、
k == 10 になって初めて条件が偽になるので、
[実行文] は実行されず for 文が終了します。
printf("[%d]\n", 2);
printf("[%d]\n", 4);
printf("[%d]\n", 6);
k の式も入れて書けば、以下のようになります。
int k;
k = 2;
printf("[%d]\n", k); k = k+2; /* k == 4 */
printf("[%d]\n", k); k = k+2; /* k == 6 */
printf("[%d]\n", k); k = k+2; /* k == 8 */
こちらは、k が 8 になった段階で条件が偽となるので、
そこで for 文が終了します。
(02/28 2011; 04/20 2013 修正)
まず、[a] と [b] ではループで使われている変数が k と j で違っていますが、 これは本質的な違いではなく、結果には影響しないことに注意しましょう。 「for 文の意味: その 5」の解答 で見たように、[a] は実際には
printf("[%d]\n", 2);
printf("[%d]\n", 4);
printf("[%d]\n", 6);
printf("[%d]\n", 8);
という作業を行っているだけで、
ループ変数が k であるか j であるかに特に意味はありません。
なお、k の式も入れて書けば、
int k;
k = 2;
printf("[%d]\n", k); k = k+2; /* k == 4 */
printf("[%d]\n", k); k = k+2; /* k == 6 */
printf("[%d]\n", k); k = k+2; /* k == 8 */
printf("[%d]\n", k); k = k+2; /* k == 10 */
となります。
[a] と [b] を比較すると、[b] の方は、for 文の [初期値] 部分がありません。 [初期値] 部分は、for 文の中で最も最初に実行される部分ですから、 これを別な場所に移動するとしたら、上を見てわかる通り、 最初の printf() が起こなわれるより前の部分に書かなければいけません。 よって (ア) か (イ) でそれを行うことになりますが、 (イ) に書いてしまうと、それは for 文の最初の [実行文] と見なされて、 毎回実行されてしまうことになります。
しかし、[初期値] 部分は最初の 1 回だけやればいいので、 for 文の実行文である { } よりも前の部分、 すなわち for 文自体の前の部分である (ア) に書くのが正解です。
よって「(ア) に『j=2;』と書く」が正解です。 [b] ではループ変数は j ですから、「k=2;」は間違いです。
ちなみに、(イ) に「j=2;」と書いてしまって
int j;
for ( ; j<=8; j=j+2) {
j=2;
printf("[%d]\n", j);
}
とすると、以下のようなことが行われてしまいます。
int j;
j = 2; printf("[%d]\n", j); /* [2] */
j = j+2; /* j == 4 */
j = 2; printf("[%d]\n", j); /* [2] */
j = j+2; /* j == 4 */
j = 2; printf("[%d]\n", j); /* [2] */
j = j+2; /* j == 4 */
j = 2; printf("[%d]\n", j); /* [2] */
j = j+2; /* j == 4 */
...
せっかく [増分式] で j を 2 増やしたのに、
最初の [実行文] である「j = 2;」でまた
j に 2 が代入されてしまって値が戻ってしまうことになります。
しかもこの場合、[条件] 部分では毎回「j=4 に対して j<=8 の判定」
が行われてしまうので、この条件は毎回真となり、
よってこの for 文はいつになっても終わらず、
無限ループとなってしまいます
(実行したプログラムが止まらなくなる)。
(02/28 2011; 04/20 2013 修正)
for 文も n も使わずに書くと以下のようになります:
printf("[%d]\n", 0); /* n == 0 */
printf("[%d]\n", 1); /* n == 0 */
printf("[%d]\n", 2); /* n == 2 */
printf("[%d]\n", 3); /* n == 2 */
printf("[%d]\n", 4); /* n == 4 */
printf("[%d]\n", 5); /* n == 4 */
なお、これが終わった後では n は 6 になっています。
(03/10 2011; 04/20 2013 修正)
for 文も x も使わずに書くと以下のようになります:
int y;
y = 0;
y = y+1;
y = y+2;
y = y+3;
y = y+4;
printf("[%d]\n", y);
見てわかる通り、
これは 1 から 4 までを加えた結果を表示するものになっています。
printf() の文も (わざと) インデントをつけて書きましたが、 実際には for 文の外にあるので、 最後に 1 回だけしか行われないことに注意してください。
(03/10 2011; 04/20 2013 修正)for 文も x も使わずに書くと以下のようになります:
int Total = 1;
Total *= 5;
Total *= 4;
Total *= 3;
Total *= 2;
Total *= 1;
printf("[%d]\n", Total);
「Total *= 5;」は「Total = Total * 5;」と同じことを意味します。
よって、これは、
int Total = 1;
Total = 1*5;
Total = 1*5*4;
Total = 1*5*4*3;
Total = 1*5*4*3*2;
Total = 1*5*4*3*2*1;
printf("[%d]\n", Total);
となり、結局1 から 5 までをかけた結果を表示するものになっています。
for 文のループ変数である x の値は最初が 5 で、 実行するたびに x-- (x=x-1 と同じ) によって 1 つずつ小さくなります。 そして「x>0」でなくなった時点、 すなわち「x=0」になったら終わり、ということになります。
(03/10 2011; 04/20 2013 修正)for 文は使わず、p, q, N を残して書くと以下のようになります:
int p, q, N;
N = 0;
p = 1; /* 初期値 */
q = 5; /* 初期値 */
N += p*q;
p++; /* p == 2 */
q--; /* q == 4 */
N += p*q;
p++; /* p == 3 */
q--; /* q == 3 */
N += p*q;
p++; /* p == 4 */
q--; /* q == 2 */
N += p*q;
p++; /* p == 5 */
q--; /* q == 1 */
N += p*q;
printf("[%d]\n", N);
, (カンマ演算子) で複数の式を並べると、
左から順にそれが実行されますので、
初期値に , で区切って書いた式は、左から順に一つずつ実行されます。
増分式に , で区切って書いた式も、各実行文が終わった後に
左から順に一つずつ実行されます。
つまり、この問題の場合は初期値の設定部分で 2 本の式が実行され、 各実行文が終わった後に 2 本の増分式が実行されるわけです。
(03/10 2011; 04/20 2013 修正)(ア) に「q=5;」、(ウ) に「q--;」と書いて以下のようにするのが正解です。
int p, q, N;
N = 0;
q = 5;
for (p=1; p<=5; p++) {
N += p*q;
q--;
}
printf("[%d]\n", N);
q の初期値の設定である「q=5;」の式は、
最初に 1 度だけ行えばいいので、for 文の前である (ア) に書きます。
一方、増分式の「q--;」は、 元々の for 文では実行文が終わった段階で行われるものですから、 実行文の 2 本目として (ウ) に書くのが正解です。
なお、厳密に言えば、元の式は「q--;」の前に「p++;」が行われますが、 (ウ) に「q--;」と書いた場合は、「q--;」の後に「p++;」が行われる、 という違いがありますが、 この問題の場合には結果に違いはありません。
(03/10 2011)
「j = 1, 3, 5, 7, 9」が正解。j = 11 になった時点で終了します。
「j = 3, 4」が正解。j = 5 のときは 2*j は 10 になって 「2*j < 10」を満たしませんので終了します。
「j = 1, 2, 3, 4」が正解。
「j % 5」 は「j を 5 で割った余り」を意味しますので、 「j % 5 != 0」は「j を 5 で割った余りが 0 でない」ことを意味し、 よって「j が 5 で割りきれない」ことを意味しますので、 j = 5 のときに条件を満たさなくなります。
「j = 0, 2, 4, 6, 8」が正解。
「j += 2」なので、j は 0, 2, 4, ... と偶数をたどります。 j+4 はその 2 つ先の偶数で、「(j+4) % 7 != 0」、 つまり「j+4 が 7 で割りきれない」は j+4 が 14 になったら 満たされなくなります。 よって、j = 10 のときにこの for 文が終了します。
なお、この条件は少し難しいので、わかりにくければ、 上のように意味を考察するよりも 実際に最初の j を代入して (j+4)%7 の値が何になるかを考えてみるといいかもしれません。
といった具合です。
少しインチキに思うかもしれませんが、「実行されない」が正解です。
これは最初の j = 1 のときから条件 「j < 1」が満たされません。 よって、一度も実行文が実行されずに終了します。 for 文の条件チェックは、 実行文が実行される前に行われることに注意してください。
(03/14 2011)
元の for 文の「for (j=1; j<=10; j++)
」は、
j=1,2,3,...,10 (10 個) の j に対して行うもので、
求める for 文の「for (k=0; k<10; k++)
」は、
k=0,1,2,...,9 (10 個) の k に対して行うものですから、
繰り返しの数は合っていますが、ひとつずれています。
よって、とりあえず k = j - 1
、すなわち j = k + 1
と考えるのが一番楽でしょう。
そうすれば代入文は、
a[(k + 1) - 1] = 2 * (k + 1) + 1;
となるので、これを展開すれば、結局
int k, a[10];
for (k=0; k<10; k++)
a[k] = 2 * k + 3;
が一つの答えとなります。
(04/28 2013)
元の for 文の「for (j=1; j<=10; j++)
」は、
j=1,2,3,...,10 (10 個) の j に対して行うもので、
求める for 文の「for (m=10; m>0; m--)
」は、
m=10,9,8,...,1 (10 個) の m に対して行うものですから、
繰り返しの数は合っていますが、反対向きになっています。
これは 2 通りの考え方があるでしょう。
m = 11 - j
、すなわち j = 11 - m
と考えて対応させる
この場合は、j = 11 - m
をそのまま実行文に代入すれば、
a[(11 - m) - 1] = 2 * (11 - m) + 1;
となるので、これを展開すれば、結局
int m, a[10];
for (m=10; m>0; m--)
a[10 - m] = 23 - 2 * m;
が一つの答えとなります。もちろん、右辺を展開せずに
「2 * (11 - m) + 1;
」のままにする解答もあるでしょう。
j = m
と対応させる
m の進み方は j とは逆順なのですが、動く値の集合に違いはありません。
この for 文の実行文では、繰り返しの実行の順番を逆にしても
結果に影響はありませんので、
よって実行文では j = m
と見てもいいわけです。
ということで、
int m, a[10];
for (m=10; m>0; m--)
a[m - 1] = 2 * m + 1;
も一つの解となります。
ただし、後者の考え方は、実行順が結果に影響を及ぼすような for 文、 例えば、
int j, a[11];
a[0] = 1;
for (j=1; j<=10; j++)
a[j] = 2 * a[j - 1]; /* 一つ前のものの 2 倍を代入 */
のようなものには使えません。
その場合は、前者のように考えるしかありません。
(04/28 2013)
解のひとつは以下の通り:
int j;
for (j=1; j<=5; j++)
printf("3× %d = %d\n", j, 3*j);
{ } で実行文をくくって、
int j;
for (j=1; j<=5; j++) {
printf("3× %d = %d\n", j, 3*j);
}
としても間違いではありませんし、「5 以下」という条件を「6 未満」にして、
int j;
for (j=1; j<6; j++)
printf("3× %d = %d\n", j, 3*j);
としてもいいでしょう。無理矢理ですが、j の初期値を 0 にして、
int j;
for (j=0; j<=4; j++)
printf("3× %d = %d\n", j+1, 3*(j+1));
でも一応間違いではないです。
ただ、最初のが多分一番自然でしょう。
(03/14 2011)
解のひとつは以下の通り:
int j;
for (j=1; j<=5; j++)
printf("5× %d = %d\n", 2*j-1, 5*(2*j-1));
繰り返し文は 5 本で、
1,3,5,7,9 という奇数列は 2*j-1 という式によって作り出すことができます。
ただし、下のように 2*j-1 を一度別な変数に代入する方が見易いかもしれません:
int j, k;
for (j=1; j<=5; j++) {
k = 2*j - 1;
printf("5× %d = %d\n", k, 5*k);
}
これらの方法は、カウンタ変数 j の値をひとつずつ増やしているために
そこから奇数列を作らないといけなくなっているのですが、
実は以下のようなもう少し自然な解があります:
int k;
for (k=1; k<=9; k+=2)
printf("5× %d = %d\n", k, 5*k);
1,3,5,7,9 は 2 ずつ値が増えるので、
増分式で 2 つずつ増やせばいいわけです。
数列の言葉で言えば「初期値が 1 で公差 2 の等差数列」となります。
この方法の場合は、終了条件も最後の奇数を指定すればいいだけですが、 終了条件として「5 本」を使いたければ、 j と k を組み合わせた以下のような解もあります:
int j, k;
for (j=1, k=1; j<=5; j++, k+=2)
printf("5× %d = %d\n", k, 5*k);
初期値の部分と増分式にそれぞれ j と k の設定が入っていますから、
最初は (j, k) = (1, 1)、後は順に (j, k) = (2, 3), (3, 5), (4, 7), ...
のように j は 1 ずつ、k は 2 ずつ増えていくことになります。
どれが一番いい、というのは難しいと思いますが、 多分 2 番目か 3 番目のものが自然な解でしょう。
(03/14 2011)このような和は、最初に x = 0 としておいて、 for 文で次々に x に値を追加していけばいいわけです。 例えば以下の通り。
int x, y, j;
double z;
x = 0; y = 0; z = 0.0
for (j=1; j<=100; j++) {
x += j;
y += j * j;
}
for (j=1; j<100; j+=2)
z += 1.0/j;
printf("x = %d, y = %d, z = %f\n", x, y, z);
x, y は同じ 100 項の和なので 1 つの for 文に入れてあります。
「x += j」は「x = x + j」と同じで、j の値を x に追加する文です。
「y += j * j」は、「+=」よりも「*」の方が優先順位が高いので、
「(y += j) * j」ではなく、「y += (j * j)」のように計算されます。
また、「z += 1.0/j」は、分子を 1 にしてしまうと、 j が整数変数のため「1/j」は整数の割り算となり、 その値は j = 1 のとき以外は 0 になってしまいます。 分子を 1.0 にすることで、実数の割り算とみなされ、 正しい分数の値が追加されます。
なお、z の for 文は、
for (j=1; j<50; j++)
z += 1.0/(2 * j - 1);
でも結構です (が、上の方が多分わかりやすい)。
(04/28 2013)
添え字 j に対する一般項を書けば、
a[j] = j + 1, b[j] = 2 * j + 1
なので、これを for 文にすればいいでしょう。
int j, a[50], b[50];
for (j=0; j<50; j++) {
a[j] = j + 1;
b[j] = 2 * j + 1;
}
(04/28 2013)
添字が偶数しか使いませんが、 この場合例えば以下のような 2 つの考え方があります。
添字を 2 * j として、j = 1, 2, ..., 50 とする、という手ですが、 この場合一般項は
a[2 * j] = j
となるので、結局以下のようにすればいいわけです。
int j, a[101];
for (j=1; j<=50; j++)
a[2 * j] = j;
添字を j として、2 ずつこれを増やして j = 2, 4, 6, ..., 100 とする手ですが、 この場合一般項は
a[j] = j/2
となりますから、以下の通りです。
int j, a[101];
for (j=2; j<=100; j+=2)
a[j] = j/2;
なお、この場合は右辺に代入するものを別な変数にして、
int j, k, a[101];
for (j=2, k=1; j<=100; j+=2, k++)
a[j] = k;
とする方がわかりやすいかもしれません。
この配列を数式で表せば、
a[j] = 100-2*j (j=0,1,...,49)となりますから、一番簡単な解は以下のものでしょう。
int j, a[50];
for (j=0; j<50; j++)
a[j] = 100 - 2*j;
かけ算を避ける解として、以下のようなものも考えられます。
int j, k, a[50];
for (j=0, k=100; j<50; j++, k-=2)
a[j] = k;
for 文のかっこ内には j だけを書くのであれば、以下のようになります。
int j, k, a[50];
k=100;
for (j=0; j<50; j++) {
a[j] = k;
k -= 2;
}
前者の k を用いない方法よりも、
多分後者の方が考えやすいだろうと思います。
(04/20 2013)
他にも解はあるでしょうが、この配列を数式で表せば、例えば
a[j] = (-1)j = cos(j*π)などのように表せます。 ただし、累乗も三角関数も実数演算なので誤差も出ますし、 計算も遅い (遅さが気になるのはよほどの場合だけですが) ので、 直接これらを数式にして代入するのは得ではありません。
一番簡単な解は、(-1) をかけ続ける方法でしょうか。
int j, k, a[50];
for (j=0, k=1; j<50; j++, k*=-1)
a[j] = k;
k を for のかっこから出せば、
int j, k, a[50];
k = 1;
for (j=0; j<50; j++) {
a[j] = k;
k *= -1;
}
この問題のように、交互に入れ替わる場合には、
2 での剰余を利用する方法もあります。詳しくは、
「for 文にする: その 8」の解答
を参照してください。
(04/20 2013)
この配列を数式で表せば、 「for 文にする: その 7」の解答 の式を利用して、
a[j] = {1-(-1)j}/2 = {1-cos(j*π)}/2などのように表せるのですが、 「for 文にする: その 7」の解答 と同様、あまりいい式ではありません。
実は C 言語には剰余演算がありますので、もっと簡単に
a[j] = j % 2と書くことができますから、
int j, a[50];
for (j=0; j<50; j++)
a[j] = j % 2;
とするのが一番簡単です。
b[j] の方は「一つずれる」と考える、あるいは 1 との反転と考える、 などにより、
b[j] = (j + 1) % 2 = 1 - j % 2のような式が作れますので、
int j, b[50];
for (j=0; j<50; j++)
b[j] = (j + 1) % 2;
か、
int j, b[50];
for (j=0; j<50; j++)
b[j] = 1 - j % 2;
などとなります。
この問題のように、 値が交互に入れ替わる場合には 2 の剰余を利用すると k を用いなくてもできます。例えば、 「for 文にする: その 7」 の問題も、 この a[ ] を 2 倍して 1 から引けばできます:
int j, a[50];
for (j=0; j<50; j++)
a[j] = 1 - 2 * (j % 2);
(04/20 2013)
これには、いくつかの解が考えられます。
奇数番目と偶数番目で規則が違うので、それを別にやる、 という方法があります。
int j, k, a[50];
for (j=0, k=1; j<50; j+=2, k++)
a[j] = k; /* 偶数番目 */
for (j=1, k=1; j<50; j+=2, k++)
a[j] = k; /* 奇数番目 */
これをまとめて、2 つずつやる、という方法もあるでしょう。
int j, k, a[50];
for (j=0, k=1; j<50; k++) { /* j は実行部分で増やす */
a[j] = k;
j ++;
a[j] = k;
j ++;
}
なお、「a[j++] = k;」と書けば
「a[j] = k; j ++;」と書いたのと同じことになりますから、これは、
int j, k, a[50];
for (j=0, k=1; j<50; k++) {
a[j ++] = k;
a[j ++] = k;
}
と書くこともできます。
0.5 ずつ増やして整数部分だけ考える、という手もあります。 ただしその場合、0.5 ずつ増やす値を、 実数変数として保存する必要があります。
int j, a[50];
float x;
for (j=0, x=1.0; j<50; j++, x+=0.5)
a[j] = x;
float 変数を int 変数に代入するときに、
小数以下は切り捨てられるので、一応これでうまくいきます。
ただ、実数から整数に切り捨てられたときに、
誤差のせいで一つ前の整数に戻ってしまうかもしれません。
それを避けるために、x の初期値を 1.1 や 1.01 くらいにする、
という手もあります。
なお、明示的に int 値に変換するためにキャスト演算子を使って
「a[j] = (int) x;」と書く方がいいかもしれません。
「for 文にする: その 8」の解答 のように 2 での剰余を利用する方法もあります。 偶数の j に対しては、a[j] の値から 1 を引くと 0, 1, 2, 3, のように j/2 になりますから、
a[j] = j/2 + 1奇数番目はそれを一つずらして
a[j] = (j - 1)/2 + 1と書けるので、両者をまとめて
a[j] = (j - (j % 2))/2 + 1と書くことができます。よって、
int j, a[50];
for (j=0; j<50; j++)
a[j] = (j - j % 2)/2 + 1;
が一つの解となります。なお、% と - は % の方が優先順位は上なので、
このように内側のかっこは省略できます。
しかし、ここまでしなくても、 整数の割り算は小数以下の値が無視されます (切り捨てられる) ので、 実はすべての j に対して
a[j] = j/2 + 1で十分です。よって、
int j, a[50];
for (j=0; j<50; j++)
a[j] = j / 2 + 1;
で実は OK です。
2., 5. の解あたりがシンプルでしょうか。 if 文を使えばもっと他の解も出てくると思います。
(04/20 2013)文字 '0' は、実際には文字「0」を意味する ASCII コード (= 48) の整数値を表しています。 '0' から '9' までは、この '0' (= 48) から順に 48,49,...,57 のように並んでいて、 ヒントとして書いたように「'3' = '0' + 3」のようにして表すことができます。 よって、以下のようになります。
int j;
char a[11];
for (j=0; j<=9; j++)
a[j] = '0' + j;
a[10] = '\0';
最後の a[10] の設定だけは for ループに入れていませんが、
if 文を使えば以下のようにすれば for ループの中に入れることもできます:
int j;
char a[11];
for (j=0; j<=10; j++) {
if (j <= 9) a[j] = '0' + j;
else a[j] = '\0';
}
しかし、これは、for 文の中で無駄な if 文を 10 回繰り返すことになりますから、
前者のように、規則的な部分だけを for 文で行い、
「規則的ではない」一回を for 文の外に出す方がいいでしょう。
(04/26 2013)
これは、基本的には「b[j] = a[j + 1]」の繰り返しを行うだけです。 ただし、最後の j == 49 だけはその規則に当てはまらないので、 for 文の外に出せばいいです。
int j;
int a[50], b[50];
/* まずは a[ ] に適当なものを設定 */
for (j=0; j<50; j++)
a[j] = 2 * j;
/* 次に b[ ] に設定 */
for (j=0; j<49; j++)
b[j] = a[j + 1];
b[49] = a[0];
if 文を使うか剰余を使えば、
一応最後のものを for ループの中に入れることもできます:
for (j=0; j<=49; j++) {
if (j < 49) b[j] = a[j + 1];
else b[j] = a[0];
}
for (j=0; j<=49; j++)
b[j] = a[(j + 1) % 50];
「(j + 1) % 50」 は j = 0 から 48 までは j + 1、j = 49 では 0 になります。
しかし、これらはいずれの場合も for 文の中で最後の一回以外は無駄な if 文、無駄な剰余計算を 繰り返すことになりますから、 前者のように、規則的な部分だけを for 文で行い、 「規則的ではない」一回を for 文の外に出す方がいいでしょう。
(04/26 2013)