C言語関係掲示板

過去ログ

No.171.COBOLのような文字列の処理について


No.1107

COBOLのような文字列の処理について
投稿者---ハイド(2002/02/27 15:13:21)


C言語初級者です。
COBOLには集団項目というのがあり、
01 level1.
02 level21 pic x(2).
02 level22 pic x(2).
この level1 に文字列 "ABCD" を転送すると、自動的に
level21 に 文字列 "AB", level22に 文字列 "CD"が入ります。

C言語で、この処理を簡単にするには、どうすればよいのでしょうか?

No.1110

Re:COBOLのような文字列の処理について
投稿者---B.Smith(2002/02/27 16:20:15)


こんにちは。

COBOLの集団項目は、Cの構造体に当たります。また、REDEFINESは共用体に当たります。
01 level1.
   02 level21 pic x(2).
   02 level22 pic x(2).

これは、
struct  TAG_FIELD {
    char    level21[2];
    char    level22[2];
};

というような感じになります。構造体に関して、詳しくはこちらをご覧ください。
処理例.
文字"ABCD"を構造体により"AB"、"CD"に分離する
#include <stdio.h>
#include <memory.h>

struct  TAG_FIELD {     /* 01 level1.              */
    char    level21[2]; /*    02 level21 pic x(2). */
    char    level22[2]; /*    02 level22 pic x(2). */
};

void main(void )
{
    struct TAG_FIELD    level1; /* 実体定義 */

    /* "ABCD"を構造体にコピー */
    memcpy(&level1,"ABCD",4);    /* MOVE "ABCD" TO level1. */

    /* 内容の表示 */
    /* "AB"、"CD"と表示される */
    printf("%c%c\n",level1.level21[0],level1.level21[1]);
    printf("%c%c\n",level1.level22[0],level1.level22[1]);

}

ここでは文字列をセットする時、標準ライブラリの関数memcpyを使用しています。この関数は、指定の位置からバイト単位での内容のコピーを行います。

level1は、構造体であっても関数memcpyから見ると連続した4バイトの領域でしかありません。ここに、文字"ABCD"をまとめてコピーし、のちにlevel21、level22を参照すれば"AB"と"CD"に分離できます。

構造体に文字列をセットする方法について、構造体同士の代入を許しているコンパイラであれば、以下のようにキャストを利用してコンパイラを欺く方法もあります。
    level1 = *(struct TAG_FIELD *)"ABCD";





No.1119

Re:COBOLのような文字列の処理について
投稿者---ハイド(2002/02/28 14:32:35)


ということは、
memcpy(&level1.level22,"EF");
とすれば、
MOVE "EF" TO lebel22.
ということになるのでしょうか?

No.1120

Re:COBOLのような文字列の処理について
投稿者---B.Smith(2002/02/28 15:59:17)


こんにちは。

構造体が
struct  TAG_FIELD {
    char    level21[2];
    char    level22[2];
};

であるとして、構造体全体へのコピー、構造体内の変数へのコピーを行う場合は、以下のようになります。
    struct TAG_FIELD    level1;

 "ABCD"をlevel1にコピー
    MOVE "ABCD" TO level1.  → memcpy(&level1,"ABCD",4);
                                      ↑
 "AB"をleven21にコピー
    MOVE "AB" TO level21.   → memcpy(level1.level21,"AB",2);
                                      ↑
 "AB"をleven22にコピー
    MOVE "AB" TO level22.   → memcpy(level1.level22,"AB",2);
                                      ↑

関数memcpyの一番目の引数はコピー先のポインタ、二番目の引数はコピー元のポインタ、三番目の引数はコピー内容のサイズ(バイト単位)です。各引数を単純に対応付けると、
    MOVE  A  TO  B.    →  memcpy(  B  ,  A  ,  Aのサイズ );

という感じになります。

level1のような構造体の変数は、変数そのものを表すので、関数memcpyの引数に指定する場合には、level1の先頭アドレスを引数とするためにアンパサンドが必要です。
    &level1  ← (構造体の変数level1の領域の「先頭アドレス」を表す)

level21、level22は、構造体内部でchar型の配列として定義されていますので、配列の先頭アドレスを引数とするには、それぞれ、
    level1.level21  ← (構造体内の変数level21の領域の「先頭アドレス」を表す)
    level1.level22  ← (構造体内の変数level22の領域の「先頭アドレス」を表す)

という表現になります。

最初の書き込みで、

>C言語初級者です。

と、言われていたので、もし、ここまでの内容が難しいと感じたら、こちらをご覧になってみてください。大変分かりやすいです。

・ポインタについて
・構造体について

COBOLを知っているのであれば、構造体は比較的理解し易いと思います。
ポインタと構造体はC言語の山場ですが、これらを理解出来ればC言語を全て理解出来た、と言っても過言では無いと思います。がんばってください。


No.1123

Re:COBOLのような文字列の処理について
投稿者---ハイド(2002/02/28 17:35:21)


ありがとうございました。

いままで、この質問のようなことはできないと思っていましたので、
関数をわざわざ作っていたのです。

勉強になりました。

No.1128

Re:COBOLのような文字列の処理について
投稿者---ハイドの師(2002/03/01 09:40:50)


こんにちは。わたくし、ハイドのCOBOLの師匠格にあたるものです。
弟子がいつもお世話にお世話になっております。

レスを拝見させていただき、ひとつ疑問が浮かびましたので、
おじゃまさせていただきます。

あのケースで

01 level1.
02 level21 X(2).
02 level22 9(2).
02 level23 X(2).

MOVE "123456" to level1.

とすれば、
level21 が "12"
level22 が 34
level23 が "56"

となり、level22はそのまま計算に使えます。

また、数字項目は C では int型に相当すると思いますが、
構造体にした場合に、そのまま 集団項目に連続した文字列として
memcpy はできないと思ったのですが、いかがでしょうか?

No.1133

Re:COBOLのような文字列の処理について
投稿者---B.Smith(2002/03/01 15:18:05)


こんにちは。

構造体のメンバに数値変数を含む場合は、確かにmemcpyでは無理ですね。
Cでは、COBOLのようにキャラクタ・数値の自動変換を行わないので、文字列と数値を同一視することはできません。そのため、

>MOVE "123456" to level1.
>
>とすれば、
>level21 が "12"
>level22 が 34
>level23 が "56"
>
>となり、level22はそのまま計算に使えます。

という扱い方は、Cでは出来ません(ただし、純粋な文字列編集であれば問題はありません)。
演算時に文字列・数値相互変換する機構を用意すれば、まったく不可能なわけではありませんが、Cの処理としては効率が悪すぎます。

一般的には、数値変数は個別に確保しておき、必要な時に文字列に編集します。例えば、
     long     Cnt;        /* 在庫数カウント */
     char     Buf[256+1]; /* 出力領域 */
               ・
               ・
               ・
     Cnt++;
               ・
               ・
               ・
     sprintf(Buf,"        在  庫  数 :%ld",Cnt); /* 出力のための編集 */


このデータの扱い方の相違は高級言語と低級(中級)言語の差です。高級言語から移ってきた人は面倒に感じるかもしれませんが、これは処理の効率性をマシン(アッセンブラ)レベルで考慮したプログラムが作成できる、Cの特徴の一つです。
お弟子さんには、そうお伝えください。



No.1134

Re:COBOLのような文字列の処理について
投稿者---ハイドの師(2002/03/01 15:38:41)


Smithさんは、C・COBOL 共に使えるのですね。

私も C は齧った程度ですが、なかなか上達しません。

ご指導、感謝します。

戻る


「初心者のためのポイント学習C言語」 Last modified:2002.05.14
Copyright(c) 2000-2002 TOMOJI All Rights Reserved