HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0507
こいるif文で1つの左辺に対して、論理演算子を使い複数の右辺と比較したい13解決


こいる

リンク

2020/5/7(Thu) 19:14:10|NO.90305

こんな感じに、
ループ回数が2回目と3回目のときに実行するようにしたいです。

// 3回目のときにしか実行しない… repeat 10 if cnt == (2|3) { mes cnt } loop

これくらいなら普通に"if cnt == 2 | cnt == 3"とすればいいですが、
右辺が多くなってくると、とても見づらいです。

なにか良い方法はありませんか?



この記事に返信する


しまくろねこ

リンク

2020/5/7(Thu) 19:22:18|NO.90306

switch文はいかがでしょうか?

repeat 10 switch cnt case 2 case 3 mes cnt swbreak swend loop




こいる

リンク

2020/5/7(Thu) 19:39:02|NO.90307

switch文ってこんな書き方もできるんですね!

しかし、"case"をいちいち書かないといけないので、
こちらも比較値(右辺)が多くなると見づらくなりますね。

論理演算子が使えたらいい感じになるのですが…

他に方法はありませんか?



沢渡

リンク

2020/5/7(Thu) 20:44:01|NO.90308

switch構文で使われる命令(switch、case、default、swbreak、swend)は
実際はcommonフォルダの中のhspdef.as内で定義されているマクロなので、
このうちcaseの定義、

#define global case(%1) %tswitch _switch_sw++} if _switch_val == (%1) | _switch_sw { _switch_sw = 0
を改造したマクロを作ってやればいいかもしれません。
以下、例です。

//case_ex p1,p2 //caseの代わりに使用する。switchで指定した変数の内容がp1以上p2以下なら、これ以下の内容を実行する。あとはcaseと同じ。 #define global case_ex(%1=-2147483648,%2=2147483647) %tswitch _switch_sw++} if ((_switch_val>=(%1))&(_switch_val<=(%2))) | _switch_sw { _switch_sw = 0 //例:cntが2以上5以下ならcntの値を表示する repeat 10 switch cnt case_ex 2,5 mes cnt swbreak swend loop



kanamaru

リンク

2020/5/7(Thu) 21:14:02|NO.90309

こんなのはどうでしょう

repeat 10 if cnt == limit(cnt,2,5) { mes cnt } loop
でも多分必ず連続した数とは限らないんですよね。
沢渡さんも僕も連続した数に対してのみ使える方法ですし。
pythonだとnumpyの力借りれば連続してなくてもいくらでも書きようがあるんですけど。



Makoto

リンク

2020/5/7(Thu) 21:41:20|NO.90310

こんな方法はいかがでしょう


p1="03 05 09 42" ;実行したい回数 repeat 100 if instr(p1,0,strf("%02d",cnt)) > -1 { mes cnt } loop

これなら不連続でも実行できます



さか

リンク

2020/5/7(Thu) 22:52:32|NO.90311

条件が多くなってくると入れ子が多くなったり1行が長くなり見づらいと言うことですよね。
条件に合わないifを並べて最後を条件にマッチした処理とするのはどうですか。

例えば、今回であれば以下です。

// 3回目のときにしか実行しない… repeat 10 if cnt < 2: continue if cnt > 3: continue mes cnt loop



こいる

リンク

2020/5/8(Fri) 11:49:23|NO.90313

>沢渡さん
連続した数値でしか使えないので、広くは使えないですね。
文字列だとまず使えないです。


>kanamaruさん
おっしゃる通り、これも広くは使えないですね。


>Makotoさん
この例ならこれで良いのですが、
文字列が"a"か"b"ならとかには使えないんですよね。

// まあ、その場合には普通にこうすれば良いのですが、 buf = "文字列" if buf=="a" | buf=="b"{ } // 自分はこういう風に左辺1個に対して右辺を〜としたいです。 // (要は左辺は同じなので何回も書きたくないということです) buf = "文字列" if buf== ("a"|"b") { }


>さかさん
これも連続した数値くらいにしか使えないような気がします。

例えば1回目と3回目に実行したいとき、書きようがないと思います。
こうすると1回目は3以外、3回目は1以外で条件を満たして結局実行されなくなってしまいます。

// 1回目と3回目に実行したいけど… repeat 10 if cnt!=1 : continue if cnt!=3 : continue mes cnt loop

こうすれば行けるみたいですが、
はっきり言って、何をやっているかいまいち分からないです。

// 1回目と3回目に実行する repeat 10 if cnt==1 ^ cnt!=3 : continue mes cnt loop


多くの返信ありがとうございます。
それなのに否定ばかりで申し訳ないです。

やはり無理があるのでしょうか…


他に方法はありますか?



mikumo

リンク

2020/5/8(Fri) 12:30:17|NO.90314

特殊展開マクロを使うという手もありますが

#define ifeq(%1, %2) %tifeq %s1 if %p0 == %2 #define or_(%1) %tifeq || %p0 == %1 #define then %tifeq %o0 #define _ or_ a = 7 ifeq a, 6 _ 7 _ 8 _ 9 _ 10 then { mes "ok" } else { mes "no" } x = "Hello" ifeq x, "A" _ "B" _ "C" then { mes "ok" } else { mes "no" }



沢渡

リンク

2020/5/8(Fri) 12:55:40|NO.90315

該当する値を入れた配列を作り、調べる値がその配列の中にあるかどうかを確かめるという方法は。

//arrchk p1,p2 //整数の1次元配列p1の中にp2があったら1を、なかったら0を返す。 // //arrchk_f p1,p2 //↑の実数配列版 // //arrchk_s p1,p2 //↑の文字列配列版 #module #defcfunc arrchk array ar1,int n1 tmp=n1 return arrchk_main(ar1,tmp) #defcfunc arrchk_f array ar2,double n2 tmp=n2 return arrchk_main(ar2,tmp) #defcfunc arrchk_s array ar3,str n3 tmp=n3 return arrchk_main(ar3,tmp) #defcfunc arrchk_main array ar,var n x=0 repeat length(ar) if ar(cnt)=n : x=1 : break loop return x #global //整数の例 dim a,3 a=7,5,3 repeat 10 if arrchk(a,cnt) : mes cnt loop //文字列の例 //10個あるアイテムの中から、特定のアイテムが見つかったら何番目のアイテムなのかを表示 sdim item,64,10 item="りんご","みかん","ぶどう","メロン","なし","いちご","もも","びわ","いちじく","バナナ" sdim b,64,3 b="いちご","もも","バナナ" repeat 10 if arrchk_s(b,item(cnt)) : mes item(cnt)+":"+str(cnt+1)+"番目のアイテム" loop



Makoto

リンク

2020/5/8(Fri) 13:38:39|NO.90316

最初の質問では対象が数値だったので
文字列に変換して instr で調べるという方法を提案しましたが

対象が文字列という事であれば instr の機能そのものずばりで OK な気がします

buf = "文字列" p1 = "spring summer autumn winter" ;この中のどれかと一致すれば実行 ;単語間のスペースはなくてもいいが、わかりやすさと ;違う文字列が実行されるのを防ぐために入れている(例:"ingsum") if instr(p1,0,buf) > -1 { }
単純に条件を満たすか満たさないかというのなら
これで出来そうな気がしますがどうでしょう



こいる

リンク

2020/5/8(Fri) 14:03:05|NO.90317

>mikumoさん
すごいですね!まさにこんなのが欲しかったです!

;#cmpopt ppout 1 // プリプロセッサファイル出力(マクロ展開) #define ifeq(%1, %2) %tifeq %s1 if %p0 == %2 #define or_(%1) %tifeq || %p0 == %1 #define then %tifeq %o0 #define _ or_ // ループ回数が1回目と3回目のときに実行する repeat 10 ifeq cnt, 1 _ 3 then { mes cnt } loop


>沢渡さん
今回は既に気に入ったものが出たので使わないと思いますが、
2度も案を出してくださってありがとうございました。


ということで解決にしたいと思います。
皆さんありがとうございました。



こいる

リンク

2020/5/8(Fri) 14:06:57|NO.90318

>Makotoさん
すみません。ページの更新していなくて気づきませんでした。

>対象が文字列という事であれば instr の機能そのものずばりで OK な気がします
確かにそうですね。
そういう場合はこちらの方法でもやってみたいと思います。

返信ありがとうございました。



沢渡

リンク

2020/5/8(Fri) 15:18:35|NO.90319

instr検索だと、たとえば今回の"spring summer autumn winter"で言えば
"ring"でも引っかかったりするので、それの対策が必要かと思います。


#module #define global ctype instr2(%1,%2=0,%3="") _instr2(%1,%2,%3) #defcfunc _instr2 str _s,int i,str s2 s=" "+_s+" " return instr(s,i," "+s2+" ") #global buf1 = "spring" buf2 = "ring" buf3 = "ingsum" p1 = "spring summer autumn winter" if instr2(p1,0,buf1) > -1 : mes "OK" : else : mes "NG" if instr2(p1,0,buf2) > -1 : mes "OK" : else : mes "NG" if instr2(p1,0,buf3) > -1 : mes "OK" : else : mes "NG" //「OK NG NG」の順で表示される筈



ONION software Copyright 1997-2023(c) All rights reserved.