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


HSPTV!掲示板


未解決 解決 停止 削除要請

2008
0528
naoテキストを複数の区切り文字で区切って、配列変数に入れたい6解決


nao

リンク

2008/5/28(Wed) 22:41:37|NO.16237

こんにちは。naoともうします。

プログラム用に加工していない(つまり、普通の)英文のテキストを読み込んで、
「,(カンマ)」「.(ピリオド)」「改行」を区切りとして、
配列変数に代入したいと考えています。

例えば、以下のようなテキストだとすると、

It is one hour thirty Universal Time. I'm Jim Tetter in
Washington.(改行)
(改行)
Rain has slowed Chinese rescue teams who are working to save
thousands of people buried under collapsed buildings across
<Sichuan> province.


以下のA案あるいはB案のように、配列変数に代入したいのです。

A案
a(0)="It is one hour thirty Universal Time."
a(1)=" I'm Jim Tetter in Washington.(改行)"
a(2)="(改行)"
a(3)="Rain has slowed Chinese rescue teams who are working
to save thousands of people buried under collapsed buildings
across <Sichuan> province."

B案(区切り文字そのものも単独で変数に代入する)
a(0)="It is one hour thirty Universal Time"
a(1)="."
a(2)=" I'm Jim Tetter in Washington"
a(3)="."
a(4)="(改行)"
a(5)="(改行)"
a(6)="Rain has slowed Chinese rescue teams who are working
to save thousands of people buried under collapsed buildings
across <Sichuan> province"
a(7)="."

区切り文字が一種類なら、getstrを使ってできたのですが、
区切り文字が複数になると、どうしたらよいかわからず、困ってい
ます。

また、改行の扱いもよくわかっていません。
(mes命令で、\nを表示すれば改行されることはわかるのですが・・・)

ヒントだけでもご教授いただければ、幸いです。
どうかよろしくお願いいたします。



この記事に返信する


yamineko

リンク

2008/5/28(Wed) 23:11:35|NO.16244

はじめまして。

目的の文字や改行コード(これも数値がある。)をどこかのサイトで調べて、
一バイトずつpeek命令で調べるのはいかがでしょうか?

改行コードは、文章を作成した環境によって異なるようで、
Windowsをお使いなら(たぶん)CR+LF
(キャリッジリターン、ラインフィード)の2バイトだと思います。
(コードは検索してね)

きっと、アルゴリズム等は、もっと優秀な方がいらっしゃいますので、
あとお任せします。 ^^;



begriff

リンク

2008/5/29(Thu) 18:57:22|NO.16271

こんにちは begriff と申します。
peekでやる方法について例を一つ提示させていただきます。


buf={" Hot Soup Processor (commonly abbreviated "HSP") is a programming language from Japan that was originally developed in 1994. It was originally based on BASIC, but has diverged significantly from those roots over the years. It is freeware as of 1996, and now is open source (OpenHSP) under the BSD licenses. HSP is used to teach programming in Japanese schools, and because it is freeware, it was a popular programming language for doujin soft in the late 1990s. "} sdim datum,512,512//分量に合わせて拡張してください。 len=strlen(buf) num=0 head=0 head_past=0 repeat data=peek(buf,head)//データを順番に一文字ずつ取り出す if data=13{//改行コード( 0x0d )なら 以下実行  if strmid(buf,head_past,head-head_past)!""{ datum(num)=strmid(buf,head_past,head-head_past) num++ } datum(num)="\\n"//見えるように今回はしました num++ head+=2 head_past=head rei=1 } if data='.'||data=','||data=':'||data=';'{//簡単に区切り文字を追加することができる datum(num)=strmid(buf,head_past,head-head_past+1) num++ if peek(buf,head+1)=' ':head+ head+ head_past=head rei=1 kai=1 } if rei=0:head++ rei=0 if head>=len:break//読み取りヘッダが素体bufの長さと同時に抜け出す loop repeat num//配列を表示 color if datum(cnt)="\\n":color 176,176,176 mes datum(cnt) loop

peekで解析などをするときは、感覚的ですが(私は)データの記録されたテープを最初から呼んでいくことを
想像してスクリプトを組んでいます。つまり変数の先頭の文字から一文字ずつ順番に読み取って行き
ある一定の文字にさしかかったときに一定の処理をするようにしています。(わかりずらいですね^^;)
変数名もそれにちなんでhead (磁気記録装置の磁気ヘッドから) としています。



nao

リンク

2008/5/29(Thu) 22:59:34|NO.16286

やみねこさん、SYAMさん、begriffさん、
本当に丁寧にアドバイスやスクリプトを教えてくださってありがとうございます!
いま、スクリプトを試す時間がないので、とりいそぎお礼まで。

明日、実際にいじって、改めてお礼を申し上げます。



SYAM

リンク

2008/5/30(Fri) 00:31:59|NO.16291

恐縮です…では、これ幸いと ちゃんとしたのを貼って前のバグ付きは削除しときます。さらに解説をつけます。
実はさらにバグ見つけたし。どうなってんだ私orz

◇変数について
NB_SEPARATOR は区切り文字の数、
sepa()は区切り文字列です。1文字でなくてもOK。
sepaの添え字の若い順から優先的に判断しますので、もし区切り文字列が他の区切り文字列をすべて内包するような場合は、長いほうを先にするとよいはずです。
srcは元の文字列。
dest()は結果の文字列の配列です。
separatorとindex は、サブルーチンに値を渡すための変数です。deffuncなどで関数にすれば要らなくなり、スマートになるでしょう。

◇やってること
まず sepaidx 配列に、各区切り文字列の最初の出現位置を代入します。instr関数を使っています。もし見つからない場合は出現位置を「一番遠く」にします。HSPの整数の最大値を代入しています。
次に、sepaidxの中で一番小さいものを調べ、前回切り取った位置(最初はsrcの先頭)から、そのsepaidxが指しているところまでを切り出します。 strmid関数です。
次に、切り出した位置を指していたsepaidxを、次の区切り文字の位置を指すように更新します。なければ一番遠くとします。
すべての区切り文字が見当たらなくなるまでこれを繰り返し、最後に残った分をdestの最後の要素とします。
以上。

この方法だと、instrによって区切り文字を探すのでワリと効率がよいはずです。
しかも、区切り文字の種類が増えても計算量があんまり変わりません。増やすのも簡単です。
すこしだけややこしい処理ではありますが。。


#define INTMAX 0x7ffffff #define NB_SEPARATOR 4 sdim sepa,NB_SEPARATOR dim sepaidx,NB_SEPARATOR sdim dest,64,16 src="Hello,baby.\nWhat are you doing?\nThis beat is non-stop.\n" sepa(0)="\n" sepa(1)="," sepa(2)="." sepa(3)="?" nb_dest=0 // 出力結果の数 sepa_end=0 // 検索し終えた区切り文字の数 repeat NB_SEPARATOR separator=sepa(cnt) : index=0 gosub *GET_NEXTINDEX : sepaidx(cnt)=i loop *CUTTING_NEXT if(sepa_end<NB_SEPARATOR){ nextidx=INTMAX repeat NB_SEPARATOR if(sepaidx(cnt)<nextidx){ nextidx=sepaidx(cnt) minidx=cnt } loop sepalen=strlen(sepa(minidx)) dest(nb_dest) = strmid(src, idx, nextidx-idx+sepalen) nb_dest++ idx=nextidx+sepalen repeat NB_SEPARATOR if(sepaidx(cnt)=nextidx){ separator=sepa(cnt) : index=idx gosub *GET_NEXTINDEX : sepaidx(cnt)=i } loop goto *CUTTING_NEXT } dest(nb_dest)=strmid(src, idx, INTMAX) //表示 repeat 16 mes strf("%02d|",cnt)+dest(cnt) loop stop *GET_NEXTINDEX i=instr(src, index, separator) if i<0 : i=INTMAX:sepa_end++:return i=index+i:return



ひまつぶし

リンク

2008/5/30(Fri) 22:50:59|NO.16327

> B案(区切り文字そのものも単独で変数に代入する)


buf = "It is one hour thirty Universal Time. I'm Jim Tetter in Washington.\n\nRain has slowed Chinese rescue teams who are working to save thousands of people buried under collapsed buildings across <Sichuan> province." notesel buf dim i dim x repeat noteinfo (0) getstr a(x), buf, i, ',' if stat { if stat = 13 { getstr a(x), buf, i, '.' i + strsize x++ if stat ! 13 { a(x) = "." x++ continue - 1 } } else { i + strsize x++ a(x) = "," x++ continue - 1 } } else { getstr a(x), buf, i, '.' if stat { i + strsize x++ a(x) = "." x++ continue - 1 } else { break } } loop repeat x mes "a("+cnt+")=\"" + a(cnt) + "\"" loop



nao

リンク

2008/6/1(Sun) 10:59:08|NO.16353

お礼が遅くなって申し訳ありません。

それぞれ実際に試させていただきました。

>やみねこさん
早々とコメントをいただき、ありがとうございました。
こんな質問に答えてもらえるかな・・・?と思っていたときに、
すぐにコメントをくださったので、うれしかったです。

>begriffさん
直感的にわかりやすいスクリプトを組んでいただき、ありがとうございました。
スキャナのように端から徐々に読んでいくというイメージですね。
非常にわかりやすいので、しっかり理解して、自分でも組めるようにしたいと思います。

>SYAMさん
非常に丁寧な解説をおつけくださり、ありがとうございました。
区切り文字の種類が増えても計算量があまり変わらないという、
非常にスマートなスクリプトですね。
こういうやり方があるのかーと感心させられました。

>ひまつぶしさん
僕があきらめたgetstrを使う方法を提示してくださり、ありがとうございました。
どう考えて無理、と思っていたのですが、できるんですね。
まだまだ勉強不足であることがわかりました。精進します。

このたびは、本当に勉強になりました。どうもありがとうございました。



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