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


HSPTV!掲示板


未解決 解決 停止 削除要請

2006
0610
ちゅう"x=5" と x=511解決


ちゅう

リンク

2006/6/10(Sat) 06:14:05|NO.1038

質問です。
テキストデータで、たとえば
"x=5" と読み込んだ時に、
変数x に 5という値を代入することができますか?

変数が一文字なら、
文字列の最初の1文字を判定して、

switch word case "a" --- swbreak case "b" --- swbreak swend
とすれば、一応可能です。
ただ、それが2文字以上の文字列になると、
ひとつずつ判定していくのは不可能になります。

なにか手がありましたら、お返事お願いします。



この記事に返信する


男性A

リンク

2006/6/10(Sat) 09:04:38|NO.1039

関数strmidで文字列を読み込むのはいかがでしょうか?



ちゅう

リンク

2006/6/10(Sat) 11:49:57|NO.1040

申し訳ありません、説明不足でした。
確かにstrmidやgetstrを使うことで、二文字以上の文字列を取り出すことができます。

しかし、
例えば、その読み込む内容をユーザーが変更できるとして、
勝手な名前を付けられてしまったら、ひとつひとつifなどで確認するのは大変になってしまします。
switch word の word が
word="a"だったら、
word="val"だったら、
word="pos_x"だったら、
とそこまでは管理仕切れないのです。

もし、"a=1" という文字列を a=1 という命令に直すような命令があればそれで解決です。
ただ、探している限りでは、そんなものは全くといっていいほど見当たりません。

何か知恵がありましたら、案を教えていただけますでしょうか?



ちゅう

リンク

2006/6/10(Sat) 11:55:18|NO.1041

すいません、読み直してみて思ったのですが、

どっちかっていうと、HSPでHSPの小型版のようなスクリプト言語がつくれるか、
という質問の方が近いかと思われます。

ただそれは、変数に代入し、
計算し、
比較するくらいの機能でいいのです。

よろしくお願いします。



Drip

リンク

2006/6/10(Sat) 12:26:30|NO.1042

Dripです。

 ちゅうさん、こんにちは。
文字列で書かれた数式を計算するためのプログラムは、次のような手順で行います。

1.カッコを分解し、数字と演算子のみにする。(getstr、inster等の文字列操作命令を用いる)
2.左から順番に文字列を数字に変換しながら計算する。(intやpeek等を用いる)

とても面倒ですが、文字列の数式の計算は簡単な命令1つでポンとできるような事ではありません。
自分で頑張って演算モジュールを組めば、数百行でできるかと思います。
(使用可能な演算子を限定すればさらに短く組むこともできます。)
がんばってください。



hiroki

リンク

2006/6/10(Sat) 13:01:00|NO.1043

僕も数回iniファイルみたいなのを作った際、"x=5" "x = 5`等の判定方法に
悩みましたが、文字列を分解するのがいい方法だということがわかりました。
それと、あまりswitchにこだわる必要はないですよ。



kz3

リンク

2006/6/10(Sat) 14:48:44|NO.1044

皆さん勘違いしてるっぽい...

>ちゅうさんへ

結論から言うと、実行時に変数の名前を決めることは今のHSPには出来ません。
コンパイルした段階でプログラム中で使われる変数(名)の数が計算されて、
実行した最初に変数を管理するスペースが固定されるからです。
このスペースはにょきにょき伸びたりしないので、
後から「x = 100」という文字列を読み込んで「x」という変数名の為のスペースは確保できません。

用は「変数名 = 数値」という文字列に対して「変数名」と「数値」を関連付ければいいので、
文字列型配列変数と、数値型配列変数を用意して、対応する添え字を一致させればいいです。
例えばこんな感じです。

VarName.0 = "hp": VarValue.0 = 999 ; hp = 999 VarName.1 = "mp": VarValue.1 = 999 ; mp = 999 VarName.2 = "exp": VarValue.2 = 123456 ; exp = 123456
こういう約束事にしておけば「変数名 = 数値」という文字列を読み込んだら、
「変数名」を切り離して、文字列型配列変数 VarName に「変数名」が登録されているかどうかを調べ、
見つかった時の配列の添え字が、そのまま「数値」を管理する数値型配列変数 VarValue の添え字に利用できるというわけです。

これを使いこなすには、探索・追加・挿入などが必要になってきます。
特に探索は大事です。
未登録の「変数名」が現れたら登録しなければなりませんが、一番簡単なのは配列の末尾にそのまま追加です。
この方法だと探索するときは先頭から順番に探索するしかありませんが、
「変数名」を辞書順で整理しながら登録していけば二分探索が利用できます。

ちょっと最後の方法は難しいと思うので、最初は自分のできる方法でやっていくのがいいです。



hiroki

リンク

2006/6/10(Sat) 15:56:03|NO.1046

僕も配列を使えば簡単だと思ったんですが、数値じゃなく文字列の
場合もあるしなーーと思い、躊躇してしまいました。^^;
インタプリタみたいなことをしたいのか、iniみたいに設定値を
読み書きしたいか、頭が固くなった僕にはまだわかりません。



ちゅう

リンク

2006/6/11(Sun) 02:57:58|NO.1056

Dripさん、hirokiさん、kz3さん
ありがとうございます。

kz3さん、稚拙な質問を理解していただいて本当に助かります。

そうなのですか・・・。そういうことになっているのですか。
というか、添え字を使えば、かなり早く便利だということですね。
その方法でやってみます。

最後の二分探索というのも、調べてみました。
処理を軽減する検索法ですね。
この場合、文字列を一文字ずつASCIIに変えて、
真ん中で判定、真ん中で判定、を繰り返せばいいということですか・・・?


hirokiさんの言うとおり、これだと文字列ができないです。
なので、文字列の2次元配列をもうひとつ用意して、やってみます。



kz3

リンク

2006/6/11(Sun) 10:02:21|NO.1058

>処理を軽減する検索法ですね。

です。

>この場合、文字列を一文字ずつASCIIに変えて、
>真ん中で判定、真ん中で判定、を繰り返せばいいということですか・・・?

「 sary = "xxx","yyy","zzz" 」という3つの要素からなる文字列配列の中から、
「 "yyy" 」を探したときはインデックス「 1 」が得られて、
「 "kz3" 」を探したときは「 sary 」に含まれていないので「 -1 」を得るようにします。

なので「真ん中で判定」は文字列の「文字」ではなく、文字列配列の「要素」になります。
文字列配列の真ん中の要素と比較し、大小にあわせて、次の検索範囲の真ん中、真ん中へと探索を進めていきます。

ちなみに文字列の辞書順の比較は「 ! 」演算子と使うといいようです。「 = 」はダメです。( by 月影ともさん )

mes "aaa"!"zzz" mes "aaa"!"aaa" mes "zzz"!"aaa" mes "aaa"="zzz" mes "aaa"="aaa" mes "zzz"="aaa"

>hirokiさんの言うとおり、これだと文字列ができないです。
>なので、文字列の2次元配列をもうひとつ用意して、やってみます。

文字列も出てくるなら数値を文字列として管理して、数値として計算に用いるときに、
int命令で数値に変換してやればいいと思います。
よって変数名を管理する文字列配列変数と、値( 数値・文字列 )を管理する文字列配列変数の
2つで十分だと思います。
# 逆に値を管理する配列が複数あると変数名のインデックスと整合取れなくなって面倒に...



Shinya

リンク

2006/6/11(Sun) 13:38:38|NO.1062

 以前に、インタプリターを作ったことがあるので、計算部分だけ載せておきます。
;モジュール----------------------------------------------------------------
#module #defcfunc Search_Str var v1, var v2, str s1, int p1, str p2, str p3, int p4 buf.0 = s1 buf.1 = p2 buf.2 = p3 prm.0 = varptr(v1) prm.1 = varptr(v2) prm.2 = varptr(buf.0) prm.3 = p1 prm.4 = varptr(buf.1) prm.5 = varptr(buf.2) prm.6 = p4 return callfunc(prm,sPtr,7) #defcfunc SearchBlock_Str var v1, var v2, str s1, str s2, int p1, str p2, str p3 buf.0 = s1 buf.1 = s2 buf.2 = p2 buf.3 = p3 prm.0 = varptr(v1) prm.1 = varptr(v2) prm.2 = varptr(buf.0) prm.3 = varptr(buf.1) prm.4 = p1 prm.5 = varptr(buf.2) prm.6 = varptr(buf.3) return callfunc(prm,bPtr,7) #deffunc Del_Str var v1,str s1,str s2,str s3 buf.0 = s1 buf.1 = s2 buf.2 = s3 prm.0 = varptr(v1) prm.1 = varptr(buf.0) prm.2 = varptr(buf.1) prm.3 = varptr(buf.2) a = callfunc(prm,dPtr,4) return 0 #deffunc UnquoteSpaces var v1 prm.0 = varptr(v1) a = callfunc(prm,uPtr,1) return 0 #deffunc __init__ _searchstr_.0 = $83ec8b55,$8b5308ec,$75030c75,$f8758914,$8b105d8b _searchstr_.5 = $7d8b1855,$3a801c,$7fe80574,$33000000,$f0e38c9 _searchstr_.10 = $13284,$204d3800,$33524974,$fc5589d2,$48ae432 _searchstr_.15 = $75c00a1a,$74c90b0c,$1ce95a33,$eb000001,$752c3c23 _searchstr_.20 = $74c90b16,$ce95a08,$eb000001,$fc45ff13,$eb42e432 _searchstr_.25 = $3809ebd5,$4743104,$1b4c933,$175e40a,$c2eb4241 _searchstr_.30 = $8a1deb5a,$c0841904,$c9850a75,$e5850f,$ceb0000 _searchstr_.35 = $74310438,$ebf10304,$e3eb4103,$b1e8,$ff77e900 _searchstr_.40 = $3353ffff,$32c933db,$fc6588e4,$a13048a,$b0f75c0 _searchstr_.45 = $30774c9,$32e8f1,$c35b0000,$2c3c26eb,$c90b1975 _searchstr_.50 = $f1030b74,$1fe8,$ebc35b00,$fc45fe13,$eb43e432 _searchstr_.55 = $3809ebcf,$4743104,$1b4c933,$175e40a,$bceb4341 _searchstr_.60 = $fc558a52,$db334ceb,$e432c933,$a3b048a,$800e75c0 _searchstr_.65 = $7500fc7d,$74c90b31,$eb3aeb2d,$752c3c21,$fc7d8014 _searchstr_.70 = $85047700,$fe2a75c9,$e432fc4d,$ebd5eb43,$31043809 _searchstr_.75 = $c9330474,$e40a01b4,$43410175,$5588c2eb,$ce8fc _searchstr_.80 = $3e800000,$5aaf7500,$4ef103c3,$68ac35a,$976803c _searchstr_.85 = $472b13c,$176dd3c,$b8c34646,$ffffffff,$8bc3c95b _searchstr_.90 = $458b087d,$2b0789fc,$c68bf875,$55c3c95b,$ec83ec8b _searchstr_.95 = $758b5308,$1875030c,$8bf87589,$558b105d,$207d8b1c _searchstr_.100 = $3a80e432,$50077400,$ffff05e8,$c93358ff,$bb740e38 _searchstr_.105 = $8419048a,$b1475c0,$fe0e74c9,$1fc80c4,$f1030775 _searchstr_.110 = $2bf87589,$3808ebf1,$3753104,$53ddeb41,$a145d8b _searchstr_.115 = $331d74e4,$19048ac9,$c75c084,$674c90b,$c438ccfe _searchstr_.120 = $8eb1274,$75310438,$e5eb4103,$ff5ce85b,$9eebffff _searchstr_.125 = $f8458b5b,$452bf02b,$8558b0c,$c95b3289,$ec8b55c3 _searchstr_.130 = $5308ec83,$8bfc9c66,$5d8b0875,$10558b0c,$32147d8b _searchstr_.135 = $740638c0,$74023867,$fe78e805,$3357ffff,$32c933ff _searchstr_.140 = $1f048ae4,$d75c00a,$3074c90b,$33e8,$ebeeeb00 _searchstr_.145 = $752c3c1f,$74c90b12,$22e807,$3eb0000,$eb47e432 _searchstr_.150 = $3809ebd8,$4743104,$1b4c933,$175e40a,$c5eb4741 _searchstr_.155 = $fedce85f,$a7ebffff,$3fe8b56,$ebe432f1,$2738a401 _searchstr_.160 = $335efb75,$c3ff33c9,$c95b9d66,$6e652dc3 sPtr = varptr(_searchstr_) bPtr = sPtr + 93*4 + 3 dPtr = bPtr + 35*4 + 2 _unquotespaces_.0 = $8bec8b55,$3e800875,$662b7522,$fe8bfc9c,$ffb9c032 _unquotespaces_.5 = $f2ffffff,$d9f741ae,$22fe7f80,$47881275,$46fe8bfe _unquotespaces_.10 = $2e9c151,$8359a5f3,$a4f303e1,$c35d9d66 uPtr = varptr(_unquotespaces_) VarCount = 0 VarList = "" Variable = "" return #defcfunc GetType var v1 a = peek(v1) return a!='+' && a!='-' && a<'0' || a>'9' #deffunc Sub_Variable var v1 v1 = "("+v1+")":a = instr( VarList,0,v1 ) if a == -1 :return -1 a + strlen(v1):getstr get1,VarList,a,')':a + strsize return int(get1) #deffunc Save_Variable var v1,str s1,int p1 ; v1 = 変数名 ; s1 = 代入する文字列 ; p1 = 0なら数字として,1なら文字列として扱うタイプ get = v1 Sub_Variable get if stat == -1 { VarList + get + VarCount + ")" + p1 + ")" Variable.VarCount = s1 :VarCount++ return } Variable.stat = s1 getstr get,VarList,a,')' if int(get) != p1 :get = ""+p1 :memcpy VarList,get,1,a return #deffunc Load_Variable var v1 get = v1:Sub_Variable get :if stat == -1 :return 0 v1 = Variable.stat getstr get,VarList,a,')' return int(get) #enum EQU = 0 #enum SHL #enum SHR #enum ADD #enum SUB #enum MOL #enum DIV #enum MOD #enum _NOT #enum _AND #enum _OR #enum _XOR #defcfunc Calculation str s1,local tmp, local ti, local ts tmp = s1 Del_Str tmp," ,\t","\"","\"" ti = SearchBlock_Str( ts,tmp,"(",")",0,"\"","\"" ) if ti != -1 { buf1 = strmid(tmp,ti,ts) buf1 = Calculation(buf1) a = ti+ts+1 tmp = strmid(tmp,0,ti-1) + buf1 + strmid( tmp,a,strlen(tmp)-a ) tmp = Calculation(tmp) } Vsig = 0; ←数値か文字列か、判断する変数 ci = 0 repeat gosub *Operator if a == -1 { if GetType(tmp) && peek(tmp)!='\"' :Load_Variable tmp :if cnt == 0 && stat :Vsig = 1 break } buf1 = strmid( tmp,0,a ) :getstr tmp,tmp,a + 1 + (c < ADD) ct = c ci = 0 gosub *Operator if a == -1 { buf2 = tmp tmp = "" } else { buf2 = strmid( tmp,0,a ) :getstr tmp,tmp,a } i = strlen(tmp) UnquoteSpaces buf1 UnquoteSpaces buf2 if Vsig == 0 { if GetType(buf1) :Load_Variable buf1 :if cnt == 0 && stat :Vsig = 1 if GetType(buf2) :Load_Variable buf2 } *@ if Vsig { switch ct case ADD tmp = "\""+buf1 + buf2+"\"" + tmp goto *@f case EQU tmp = "" + (buf1 == buf2) + tmp goto *@f case _NOT tmp = "" + (buf1 != buf2) + tmp goto *@f default dialog "サポートされない機能を選択しました",1 :end swend } switch ct case EQU tmp = "" + (double(buf1) == double(buf2)) + tmp swbreak case SHL tmp = "" + (int(buf1) << int(buf2)) + tmp swbreak case SHR tmp = "" + (int(buf1) >> int(buf2)) + tmp swbreak case ADD tmp = "" + (double(buf1) + double(buf2)) + tmp swbreak case SUB tmp = "" + (double(buf1) - double(buf2)) + tmp swbreak case MOL tmp = "" + (double(buf1) * double(buf2)) + tmp swbreak case DIV tmp = "" + (double(buf1) / double(buf2)) + tmp swbreak case MOD tmp = "" + (int(buf1) \ int(buf2)) + tmp swbreak case _NOT tmp = "" + (int(buf1) ! int(buf2)) + tmp swbreak case _AND tmp = "" + (int(buf1) & int(buf2)) + tmp swbreak case _OR tmp = "" + (int(buf1) | int(buf2)) + tmp swbreak case _XOR tmp = "" + (int(buf1) ^ int(buf2)) + tmp swend *@ if a == -1 :break ci = strlen(tmp) - i loop UnquoteSpaces tmp return tmp *Operator // 文字列チェック if cnt == 0 && peek(tmp) == '\"' :Vsig = 1 // 負号チェック repeat a = Search_Str( c,tmp,"==,<<,>>,+,-,*,/,%,!,&,|,^",ci,"\"","\"",1 ) if a == -1 :break if c == SUB { if Vsig :break if ctmp :ci++ :continue } a + ci break loop ctmp = strmid(tmp,a+1,1) == "-" return #global ; 初期化 __init__ ;------------------------------------------------------------------------ ;----- メイン -----; #define 数値 0 #define 文字 1 // 変数名 vname = "var" ; 数値を代入 Save_Variable vname,"10",数値 ; mes Calculation("var + (5 * 2) / 15") ; 文字列を代入 Save_Variable vname,"abc",文字 ; mes Calculation("var + 5 + 50 + 100")
長くてすみません...。
 変数の内容は、文字列型の配列変数に退避しておきます。
変数名は、変数名のリストを作成しています。

 ↑この場合だと、変数の管理がすべて文字列になるので、
WinApi の HeapAlloc を使うのもありです。(HeapAllocはこの掲示板で教えてもらいました)
モジュールの詳しい内容は、
http://hspwiki.nm.land.to/?%CA%B8%BB%FA%CE%F3%A4%CE%B7%D7%BB%BB%A5%E2%A5%B8%A5%E5%A1%BC%A5%EB
にあります。



ちゅう

リンク

2006/6/13(Tue) 18:06:32|NO.1088

kz3さん、Shinyaさん、お返事ありがとうございます。

kz3さん、
確かにそうですね。よく考えたら、名前で二分した場合は
変数名によって偏って二分できませんよね(汗)
すべて文字列として扱ってみます。
ご指摘ありがとうございます。

Shinyaさん、
貴重な情報をありがとうございます。
これを元に色々試してみようと思います。
とりあえず、自分なりに作ってみて、
どうしても行き詰ったら、参考にさせてもらおうと思っています。

みなさまのお陰で、アルゴリズム上は問題なく作動させられています。
まだ300行程度しか作っていないですが、それでも充分、
それらしいものが作れそうです。

本当に助かりました。ありがとうございました。



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