2017年5月4日木曜日

[UWSC]配列のサイズを変更する一【要素を削除】

初心者のプログラミング導入のため、UWSCという開発ソフトを使って作り上げる作業を実際にやって見せるカテゴリ。準備した自作関数や使い方、トラブルを記事にしていきます。得るものがあれば幸いです。
今回は、配列の要素を削除し、配列をリサイズしてしまう方法について書きました。

記事の内容

○配列の要素を削除

プログラムを作る際にはサラッと短いコードで見やすくするのが基本です。理由は、全てのステップに意味があるので、これは何だっけ?と常に再考する必要があるからです。

そのためによく使うのはループ。ループを使うにはやっぱり要素番号を指定して使える配列変数が便利です。というわけで、配列変数をもうちょっと使いこなします。


配列の要素を削除して再構築してしまう

配列の要素を削除し、順番を詰めて綺麗な配列を再構築する手順を作りました。

その中で使用する関数が以下です。
この関数の中でb[]という引数a[]より一つ要素の少ない配列を宣言して、a[]の要素のうち必要なものだけをコピーするための箱として使用します。必要な部分かどうかは4~16行目のif文で判断します。また、ubound()はこちらの記事([UWSC]配列の最大要素を返す関数)で作成した自作関数で、“渡された配列の最大要素数”を返す関数。
arry_remove()関数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
FUNCTION arry_remove(a[],rn)
            j=0
            DIM b[ubound(a)-1]
   IF rn>ubound(a)
            RESULT=SLICE(a,0,LENGTH(a)-1)
            PRINT "ポクエラー(arry_remove関数):最大要素数より大きな要素が削除指定されました。"
   ELSE
      FOR i=0 TO ubound(a)
         IF (i=rn)
         ELSE
            b[j]=a[i]
            j=j+1
         ENDIF
      NEXT
            RESULT=SLICE(b,0,LENGTH(b)-1)
   ENDIF
FEND
関数プログラム説明
1,17行目1
17
FUNCTION arry_remove(a[],rn)
FEND
arry_remove()関数宣言:
引数a[]:削除したい要素のある配列、引数rn:削除する要素数
2,3行目2
3
            j=0
            DIM b[ubound(a)-1]
以降使用する変数の初期値を代入。
配列b[]は渡された配列a[]より一つサイズの小さいものを宣言。(1要素削除する関数なので)
4,7,16行目4
7
16
   IF rn>ubound(a)
   ELSE
   ENDIF
if条件文は、引数rn(:削除しろと渡された要素番号)が、削除対象の配列a[]の最大要素数より大きいかどうか。
(成り立つ)⇒ 5~6行目を実行
(成り立たない)⇒ 8~15行目を実行
5,6行目5
6
            RESULT=SLICE(a,0,LENGTH(a)-1)
            PRINT "ポクエラー(arry_remove関数):最大要素数より大きな要素が削除指定されました。"
削除するべきものがないのでa[]をそのまま返す。また、使用法が間違っているのでエラーを表示。
8~15行目8
9
10
11
12
13
14
15
      FOR i=0 TO ubound(a)
         IF (i=rn)
         ELSE
            b[j]=a[i]
            j=j+1
         ENDIF
      NEXT
            RESULT=SLICE(b,0,LENGTH(b)-1)
変数iを0→a[]の最大要素までループさせる。

if条件文はi=rn。つまり、指定された番号(削除したい番号)の場合。
(成り立つ)⇒ 何もしない、(成り立たない)⇒ 11、12行目を実行

11、12行目
b[j]a[i]を代入。その後jを+1する。
いま8、14行目のループでiが増加。b[]a[]を同じ順番で全て代入するのではなく、削除したい番号は抜いて詰めたいので、iを使用せずjという新しい変数を使用。jは12行目を通ったとき(=b[]に一つ代入された)ときしか+1されないので、b[j]には順番に代入されていく。(削除する番号より小さいときはb[n]にはa[n]、大きいときはb[n]にはa[n+1]が代入されていく。)

全要素コピーし終わってループを抜けたら、出来上がったb[]を関数の戻り値として返す。

呼び出し側は(“ARRY[]”という配列を使っている場合)
呼び出し側
1
2
3
4
5
      dmy=arry_remove(ARRY,2)
      DIM ARRY[ubound(dmy)]
   FOR i=0 TO ubound(dmy)
      ARRY[i]=dmy[i]
   NEXT
呼び出し側プログラム説明
1行目1      dmy=arry_remove(ARRY,2)
配列ARRY[2]を上の関数で削除します。戻り値を配列dmyに代入します。
2行目2      DIM ARRY[ubound(dmy)]
配列ARRY[]の最大要素番号を配列dmyの最大要素番号に変更します。
3~5行目3
4
5
   FOR i=0 TO ubound(dmy)
      ARRY[i]=dmy[i]
   NEXT
配列ARRY[]へ配列dmyをコピーします。

使用する場合には、3ヶ所(1、2、4行目)の“ARRY”を目的の配列名に書き直します。


動作確認しながら仕様を理解

★1、★2、★4を準備して動作確認します。
動作確認
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//↓★1
      DIM ARRY[9]
   FOR i=0 TO 9
      ARRY[i]=i+1
   NEXT
//↑★1   ↓★2
      PRINT "使用前"
   FOR i=0 TO ubound(ARRY)
      PRINT "ARRY["+i+"]="+ARRY[i]
   NEXT
//↑★2   ↓★3
      dmy=arry_remove(ARRY,2)
      DIM ARRY[ubound(dmy)]
   FOR i=0 TO ubound(dmy)
      ARRY[i]=dmy[i]
   NEXT
//↑★3   ↓★4
      PRINT "使用後"
   FOR i=0 TO ubound(ARRY)
      ARRY[i]=dmy[i]
      PRINT "ARRY["+i+"]="+ARRY[i]
   NEXT
//↑★4
動作確認用プログラム説明
2~5行目2
3
4
5
      DIM ARRY[9]
   FOR i=0 TO 9
      ARRY[i]=i+1
   NEXT
確認に使うためにARRYという配列変数に適当な値入れておく。
7~10行目7
8
9
10
      PRINT "使用前"
   FOR i=0 TO ubound(ARRY)
      PRINT "ARRY["+i+"]="+ARRY[i]
   NEXT
目的のブロック(★3)に入る前にARRYの中身がどうなってるか表示しておく。
12~16行目12
13
14
15
16
      dmy=arry_remove(ARRY,2)
      DIM ARRY[ubound(dmy)]
   FOR i=0 TO ubound(dmy)
      ARRY[i]=dmy[i]
   NEXT
動作確認をしたい呼び出しコード。
このプログラムでは“要素数2”を削除してみようと思います。
18~22行目18
19
20
21
22
      PRINT "使用後"
   FOR i=0 TO ubound(ARRY)
      ARRY[i]=dmy[i]
      PRINT "ARRY["+i+"]="+ARRY[i]
   NEXT
目的のブロック(★3)から出た後ARRYの中身がどうかわったか表示する。


確認結果
結果 使用前 使用後
結果 ARRY[0]=1
ARRY[1]=2
ARRY[2]=3
ARRY[3]=4
ARRY[4]=5
ARRY[5]=6
ARRY[6]=7
ARRY[7]=8
ARRY[8]=9
ARRY[9]=10
ARRY[0]=1
ARRY[1]=2
ARRY[2]=4
ARRY[3]=5
ARRY[4]=6
ARRY[5]=7
ARRY[6]=8
ARRY[7]=9
ARRY[8]=10

元々、3が入っていたARRY[2]が削除され順に詰められました。
rnの値を変更して動きを確認してみてください。


綺麗な状態にしておきたい配列はクラスでも作ってグローバルで管理した方がよいのですが、ループの作り方の例題として配列の操作は向いてるかなと思い作ってみました。

ただ、呼び出し側が4行あり、再利用の際には3ヶ所書き換え要。と余りスッキリしないコードになってしまいました。もっとスマートなやり方誰か教えてください。


記事の内容

記事の内容は伝わりましたでしょうか。
○配列の要素を削除


関数群のダウンロードはこちら
func_poku.uwsのコメント欄に呼び出し方が書いてあります。


【関連記事】[UWSC]タイムアウト関数(作り直し)
[UWSC]配列のサイズを変更する二【要素を挿入・追加】
[UWSC]iniファイルを扱う関数
[UWSC]画像が表示された中心座標を返す関数


スポンサーリンク



ブログ村へ blogramのブログランキング

ポク太郎の「俺の説明聞いてくれ」 コンテンツ
ポク太郎の「俺の説明聞いてくれ」最キラー記事 コンピュータ(ハード/ソフト)
映画・ドラマ・芸能
変人のつぶやきとトラブル
ホームへ戻る


0 件のコメント:

コメントを投稿