回答箱 No.99-3:文字列を中央で2分割したい

  ◆ 質問箱 No.99  質問者: 藤原 良允   1999年08月 211号 P.13
      ◆ 質問箱 目次へ
No.99-3   文字列を中央で2分割したい 回答者
  入川 精二
1999年09月
212号 P.19
   ◆ No.99(1999年 8月号)の回答-3
  • 全角半角が混在する文字列を2分割するのは簡単なようでなかなかうまく行かないのですね。それと‘SuperPIPS’には文字数を得る関数‘LEN’がありますが「桁数」を得る関数がありません。分割する位置を決められないのです。
    (ThePIPSなら、文字数:KLEN,桁数:LENを使い分けることが出来ます)
    それで、何がなんでも関数を使って切り分けようという「力技」的な方法と、  なるべく関数を使わないで PIPS のコマンドを主体にした「PIPS流」の方法をご紹介します。


<<関 数 依 存 の 方 法 >>

  • 幸いなことに、SuperPIPS には‘JEDIT’という関数があります。コマンド解説書の文字列関数の所(P.484)を見ても要領を得ない説明がありますが、実際に使ってみると文字コードの第1バイトと第2バイトの記号2文字が得られることが分かります。
    例えば LET V1=JEDIT(";ア";) とすると V1 には‘/1’が格納され  ます。「A」 なら‘.A’、「1」 なら‘.1’、「A」 なら‘#A’、「亜」 なら‘0!’といった具合です。半角文字は全て‘/’か‘.’が1桁目にあります。これを利用すれば文字の全角半角を判別することが可能です。 (実際にはさらにその ASCII  コードを使います)

  • 文字列を1文字目から順に全角か半角か判別し、全角なら 2 を、半角なら 1を加算して行くと何文字目で25桁を超したかが分かります。分割するのはその位置です。1文字ずつチェックするので少し時間はかかりますが、安全確実な方法です。コンピュータは面倒臭いなどといわずにやってくれます。

  • さて、関数を使うのでオートプログラムでないと実行できません。下のプログラムは分割した文字列を同じ行の別の列に書き込むようになっていますが、実際の場面に応じて如何様にもアレンジできるでしょう。
 プログラムの12行目で、文字列の中の1文字ずつを取り出してそれを文字コードに変換し、更にその1桁目のアスキーコードを X2 に格納します。
 X2 が 46 か 47 なら 半角、それ以外は全角として桁数を積算します。
 桁数加算の都度結果をチェックして、25か25を超えていれば文字列を振り分ける作業に入ります。25桁目と26桁目にまたがって全角文字があれば、26桁目までの左側と27桁目以降の右側に分割します。
 分割した文字列はここでは別の列に書き込むようにしていますが、書込み位置を変えれば、どこにでも書き込めます(文書形式でも可能です)。

 【プログラム−SuperPIPS】
    1 <文字列分割1>
    2          G;?;
    3          CAL;HOME;
    4          ACCEPT ";元データの列は? ";,X11;
    5          ACCEPT ";文字列の左半分を格納する列は? ";,X12;
    6          ACCEPT ";文字列の右半分を格納する列は? ";,X13;
    7          FOR X20=H TO T;
    8             LET V1="; ";;
    9             LET X3=0;
   10             LET V1=[X20,X11];
   11             FOR X1=1 TO LEN(V1);
   12                LET X2=ASCII(JEDIT(MID$(V1,X1,1)));
   13                    IF X2<>46 AND 47 THEN GOTO 全;
   14 $半:           LET X3=X3+1;  GOTO CHK;
   15 $全:           LET X3=X3+2;
   16 $CHK:             IF X3>=25 THEN GOTO 分割;
   17             NEXT;
   18 $分割:      LET [X20,X12]=LEFT$(V1,X1);
   19             LET [X20,X13]=RIGHT$(V1,X1+1);
   20          NEXT;
   21 STOP;


<<P I P S コ マ ン ド 中 心 の 方 法 >>

  • 関数を使ってやるのが正統的な方法とするなら、ゲリラ的な方法もあっていいかと思います。
     BASIC的手法  VS  PIPS的手法 の対決ですね )
  • 50桁ある対象の列を思い切って‘CF’で26桁にします。残ったのは文字列の左半分です。26桁目と27桁目に跨っている全角文字は消えます。改めてその文字列の「文字数」を読めば分割位置が分かります(ここは関数が必要)。
    後は左半分と右半分をどこに書き込むかだけです。
  • 下のプログラムでは、対象の表に予め26桁の列を2列用意してあります。

 【プログラム−SuperPIPS】
   1 <文字列分割2>
   2         G;?;                                   /* 対象の表を呼び出す */
   3         CAL;HOME;                          /* スケールを列桁数にする */
   4          ACCEPT ";分割対象の列番号は? ";,X11;
   5          ACCEPT ";分割文字列の左半分を書込む列番号は? ";,X12;
   6          CCEPT ";分割文字列の右半分を書込む列番号は? ";,X13;
   7         CPB;*;                               /* サブバッファにコピー */
   8         CF;%X11;26;                          /* 対象列を26桁にする */
   9         SB;                                  /* 元の表をメインにする */
  10 $分割:  FOR X1=1 TO T;
  11            LET X2=LEN({X1,X11});        /* サブの文字列の桁数を読む */
  12            LET [X1,X12]=LEFT$([X1,X11],X2);     /* 左半分を書き込む */
  13            LET  [X1,X13]=RIGHT$([X1,X11],X2+1); /* 右半分を書き込む */
  14         NEXT;
  15 STOP;

〜〜〜〜〜〜〜〜  「PIPS的手法」の勝ち  ですかね

戻る