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


HSPTV!掲示板


未解決 解決 停止 削除要請

2008
0123
KENTAnote命令類を使わず全行数を取得10解決


KENTA

リンク

2008/1/23(Wed) 20:51:08|NO.13242

noteがつく命令を使わずに行数を取得するには、
sendmsg命令を利用して、オブジェクト内の行数を取得することができます。
しかし、変数内の行数をsendmsgで取得することができません。
noteがつく命令を使わず、全行数を取得する方法があれば教えてください。


この質問と関係がないのですが、最近、Yahoo! IDを取得しました。
ブリーフケースにHSPのスクリプトを置いていく予定なので、よろしくお願いします。
>http://briefcase.yahoo.co.jp/kenta_3759



この記事に返信する


KENTA

リンク

2008/1/23(Wed) 21:08:53|NO.13243

すいません。解決しちゃいました。
一応、行数を取得するスクリプトを書き込んどきます。

#module #defcfunc notemax_ str p1 char=p1 sel=0 max=0 repeat sel+=instr(char,sel,"\n") max++ if sel+2=strlen(char) :return max sel++ await 0 loop #global a="Hot\nSoup\nProcessor\n\n" mes notemax_(a)



eller

リンク

2008/1/23(Wed) 21:41:19|NO.13244

KENTAさん、こんばんは。

repeat〜loop内でreturnを使っているようですが、これは正しい使い方ではありませんのでお勧めしません。
例えば以下のスクリプトを実行すればエラーが出てしまいます。
// モジュール部省略
a="Hot\nSoup\nProcessor\n\n" repeat 1 mes notemax_(a) loop
repeat〜loopからbreakを使って外へ出て、それからreturnを使ってください。


そして参考までに、正規表現を利用したスクリプトを置いておきます。

#module // instr()を利用した行数の取得 #defcfunc get_line_nums var p1 result = 0 repeat result++ ins = instr(p1, cnt, "\n") if ins == -1 : break continue cnt + ins + 2 // 2 = 文字列"\n"の長さ[byte] loop return result // 正規表現を利用した行数の取得 #defcfunc get_line_nums2 var p1 if vartype(com_regex) != vartype("comobj") { // comオブジェクト型変数の初期化 newcom com_regex, "VBScript.RegExp" comres com_result com_regex("Pattern") = "\\r\\n" com_regex("Global") = 1 } com_regex->"Execute" p1 return com_result("Count") + 1 // 行数 = 改行の個数 + 1 #global s = "Hot\nSoup\nProcessor\n\n" mes get_line_nums(s) mes get_line_nums2(s) stop



KENTA

リンク

2008/1/23(Wed) 21:52:23|NO.13246

ellerさん、ご指摘ありがとうございます。
一応修正したのが下のスクリプトです。

#module #defcfunc notemax_ str p1 char=p1 sel=0 max=0 repeat sel+=instr(char,sel,"\n") max++ if sel+2=strlen(char) :break sel++ await 0 loop return max #global a="Hot\nSoup\nProcessor\n\n" mes notemax_(a)



eller

リンク

2008/1/23(Wed) 22:50:25|NO.13247

すみません、先ほどは気づきませんでしたが「改行で終わらない文字列」に対してKENTAさんの関数を呼び出すと無限ループに陥るようです。
一応報告まで。



KENTA

リンク

2008/1/23(Wed) 23:06:45|NO.13248

ellerさん、ご報告ありがとうございます。

sel+=instr(char,sel,"\n")
の下に

if max=0 & sel=-1 :break
を追加してください。



FUJI

リンク

2008/1/24(Thu) 00:01:42|NO.13249

eller さんのスクリプトを試してみましたが、instrを使う方法と正規表現を使う方法の両方で 空文字列のときに 0 行ではなく 1 行となってしまいます。
notemax はちゃんと空文字列のとき 0 を返します。

# 素直に notemax を使った方がいいと思うのですが...



eller

リンク

2008/1/24(Thu) 06:03:41|NO.13251

> FUJIさん
ご指摘ありがとうございます。
空文字の時に1を返すべきか0を返すべきかはケースによるとも思いますが、HSP標準のnotemaxに合わせた方が過去の資料などを活用しやすく好ましいですね。
// notemaxを利用した行数の取得
#module // notemaxを利用 #defcfunc get_lines_num3 var p1 notesel p1 result = notemax noteunsel return result #global s = "Hot\nSoup\nProcessor\n\n" mes get_lines_num3(s) // 空行で終わる時はその行をカウントしない s = "" mes get_lines_num3(s) stop



a

リンク

2008/1/24(Thu) 20:11:12|NO.13257

notesel命令は安易に使うとマズイよ

a = "A\nA\nA\nA\nA\nA" // 6行 b = "B\nB\nB\nB" // 4行 c = "C\nC" // 2行 notesel a noteget s, 0 : mes s+" "+notemax notesel b noteget s, 0 : mes s+" "+notemax notesel c noteget s, 0 : mes s+" "+notemax noteunsel noteget s, 0 : mes s+" "+notemax noteunsel noteget s, 0 : mes s+" "+notemax noteunsel
ヘルプの解説だけ読むと

A 6 B 4 C 2 B 4 A 6
と、表示されそうだけど、実際は

A 6 B 4 C 2 B 4 B 4
に、なる。
noteunselで復帰できるのは1つ手前にだけ。 noteunselを2回実行しても2つ手前には戻せない。
バッファ設定を保持させたい場合、ネストしても良いのは1段のみ。
なので、すでにネストしているのかが判別できないサブルーチン内や、汎用のユーザー関数では、
note系の命令を使いたくても使えない状況が発生。
KENTAさんの質問はそうゆう理由からだと思う。たぶん。

すでにネストした状態で、さらにnotesel〜noteunselを使ってしまうと
バッファ設定が復帰しないまま動作が進行してしまい、バグ発生。
エラーが出るわけでもないし、なかなか気付かないんだ。このバグ。


#module #defcfunc get_line_nums var s result = 0 idx = 0 repeat p = instr(s, idx, "\n") if( p == -1 ) { break } result++ idx += p + 2 loop if( peek(s, idx) != 0x00 ) { result++ } return result #global #module #defcfunc get_line_nums2 var p1 if vartype(com_regex) != vartype("comobj") { newcom com_regex, "VBScript.RegExp" comres com_result com_regex("Pattern") = "\\r\\n|[^\\n]$" com_regex("Global") = 1 } com_regex->"Execute" p1 return com_result("Count") #global



FUJI

リンク

2008/1/25(Fri) 09:54:57|NO.13261

aさん。なるほど、勉強になります。

#module #defcfunc get_lines_num4 var p1 mref hspctx, 68 dim selnoteinfo, 4 // HSPCTX のnote_pvalからnotep_aptrまでは // 先頭から 808 バイトから 16 バイト memcpy selnoteinfo, hspctx, 16, 0, 808 notesel p1 result = notemax memcpy hspctx, selnoteinfo, 16, 808, 0 return result #global a = "A\nA\nA\nA\nA\nA" // 6行 b = "B\nB\nB\nB" // 4行 c = "C\nC" // 2行 notesel a noteget s, 0 : mes s+" "+notemax notesel b noteget s, 0 : mes s+" "+notemax mes get_lines_num4( c ) noteget s, 0 : mes s+" "+notemax noteunsel noteget s, 0 : mes s+" "+notemax noteunsel
noteunselではなく、hspctxのデータを記憶しておいて戻すというのをやってみました。



a

リンク

2008/1/25(Fri) 21:30:29|NO.13267

なるほど、こちらこそ勉強になりますw
その方法使えば、ネストの問題は解決ですね。ありがとうございます。

標準命令をラップして、#defineで置き換えてみた
notesel2.as

//==================== notesel2.as ==================== #ifndef __notesel2__ #define global __notesel2__ #module notesel2_ #const _stack_max 20 //←ネスト可能最大値 (お好きな数をどうぞ) #uselib "msvcrt.dll" #func _memmove "memmove" int,int,int #deffunc notesel@notesel2_ var _buf if( vartype(stack) == 4 ) { sdim stack, 16*_stack_max } _memmove varptr(stack)+16, varptr(stack), 16*(_stack_max-1) mref hspctx, 68 memcpy stack, hspctx, 16, 0, 808 notesel@hsp _buf return #deffunc noteunsel@notesel2_ if( vartype(stack) == 4 ) { return } mref hspctx, 68 memcpy hspctx, stack, 16, 808, 0 _memmove varptr(stack), varptr(stack)+16, 16*(_stack_max-1) return #global #undef notesel #define global notesel(%1) notesel@notesel2_ %1 #undef noteunsel #define global noteunsel noteunsel@notesel2_ #endif //=======================================================
使用例

#include "notesel2.as" a = "A\nA\nA\nA\nA\nA" // 6行 b = "B\nB\nB\nB" // 4行 c = "C\nC" // 2行 d = "D\nD" // 2行 e = "E\nE" // 2行 notesel a noteget s, 0 : mes s+" "+notemax notesel b noteget s, 0 : mes s+" "+notemax notesel c noteget s, 0 : mes s+" "+notemax notesel d noteget s, 0 : mes s+" "+notemax notesel e noteget s, 0 : mes s+" "+notemax noteunsel noteget s, 0 : mes s+" "+notemax noteunsel noteget s, 0 : mes s+" "+notemax noteunsel noteget s, 0 : mes s+" "+notemax noteunsel noteget s, 0 : mes s+" "+notemax noteunsel



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