【入門編】LENGTH関数とSTG関数による動的文字列のサイズ取得 – PL/Iの基本構文とデータ制御実践ガイド

PL/Iの動的文字列サイズ:LENGTH関数とSTG関数、あなたはどっちを選ぶ?

JavaやCOBOLの世界からようこそ!メインフレームの世界へ足を踏み入れたばかりのあなた、PL/Iってなんだか独特で、最初は戸惑うことも多いかもしれませんよね。でも大丈夫。一つずつ紐解いていけば、そのパワフルさがきっと好きになるはずです。

今日は、PL/Iで扱う「動的な文字列」のサイズを調べる、とっても便利な2つの関数、`LENGTH`関数と`STG`関数について、その違いと使い分けを、実例を交えながら優しく解説していきます。

PL/Iの「文字列」って、ちょっと特別?

まず、PL/Iの文字列を理解するために、少しだけデータ格納の仕組みに触れておきましょう。他の言語で「文字列」と聞くと、通常は文字の並びそのものを指すことが多いですよね。PL/Iでは、文字列にもいくつかの「属性」を持たせることができます。

例えば、固定長の文字列(CHARACTER)と、可変長の文字列(VARYING)があるんです。

  • 固定長文字列 (CHARACTER(n)): あらかじめ決まった長さ `n` の領域が確保されます。たとえ短い文字列を入れても、指定された長さぴったりに「パディング」されて格納されます。
  • 可変長文字列 (VARYING(n)): 最大で `n` 文字まで格納できるのですが、実際に格納されている文字数(現在長)は、その都度変わります。この「現在長」と「最大長」を管理するのが、PL/Iの得意技の一つなんです。

今回の主役である`LENGTH`関数と`STG`関数は、この「可変長文字列」のサイズを調べる際に特に活躍します。

1. `LENGTH`関数:今、どれだけ文字が入ってる?(現在長を知りたい!)

`LENGTH`関数は、その名の通り、可変長文字列に現在格納されている文字数を返します。
これは、他の言語でいうところの、Stringオブジェクトの`length()`メソッドや`strlen()`関数に似た感覚で捉えていただいて良いでしょう。

例えば、`DECLARE MY_STRING VARYING(100);` という変数があったとします。
`MY_STRING`には最大100文字まで入りますが、現時点で「Hello」という5文字の文字列が入っている場合、`LENGTH(MY_STRING)`は「5」を返します。もし「PL/I is fun!」という11文字の文字列が入っていれば、`LENGTH(MY_STRING)`は「11」を返します。

コード例で見てみよう!

/ 動的文字列の現在長を取得するサンプル /
DCL MY_STRING VARYING(255); / 最大255文字まで格納できる可変長文字列 /
DCL CURRENT_LEN FIXED BINARY(31); / 現在長を格納するための変数 (32bit符号なし整数) /

/ 初期化 /
MY_STRING = ‘Hello PL/I’; / 文字列を代入 /

/ LENGTH関数で現在長を取得 /
CURRENT_LEN = LENGTH(MY_STRING);

/ 結果の表示 (例: PUT LIST) /
PUT SKIP LIST(‘MY_STRING の現在長は: ‘, CURRENT_LEN, ‘文字です。’);

/ 文字列を変更 /
MY_STRING = ‘A very long string that might exceed some limits, but not this one!’;

/ 再度LENGTH関数で現在長を取得 /
CURRENT_LEN = LENGTH(MY_STRING);

PUT SKIP LIST(‘MY_STRING の変更後の現在長は: ‘, CURRENT_LEN, ‘文字です。’);

/ 空文字列の場合 /
MY_STRING = ”;
CURRENT_LEN = LENGTH(MY_STRING);
PUT SKIP LIST(‘MY_STRING が空文字列の場合の現在長は: ‘, CURRENT_LEN, ‘文字です。’);

このコードでは、`MY_STRING`に文字を代入するたびに`LENGTH`関数を使って、その時点での文字列の長さを取得しています。`PUT LIST`は、結果を画面に出力するための命令だと思ってください。

`LENGTH`関数は、

  • 「今、この文字列には何文字入っているんだろう?」
  • 「この文字列を処理するために、どれくらいのバッファが必要かな?」
  • 「特定の条件で文字列を切り出したいけど、どこまでが有効なデータかな?」

といった、「実質的な文字数」を知りたい場合に迷わず使いましょう!

2. `STG`関数:どれくらいの「場所」が確保されてる?(割り当て済みストレージサイズを知りたい!)

一方、`STG`関数は、ちょっと違った視点からサイズを教えてくれます。
`STG`関数は、可変長文字列変数に割り当てられている、実際のストレージサイズ(バイト数)を返します。

PL/Iの可変長文字列(VARYING)は、内部的に「文字列データ本体」と「その長さを管理するための情報(現在長と最大長)」を一緒に保持しています。`STG`関数は、この全体が確保しているメモリの総量を教えてくれるのです。

これは、他の言語ではあまり直接的に意識しない部分かもしれません。例えば、JavaのStringオブジェクトは内部でchar配列を持っていますが、その配列の実際のサイズを直接取得するような関数は一般的ではないですよね。

`STG`関数のポイント

`STG`関数が返す値は、文字列の現在長そのものではありません。
可変長文字列 `VARYING(n)` では、通常、以下のサイズのストレージが確保されます。

  • 文字データ本体: 最大 `n` バイト(実際には `n` 文字分)
  • 長さ情報: 2バイト(現在長を格納するため)
  • 最大長情報: 2バイト(最大長を格納するため)

したがって、`STG(MY_STRING)`が返す値は、`MY_STRING`の最大長 `n` に、長さ情報を格納するための4バイト(2バイト+2バイト)を加えたものになります。

コード例で見てみよう!

/ 動的文字列の割り当て済みストレージサイズを取得するサンプル /
DCL MY_STRING VARYING(100); / 最大100文字まで格納できる可変長文字列 /
DCL STORAGE_SIZE FIXED BINARY(31); / ストレージサイズを格納するための変数 /

/ 文字列を代入 /
MY_STRING = ‘Hello’; / 現在長は5文字 /

/ STG関数で割り当て済みストレージサイズを取得 /
STORAGE_SIZE = STG(MY_STRING);

/ 結果の表示 /
PUT SKIP LIST(‘MY_STRING の割り当て済みストレージサイズは: ‘, STORAGE_SIZE, ‘バイトです。’);
PUT SKIP LIST(‘(参考: 最大長は 100文字, 現在長は ‘, LENGTH(MY_STRING), ‘文字です。)’);

/ 文字列を長くしてみる /
MY_STRING = ‘This is a longer string.’; / 現在長は24文字 /

/ 再度STG関数で割り当て済みストレージサイズを取得 /
STORAGE_SIZE = STG(MY_STRING);

PUT SKIP LIST(‘MY_STRING の変更後の割り当て済みストレージサイズは: ‘, STORAGE_SIZE, ‘バイトです。’);
PUT SKIP LIST(‘(参考: 最大長は 100文字, 現在長は ‘, LENGTH(MY_STRING), ‘文字です。)’);

/ 最大長まで入れてみる /
MY_STRING = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789’; / 現在長は62文字 /
MY_STRING = MY_STRING || MY_STRING || MY_STRING || MY_STRING; / 62 4 = 248文字 (最大長100なので一部は切り捨てられる) /

/ 実際には、VARYING(100)なので、最大100文字しか入らない /
MY_STRING = ‘A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789I123456789J123456789’; / 現在長100文字 /
STORAGE_SIZE = STG(MY_STRING);
PUT SKIP LIST(‘MY_STRING が最大長(100文字)の場合の割り当て済みストレージサイズは: ‘, STORAGE_SIZE, ‘バイトです。’);
PUT SKIP LIST(‘(参考: 最大長は 100文字, 現在長は ‘, LENGTH(MY_STRING), ‘文字です。)’);

この例を見ると、`MY_STRING`にどんな長さの文字列を入れても、`STG(MY_STRING)`が返す値は、基本的には `最大長 + 4` バイト(つまり `100 + 4 = 104` バイト)になることがわかります。
これは、PL/Iが`VARYING(100)`という宣言を見たときに、最大100文字を格納できるだけのメモリ領域と、その長さを管理するための領域を、あらかじめ確保しているからです。

`STG`関数は、

  • 「この変数には、一体どれくらいのメモリが割り当てられているんだろう?」
  • 「メモリ使用量を把握したい、あるいは最適化したい」
  • 「(まれに)PL/Iの内部的なデータ構造を意識した処理を行いたい」

といった、「確保されているメモリの総量」を知りたい場合に役立ちます。

結局、どっちを使えばいいの?

ほとんどの場合、あなたが知りたいのは「今、文字列として有効な文字は何文字あるのか?」ということだと思います。その場合は、迷わず `LENGTH`関数 を使いましょう。これは、他の言語の感覚にも一番近いですし、直感的で分かりやすいです。

一方、`STG`関数は、PL/Iの可変長文字列の内部的なメモリ管理の仕組みを理解するために、あるいは特殊なメモリ管理の必要性がある場合に使う関数です。普段のプログラミングで「この文字列の長さは?」と聞かれたら、`LENGTH`関数で十分なケースがほとんどです。

まとめ:PL/Iの「動的文字列」をマスターしよう!

今日は、PL/Iの`LENGTH`関数と`STG`関数について、その違いと使い分けを解説しました。

  • `LENGTH(文字列変数)`: 現在格納されている文字数を知りたいときに使う。
  • `STG(文字列変数)`: 変数に割り当てられているストレージの総量(バイト数)を知りたいときに使う。

メインフレームのレガシーシステムは、一見すると難解に見えるかもしれませんが、PL/Iのこれらの関数のように、一つ一つの仕様を丁寧に理解していけば、その奥深さと便利さがきっと見えてくるはずです。

ぜひ、今回の解説を参考に、実際のPL/Iプログラムでこれらの関数を試してみてくださいね。きっと、あなたのPL/Iライフがより豊かになるはずです!

タイトルとURLをコピーしました