|
|
2021/1/13(Wed) 14:52:03|NO.92062
こんにちは。初めて掲示板に投稿するとmikotoと申します。
さっそく質問ですがUnicodeのテキストによる10000行以上のテキストに含まれている任意の文字列を改行に置換するプログラムの組み立てに困りごとです。
下記のプログラムを組み立てたのですが
#include "hsp3utf.as"
sdim minamoto,10000000,1 ; 変数aは3文字までの文字列を10000つの要素で扱えます
mesbox minamoto,150,150,5,10000000000000000000000000000000
button goto "改行する",*label
stop
*label
strrep minamoto,":","\n"
mesbox minamoto,150,150,5,100000000000000000000000000000000
stop
をHSP実行を押して実行結果のメッセージボックスに改行する10000行以上のUnicodeのテキストを入力して改行するボタンを押すと実行結果ウィンドウが消えてしまいます。
原因をしるために検索して自分でも調べていますが
皆様からヒントをもらえると助かります。
よろしくお願いします。
|
|
2021/1/13(Wed) 17:50:10|NO.92064
あと、使用環境はWindows10でHSPのバージョンは3.5です。
|
|
2021/1/13(Wed) 18:05:57|NO.92065
とりあえず気になることは、
・mesboxの第5パラメータの数値があまりにも大きすぎる。
整数の最大値は2147483647ですし、現実的に考えてGB単位の文書を入力するなんて
まずありえないと思いますから、もう少し現実的な値にした方が良いでしょう。
(たとえばminamotoのサイズに合わせて10MB程度とか)
・このコードだと*labelを呼び出すたびに新しいメッセージボックスが作られてしまう。
メッセージボックスの内容への反映はobjprmを使った方が良い。
|
|
2021/1/13(Wed) 18:28:58|NO.92066
UTF-8版のランタイムの不具合な気がします。
文字列が32767文字までは大丈夫ですが、それ以上になると落ちるっぽい。
// UTF-8版でなければ落ちない模様
#include "hsp3utf.as"
// 長い文字列を用意
sdim s, 10000000
repeat 32768 // 32767 であれば落ちない
poke s, cnt, '0' + cnt \ 10
loop
// メッセージボックス表示&書き換え
mesbox s, 640, 480, 1, -1
objid = stat
objprm objid, s
|
|
2021/1/13(Wed) 19:45:54|NO.92068
多分、252行目のメモリ確保処理がUTF-8版において足りていない予感。
http://dev.onionsoft.net/trac/openhsp/browser/trunk/hsp3/win32gui/hspwnd_obj.cpp#L252
231 static void Object_StrInput( HSPOBJINFO *info, int wparam )
〜略〜
248 if (size < 0x8000) {
249 bigbuf = minp;
250 val = GetDlgItemText( hwnd, cid, minp, 0x7fff );
251 } else {
252 bigbuf = (HSPAPICHAR*)sbAlloc( size+1 );
253 val = GetDlgItemText( hwnd, cid, bigbuf, size );
254 }
横展開して確認してませんので、他にもあるかも…?
|
|
2021/1/14(Thu) 13:14:04|NO.92070
沢渡様、TOMATO様、教えてくださりありがとうございます。
objprmを使ってメッセージボックスの内容を変えた方がボタンを押すたびに
新しいメッセージボックスを作らずにメッセージボックス命令も一回書くのみで成り立ちます。
#include "hsp3utf.as"の機能は文字列が32767文字までの受付を許すようです。
http://dev.onionsoft.net/trac/openhsp/browser/trunk/hsp3/win32gui/hspwnd_obj.cpp#L252
のページも見ましたがプログラムが長くてすこしよくわからないところがあるので保留にします。
Unicodeの32767文字までのテキストに含まれる任意の文字列を改行に置換するプログラムを組み立てなおしたのでのせておきます。
#include "hsp3utf.as" //文字列が32767文字までは大丈夫
screen 0, 369,369, screen_tool
objmode 2,1
font "游明朝",24,16
title "テキストに含まれる任意の文字を改行に置換する。"
sdim minamoto,2147483,1
sdim nyuuryoku,2147483,1
mes "32767文字までの文字列を入力"
mesbox minamoto,369,150,5,2147483647
mes "下記に改行に置換する文字を入力"
input nyuuryoku,369,100,0
objsize 369,36
button goto "改行に置換する",*label
stop
*label
strrep minamoto,nyuuryoku,"\n"
objprm 0,minamoto
objprm 2,"改行に置換しました"
stop
Unicodeの32767文字以上のテキストファイルは複数に分割して改行に置換にするとよいと思いました。
解決とします。ありがとうございました。
|
|
2021/1/14(Thu) 13:14:40|NO.92071
あくまで応急処置ですが、winobjでメッセージボックスを作るのはどうでしょう?
処理はだいぶ面倒になりますが。
#include "hsp3utf.as"
#const WS_CHILD 0x40000000
#const WS_VISIBLE 0x10000000
#const WS_BORDER 0x800000
#const WS_HSCROLL 0x100000
#const WS_VSCROLL 0x200000
#const ES_AUTOHSCROLL 0x80
#const ES_AUTOVSCROLL 0x40
#const ES_MULTILINE 0x4
#const EM_SETLIMITTEXT 0xC5
#const WM_GETTEXTLENGTH 0xE
#const WM_GETTEXT 0xD
#const WM_SETTEXT 0xC
winobj "EDIT","",0,WS_CHILD|WS_VISIBLE|WS_BORDER|WS_HSCROLL|WS_VSCROLL|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_MULTILINE,150,150
id_edit=stat
h_edit=objinfo(id_edit,2)
sendmsg h_edit,EM_SETLIMITTEXT,10000000,0 //書き込める文字数の上限を1千万文字に(UTF-16なのでバイト数ではなく文字数)
button gosub "改行する",*label
stop
*label
gosub *gettext
strrep minamoto,":","\n"
sdim buf,strlen(minamoto)*2+2 //UTF-8からUTF-16に変換するためのバッファ
cnvstow buf,minamoto //変換
sendmsg h_edit,WM_SETTEXT,0,varptr(buf) //エディットボックスに更新した文章を反映
dim buf //バッファを解放
return
*gettext
//minamotoにエディットボックスの内容を反映
sendmsg h_edit,WM_GETTEXTLENGTH,0,0 //文字数を取得
size=stat+1 //末端にNULLを追加
sdim buf,size*2 //UTF-16は1文字2バイトなのでsizeの2倍のバッファを確保
sendmsg h_edit,WM_GETTEXT,size,varptr(buf) //エディットボックスから文字列を取得
minamoto=cnvwtos(buf) //UTF-16からUTF-8に変換
dim buf //バッファを解放
return
| |
|
2021/1/14(Thu) 13:15:42|NO.92072
あっと、すれ違いでした。
解決されたようですが、あくまでも参考までにということで。
|
|
2021/1/14(Thu) 13:32:38|NO.92073
沢渡様、追加の回答ありがとうございます。
#include "hsp3utf.as"
#const WS_CHILD 0x40000000
#const WS_VISIBLE 0x10000000
#const WS_BORDER 0x800000
#const WS_HSCROLL 0x100000
#const WS_VSCROLL 0x200000
#const ES_AUTOHSCROLL 0x80
#const ES_AUTOVSCROLL 0x40
#const ES_MULTILINE 0x4
#const EM_SETLIMITTEXT 0xC5
#const WM_GETTEXTLENGTH 0xE
#const WM_GETTEXT 0xD
#const WM_SETTEXT 0xC
winobj "EDIT","",0,WS_CHILD|WS_VISIBLE|WS_BORDER|WS_HSCROLL|WS_VSCROLL|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_MULTILINE,150,150
id_edit=stat
h_edit=objinfo(id_edit,2)
sendmsg h_edit,EM_SETLIMITTEXT,10000000,0 //書き込める文字数の上限を1千万文字に(UTF-16なのでバイト数ではなく文字数)
button gosub "改行する",*label
stop
*label
gosub *gettext
strrep minamoto,":","\n"
sdim buf,strlen(minamoto)*2+2 //UTF-8からUTF-16に変換するためのバッファ
cnvstow buf,minamoto //変換
sendmsg h_edit,WM_SETTEXT,0,varptr(buf) //エディットボックスに更新した文章を反映
dim buf //バッファを解放
return
*gettext
//minamotoにエディットボックスの内容を反映
sendmsg h_edit,WM_GETTEXTLENGTH,0,0 //文字数を取得
size=stat+1 //末端にNULLを追加
sdim buf,size*2 //UTF-16は1文字2バイトなのでsizeの2倍のバッファを確保
sendmsg h_edit,WM_GETTEXT,size,varptr(buf) //エディットボックスから文字列を取得
minamoto=cnvwtos(buf) //UTF-16からUTF-8に変換
dim buf //バッファを解放
return
のプログラムを分析してみます。
| |
|
2021/1/14(Thu) 13:39:35|NO.92074
すこし関係ある話ですが翻訳の実行過程も置換命令の応用ですね。
|
|