変数iについて。iはどこにあるのか?
勉強中さん
(No.1)
初歩的なことで申し訳ないですが質問です。
科目Bの設問の中で、「変数iを⚪︎まで1ずつ増やす」とあるにも関わらず、
その後の関数の中にiが登場しないのはなぜでしょうか?
iは見えないだけでどこかに隠れていますか?
例えば、新年度サンプル問題の問10などです。
関数の中でどの部分をiとして1ずつ増やしていっていいかよくわかりません。。。
〔プログラム〕
大域: ListElement: listHead // リストの先頭要素が格納されている
○delNode(整数型: pos) /* posは,リストの要素数以下の正の整数 */
ListElement: prev
整数型: i
if (pos が 1 と等しい)
listHead ← listHead.next
else
prev ← listHead /* posが2と等しいときは繰返し処理を実行しない */
for (i を 2 から pos - 1 まで 1 ずつ増やす)
prev ← prev.next
endfor
prev.next ←⬜︎
endif
科目Bの設問の中で、「変数iを⚪︎まで1ずつ増やす」とあるにも関わらず、
その後の関数の中にiが登場しないのはなぜでしょうか?
iは見えないだけでどこかに隠れていますか?
例えば、新年度サンプル問題の問10などです。
関数の中でどの部分をiとして1ずつ増やしていっていいかよくわかりません。。。
〔プログラム〕
大域: ListElement: listHead // リストの先頭要素が格納されている
○delNode(整数型: pos) /* posは,リストの要素数以下の正の整数 */
ListElement: prev
整数型: i
if (pos が 1 と等しい)
listHead ← listHead.next
else
prev ← listHead /* posが2と等しいときは繰返し処理を実行しない */
for (i を 2 から pos - 1 まで 1 ずつ増やす)
prev ← prev.next
endfor
prev.next ←⬜︎
endif
2025.05.24 10:30
jjon-comさん
★FE プラチナマイスター
(No.2)
例として、"実行中"と 10 回 印字する次のプログラムを挙げます。
for (i を 1 から 10 まで 1 ずつ増やす)
"実行中"と印字する
endfor
印字するのは"実行中"という文字であり、
1,2,3,4,5,6,7,8,9,10 という文字を印字する必要はありません。
変数 i は現在の繰返し回数を一時記憶しておくカウンタとしてだけ用意したので、
for と endfor に挟まれた繰り返し処理内に i は登場しません。
同様に、次の問題でも。
サンプル問題 科目B 問10 delNode()
https://www.fe-siken.com/kakomon/sample/b10.html
繰り返し処理内では i の値を参照しません。
for (i を 1 から 10 まで 1 ずつ増やす)
"実行中"と印字する
endfor
印字するのは"実行中"という文字であり、
1,2,3,4,5,6,7,8,9,10 という文字を印字する必要はありません。
変数 i は現在の繰返し回数を一時記憶しておくカウンタとしてだけ用意したので、
for と endfor に挟まれた繰り返し処理内に i は登場しません。
同様に、次の問題でも。
サンプル問題 科目B 問10 delNode()
https://www.fe-siken.com/kakomon/sample/b10.html
/* pos が 2 と等しいときは繰返し処理を実行しない */
for (i を 2 から pos-1 まで 1 ずつ増やす)
prev ← prev.next
endfor
prev ← prev.next の繰返し回数を決めるカウンタとして i を用意しています。for (i を 2 から pos-1 まで 1 ずつ増やす)
prev ← prev.next
endfor
繰り返し処理内では i の値を参照しません。
2025.05.24 11:27
ゆるふわさん
(No.3)
これは、for文の性質として「適当な変数を定義し、変数が特定の値になるまで変数を更新する」という指示をしなくてはならないからです。
例えば、c++だと、3回繰り返すときに for (int i = 0; i < 3; i++) と書きます。3回繰り返したいだけでも、「iを0から始めて1ずつ増やし、3未満のときにだけ実行する」という指示をしなければなりません。
なので、iをfor文の中で使わないときは for (int _ = 0; _ < 3; _++) などとアンダースコアを用いることもあります。
例えば、c++だと、3回繰り返すときに for (int i = 0; i < 3; i++) と書きます。3回繰り返したいだけでも、「iを0から始めて1ずつ増やし、3未満のときにだけ実行する」という指示をしなければなりません。
なので、iをfor文の中で使わないときは for (int _ = 0; _ < 3; _++) などとアンダースコアを用いることもあります。
2025.05.24 11:32
勉強中さん
(No.4)
jjon-comさん
教えていただきありがとうございます!
繰り返し回数のカウンターだと考えると腑に落ちるのですが、
それなら問題の中のfor (i を 2 から pos-1 まで 1 ずつ増やす)が、
なぜ2からスタートするのかよくわからないです。
もし設問をpos=3で考えた場合、繰り返す回数は
for (i を 2 から pos-1 まで 1 ずつ増やす)→2から2(3−1)まで
つまり、1回だけ処理をする(繰り返す)と解釈しました。
それならfor (i を 1から pos-2 まで 1 ずつ増やす)としてもいいのでしょうか?
教えていただきありがとうございます!
繰り返し回数のカウンターだと考えると腑に落ちるのですが、
それなら問題の中のfor (i を 2 から pos-1 まで 1 ずつ増やす)が、
なぜ2からスタートするのかよくわからないです。
もし設問をpos=3で考えた場合、繰り返す回数は
for (i を 2 から pos-1 まで 1 ずつ増やす)→2から2(3−1)まで
つまり、1回だけ処理をする(繰り返す)と解釈しました。
それならfor (i を 1から pos-2 まで 1 ずつ増やす)としてもいいのでしょうか?
2025.05.24 16:05
勉強中さん
(No.5)
ゆるふわさん
教えていただきありがとうございます!
for文に初期値と条件式と変化式があることは理解しておりましたが、処理の中にその変数がないのがなんかしっくりこなくて・・・
もし変数iがあれば、それを変化させて、条件式がFalseになるまで繰り返す。
変数iがなければiは単に繰り返す回数をカウントするためと認識すればよいですか?
C++は、_の有無によってiをどのように捉えたらいいか区別されているということでしたら、すごくわかりやすいと思いました。
何か的外れなことを言っていたらすみません。
教えていただきありがとうございます!
for文に初期値と条件式と変化式があることは理解しておりましたが、処理の中にその変数がないのがなんかしっくりこなくて・・・
もし変数iがあれば、それを変化させて、条件式がFalseになるまで繰り返す。
変数iがなければiは単に繰り返す回数をカウントするためと認識すればよいですか?
C++は、_の有無によってiをどのように捉えたらいいか区別されているということでしたら、すごくわかりやすいと思いました。
何か的外れなことを言っていたらすみません。
2025.05.24 16:18
ゆるふわさん
(No.6)
勉強中さん
はい!その通りです。iが出てこなければカウントするためだけだと捉えて問題ないと思います。
全然的外れではないですよ!
はい!その通りです。iが出てこなければカウントするためだけだと捉えて問題ないと思います。
全然的外れではないですよ!
2025.05.24 17:30
jjon-comさん
★FE プラチナマイスター
(No.7)
> pos=3で考えた場合、繰り返す回数は
> 2から2(3−1)まで
> つまり、1回だけ処理をする(繰り返す)と解釈しました。
はい、それで正しいです。
> それならfor (i を 1から pos-2 まで 1 ずつ増やす)としてもいいのでしょうか?
はい、大丈夫です。
for (i を 1 から pos-2 まで 1 ずつ増やす)
for (i を 2 から pos-1 まで 1 ずつ増やす)
for (i を 3 から pos まで 1 ずつ増やす)
for (i を 4 から pos+1 まで 1 ずつ増やす)
for (i を 5 から pos+2 まで 1 ずつ増やす)
……
等々、どの書き方をしようがプログラムは正しく動作します。
2025.05.24 20:00
jjon-comさん
★FE プラチナマイスター
(No.8)
この投稿は投稿者により削除されました。(2025.05.24 20:02)
2025.05.24 20:02
jjon-comさん
★FE プラチナマイスター
(No.9)
この投稿は投稿者により削除されました。(2025.05.24 20:07)
2025.05.24 20:07
jjon-comさん
★FE プラチナマイスター
(No.10)
(二度、投稿し直したけれど、図の文字位置のずれが修正できませんでした)
どの書き方をしても正しく動作するのなら、
その状況をもっとも適切に表している書き方を採用すべきだ、
という出題者が判断したということでしょう。
delNode(pos) は、指定した位置(POSition)のリスト要素(NODE)を削除(DELete)する手続きです。
念のため、質問者は、次の点は理解していらっしゃいますね?
単方向リストにおける要素の削除は、削除したい要素の変更ではなく、
「削除したい要素の直前(PREVious)の要素のnextポインタの変更」で実現する。
サンプル問題 科目B 問10 delNode()
https://www.fe-siken.com/kakomon/sample/b10.html
の単方向リストを次のように図示することにします。
まず、pos=1、つまり、要素1の削除を実現するには、
下図の★の値を■に代入すればいい。
続いて、pos=2、つまり、要素2の削除を実現するには、
下図の★の値を■に代入すればいい。
そして、削除対象が要素3以降の場合です。図示がたいへんなので文で示します。
要素3を削除する場合は、
prev を要素2の位置から、要素2の位置(削除対象の要素3の直前)まで移動する。
要素4を削除する場合は、
prev を要素2の位置から、要素3の位置(削除対象の要素4の直前)まで移動する。
要素5を削除する場合は、
prev を要素2の位置から、要素4の位置(削除対象の要素5の直前)まで移動する。
要素6を削除する場合は、
prev を要素2の位置から、要素5の位置(削除対象の要素6の直前)まで移動する。
つまり、prev を 2 の位置から posー1 の位置まで移動させています。
これをもっとも適切に表している書き方が
for (i を 2 から pos-1 まで 1 ずつ増やす)
だと出題者は判断したわけです。
> なぜ2からスタートするのかよくわからないです。
どの書き方をしても正しく動作するのなら、
その状況をもっとも適切に表している書き方を採用すべきだ、
という出題者が判断したということでしょう。
delNode(pos) は、指定した位置(POSition)のリスト要素(NODE)を削除(DELete)する手続きです。
念のため、質問者は、次の点は理解していらっしゃいますね?
単方向リストにおける要素の削除は、削除したい要素の変更ではなく、
「削除したい要素の直前(PREVious)の要素のnextポインタの変更」で実現する。
サンプル問題 科目B 問10 delNode()
https://www.fe-siken.com/kakomon/sample/b10.html
の単方向リストを次のように図示することにします。
listHead=10 /* リストの先頭要素の参照があらかじめ格納されている */
↓
10 20 30 40
+―――+―+ +―――+―+ +―――+―+ +―――+―+
|要素1|20|→|要素2|30|→|要素3|40|→|要素4|略|
+―――+―+ +―――+―+ +―――+―+ +―――+―+
↓
10 20 30 40
+―――+―+ +―――+―+ +―――+―+ +―――+―+
|要素1|20|→|要素2|30|→|要素3|40|→|要素4|略|
+―――+―+ +―――+―+ +―――+―+ +―――+―+
まず、pos=1、つまり、要素1の削除を実現するには、
下図の★の値を■に代入すればいい。
listHead=■
↓
10 20 30 40
+―――+―+ +―――+―+ +―――+―+ +―――+―+
|要素1|★|→|要素2|30|→|要素3|40|→|要素4|略|
+―――+―+ +―――+―+ +―――+―+ +―――+―+
これは、擬似言語では次のコードになります。↓
10 20 30 40
+―――+―+ +―――+―+ +―――+―+ +―――+―+
|要素1|★|→|要素2|30|→|要素3|40|→|要素4|略|
+―――+―+ +―――+―+ +―――+―+ +―――+―+
if (pos が 1 と等しい)
listHead■ ← listHead.next★ /* この実行でlistHead=10になる */
listHead■ ← listHead.next★ /* この実行でlistHead=10になる */
続いて、pos=2、つまり、要素2の削除を実現するには、
下図の★の値を■に代入すればいい。
listHead=10
↓
10 20 30 40
+―――+―+ +―――+―+ +―――+―+ +―――+―+
|要素1|■|→|要素2|★|→|要素3|40|→|要素4|略|
+―――+―+ +―――+―+ +―――+―+ +―――+―+
これは、擬似言語では次のコードになります。↓
10 20 30 40
+―――+―+ +―――+―+ +―――+―+ +―――+―+
|要素1|■|→|要素2|★|→|要素3|40|→|要素4|略|
+―――+―+ +―――+―+ +―――+―+ +―――+―+
prev ← listHead
/* pos が 2 と等しいときは繰返し処理を実行しない */
prev.next■ ← prev.next.next★【カ】
このとき、prev は要素1を指しています(削除対象の要素2の直前)。/* pos が 2 と等しいときは繰返し処理を実行しない */
prev.next■ ← prev.next.next★【カ】
そして、削除対象が要素3以降の場合です。図示がたいへんなので文で示します。
要素3を削除する場合は、
prev を要素2の位置から、要素2の位置(削除対象の要素3の直前)まで移動する。
要素4を削除する場合は、
prev を要素2の位置から、要素3の位置(削除対象の要素4の直前)まで移動する。
要素5を削除する場合は、
prev を要素2の位置から、要素4の位置(削除対象の要素5の直前)まで移動する。
要素6を削除する場合は、
prev を要素2の位置から、要素5の位置(削除対象の要素6の直前)まで移動する。
つまり、prev を 2 の位置から posー1 の位置まで移動させています。
これをもっとも適切に表している書き方が
for (i を 2 から pos-1 まで 1 ずつ増やす)
だと出題者は判断したわけです。
2025.05.24 20:09
jjon-comさん
★FE プラチナマイスター
(No.11)
> 要素3を削除する場合は、
> prev を要素2の位置から、要素2の位置(削除対象の要素3の直前)まで移動する。(No.10)
ごめんなさい、この説明は正しくないですね。
ループ前の時点で、prevが10を指しているから、prev.nextが20を指している。
ここでループ内を1回実行すると、prevが20を指す。prev ← prev.next
となりますから、
要素3を削除する場合は、
prev を【(ループ前の)要素1】の位置から、要素2の位置(削除対象の要素3の直前)まで【1回】移動する。
という説明が正しいです。
これを for (i を 1 から pos-1 まで 1 ずつ増やす) と表記してしまうと2回のループになってしまうので、ループカウンタの初期値を 2 に変更して帳尻を合わせているのだと思います。
2025.05.24 23:19
勉強中さん
(No.12)
jjon-comさん
単方向リストの考え方については理解しているつもりでしたが、記載していただいた図と「削除したい要素の直前(PREVious)の要素のnextポインタの変更」という表現でより解像度が上がりました。
「posー1」という表現だと「消したい要素の1個前」というのがイメージしやすいですが、
for (i を 1 から pos-2 まで 1 ずつ増やす)とかだと訳わからなくなりますよね。
その帳尻合わせのために初期値を2としているということですね!
大変丁寧に教えていただきありがとうございました。
よく理解できました。
単方向リストの考え方については理解しているつもりでしたが、記載していただいた図と「削除したい要素の直前(PREVious)の要素のnextポインタの変更」という表現でより解像度が上がりました。
「posー1」という表現だと「消したい要素の1個前」というのがイメージしやすいですが、
for (i を 1 から pos-2 まで 1 ずつ増やす)とかだと訳わからなくなりますよね。
その帳尻合わせのために初期値を2としているということですね!
大変丁寧に教えていただきありがとうございました。
よく理解できました。
2025.05.25 08:58
広告
返信投稿用フォーム
スパム防止のためにスレッド作成日から40日経過したスレッドへの投稿はできません。
広告