横山実習室へ戻る
以下にC言語からJAVA言語にプログラムを変換する時の要点 を 述べるが、それを機械的に変換するプログラムの研究成果を まず、第1段階として、 ・字下げ SrCnv.java ・単純な置換 CnvBS.java ・各種変換  CnvEX.java をlinecnv.jarとして示す。 C言語をJAVA言語に変換する
このプログラムは、行単位に文を解釈するために、各種の問題点が
あるが、一応簡単な手作業の代替には十分である。
しかし、このプログラムの開発でわかったことであるが、この方法
では、C言語の複雑な入れ子構造のプログラムを変換する時は限界
を感ずる。
変換ロジックを木構像に改良
第2段階として、プログラム全体を木構造に変換し、入れ子構造を
意識して、文の解釈を行うことにより、Goto文を break aa;
continue bb; に変換するなど、改良したものを、srcnv.jar に
示す。
次に、C言語からJava言語に変換するときの各種のポイント を以下にのべる。

C言語からJAVA言語にプログラムを変換する時の要点
1.概要
  C言語からJAVA言語にプログラムを変換する場合、問題となる事項と解決策の概要
 は以下の通りである。
    1.1 命令単位の変換
   C言語の文法はあいまいで、許される記述の許容範囲は広いが、JAVA言語では細かに
   文法で規定がある。
   しかし、基本的には概念は似ているので、C言語の標準的な記述に書き換えれば、
   ほとんどの命令はJAVA言語でも実行できる。
    ① 演算と代入の式
    int, long, float, double は 値の範囲の規定を厳密に考えなければ、そのまま
    で、変換する所はない。
    c言語の char は Java言語のcharに対応させる場合とStringに対応させる場合
    があるが、charの配列はStringに対応させる方が良い場合が多い。
    ② 条件式
    c言語では 0 が false、0以外が true なのに対して、Java言語では厳密
    に結果が boolean になることが要求される。
すなわち、c言語では比較条件式が省略されているので、たとえば以下のように
    変換する。
    変数が クラスの参照の場合は !=null、 数式の値の場合は !=0 を付加して
    条件式になる様に変換する。
    例
c言語 Java言語
      if( z ) .... if(z!=null) ....
if( i%2 ).... if( i%2 !=0 ).....
    ③ , 演算子
c言語では文と文をカンマで結合して、if文、for 文の実行範囲を{ ...} の形式を
    使用しないで、複文をまとめて制御することができる。
    Java言語ではfor文の(....)内でのみ、カンマ演算子を適用できる。
    したがって、for文以外のカンマ演算子は、ブロック{ ....; ...; } を使って実行範囲を
    制御するように変換する必要がある。
           ④ for文 
    基本的には、互換があるが、ループ条件の文中にカンマ演算子が使えないので、
    以下の例のような、変換が必要な場合がある。
    c言語  for(z=r->z;z=(Z)z->next,z!=r->z; ) ......
  Java言語 for(z=r.z,z=(Z)z.next;z!=r.z;z=(Z)z.next) .........
  ⑤ 構造体
構造体はクラスに変換する。
    c言語 typedef stract AAA{ int a; char *b };
  Java言語 class AAA{ int a; char[] b };
この構造体がファイル内に限って使用されている場合は内部クラスとする。
    構造体がファイルをまたがって使用されている場合は独立したクラスとする。
     1.2 マクロ記述の変換
   JAVAではマクロ機能がないので、手作業またはツールでソースに展開形で記述する
   変換が必要である。
 1.3 ポインターの扱い
   構造体のポインターはJavaでは クラスの参照に対応させる。したがって −>
   は . に変換すればよい、( 例  z->a z.a )
int long float double などの基本データに対するポインターは、配列で対応
   する。 
      c言語 int * aaa;
    Java言語 int[] aaa;
 1.4 配列の扱い
   配列の定義の方法、初期値の設定方法に、少しの違いがあるが、その点を注意
   すれば、そのままJavaの配列で対応させることができる。
      ① 基本型の配列
      c言語 int aaa[50];
    Java言語 int[] aaa=new int[50];
  ② 構造体の配列
      c言語 AAA aaa[50];
    Java言語 AAA[] aaa=new AAA[50];
 1.5 インクルード(INCLUDE)の扱い
   構造体は独立したクラスまたは、内部クラスに、定数は独立したインターフェース
   または、本体に組み込む、その他は本体に展開することで対応できる。
 1.6 グローバル変数(EXTERN)の扱い
   JAVAの構造は、基本的にC のファイル単位にクラスにし、EXTERNで関連するファイル
   はすべて、順に一列に継承することで対応できる。
 1.7 C言語で提供される関数の扱い
   数学的な関数は、Java の Mathクラスを使用し、それ以外は個別に代替できる
   Javaのクラスを見つけるか、独自のクラスを作成することで対応できる。
 1.8 スコープの違いに起因する問題
   C言語のスコープとJAVA言語のスコープは微妙な違いがあります。
   JAVAでは自動変数の定義で、ブロックの外の変数と一致した場合、エラーとなり、
   C言語ではブロックの外と中で同一変数を定義すると別々の変数としてエラー
   になりません。
     以上、大雑把な変換のイメージを示したが、以下では具体的なプログラムの部分を
 とりあげて変換方法を解説する。
  2. 具体的な変数定義の変換例 
1.1 プロトタイプ
bool isLoon2(Z*zdoor, Z*zteritoty,int t);
void destroyEye(Z*z);
void markGflag(F *f,int flag);
void reseteye( Z *z) ;
int arm( Z *z);
void markhot(Z *z,int) ;
上記はC言語のプロトタイプの部分である、JAVA言語ではプロトタイプは必要ないが、
1.6 グローバル変数(EXTERN)で説明したようにすべてのプログラムを縦に順番に
継承した構造にするため、先祖の関数は子孫のプログラムで参照できるが、子孫の関数を
先祖で参照する場合は abstract 宣言したメソッドを定義する必要がある。
例 abstract int arm( Z z );
1.2 外部変数
  int mainKey;
Z *Zattack,*Zdefense;
Z *ZEYELIST[20];
int ZEYESIZE;
int ZEYEOWNER;
int EYEPAM[5];
int CORNERWEIGHT;
上記はC言語の外部変数の定義部分である、一般てきには、ファイル対応でクラスを
定義するが、そのすぐ下で、プロパティ変数でこれらを定義する。
int mainKey;
Z Zattack,Zdefense;
Z[] ZEYELIST=new Z[20];
int ZEYESIZE;
int ZEYEOWNER;
int[] EYEPAM=new int[5];
int CORNERWEIGHT;
1.3 定数のマクロ定義 #define TEBANWIN 3
#define SEKISEKI 4
#define BWINSEKI 5
#define WWINSEKI 6
#define SEMEAICOMPLICATE 7
上記は定数のマクロ定義であり。JAVAにはマクロ機能がないので以下の形式で
定数定義とし、プロパティ変数に入れる。
static final int TEBANWIN= 3 ;
static final int SEKISEKI= 4 ;
static final int BWINSEKI= 5 ;
static final int WWINSEKI= 6 ;
これらの定義はCではヘッダーファイルに記述し、他のプログラムと共有する
場合が多い。この場合は 定数のインターフェース記述を別ファイルとし、
import で組み込むことにする。
1.4 構造体
typedef struct analys
{
     bool death,hot,hot1,hot2,touch ;int c; int hotvalue;
     }
     analys;
上記は構造体の定義であり。JAVAではクラスに変換する。
class analys{
boolean death,hot,hot1,hot2,touch ;
int c; int hotvalue;
}
この構造体がこのファイル内に閉じて使用される場合は、内部クラスとし
他のプログラムファイルでも使われる場合は新たな独立したファイルとし
て作成する。
1.5 STATIC 変数
static bool connectSW;
static bool bothKiriSW;
static int ConnectTT;
上記はSTATIC変数の定義であり。JAVAでも同様にSTATIC変数に変換する。
static boolean connectSW;
static boolean bothKiriSW;
static int ConnectTT;
これは外部変数で定義されていたが、C言語では関数の内部で定義されて
いる場合もある。JAVAではその場合もメソッドの外に定義を移す必要が
ある。
2.具体的な関数内部の変換例
2.1 関数の標準的な変換
void CreateFamily(){
 int rcount, x,y,i,j,t,potent;
  R *r;
Z*z;
F *f;
goban->GOBANID=1;
CFCount=0;
rcount=0;
f= new F(1,goban);
f->t=0;
CreateFList[CFCount++]=f;
f->flag=500;
FORALLXY{
z= goban->xytoz(x,y);
上記は関数の始まり部分である、JAVAではメソッドの対応させて変換する。
メソッドの形式に合わせる変換と、マクロ部分の展開をした後、JAVAC
でコンパイルするとエラーがでるので、前項で述べた方針に従って
命令単位で修正すれば、変換は完了すると考えてよい。
void CreateFamily(){
int rcount,x,y,i,j,t,potent;
R r;
Z z;
F f;
Cons.app.GOBANID=1;
CFCount=0;
rcount=0;
f= new F(1,Cons.app);
f.t=0;
CreateFList[CFCount++]=f;
f.flag=500;
for(x=1;x<=Cons.gsize;x++)for(y=1;y<=Cons.gsize;y++){
z= Cons.app.xytoz(x,y);
・ gobanとゆう変数は、外部変数で extern kernel *goban;と定義されて いて、C++で作成されたクラス Kernelのインスタンスをさすポインタであ
る。
ほとんどのプログラムから参照される変数なので、以下のような特別のクラス
を作成し、Cons.app とゆう変数で対応することにしている。
public class Cons{
public static int gsize=19;
public static int MainDebug=0;
public static Kernel app;
・ FORALLXYはマクロ定義であり、概要に述べたとおり展開形で直接記述した。
・ ポインタの参照 −>は 単純に . に変換する。
・ ポインタの定義の * および 参照 * は スペースに変換する。
  ただし ** は配列に置き換えるので注意すること。
2.2 ポインタを配列に変換する例
・ ポインタを示す & はスペースに変換するが、対応する変数の定義を   配列に変換する必要がある。
2.3 ポインタ演算の変換例
・ ポインタ変数に対して p++; *p+5 ; などを JAVA でどう記述するか。
2.4 スコープの違いを解決する変換の例

2.5 キャスティングが必要な例

2.6 初期化を追加する例

2.7 条件式のあいまいさを補完する例

2.8 0 と NULL を正しく補完する例
3 考察
  一般のプログラムを別の言語に変換する例は今まであまり例がないと  思う。
  従来、ハードウエアを入れ替えたため、アセンブラをCOBOL言語に書き換えた
 例では、変換とゆうより、設計書から作り直しとゆう作業が行われた。
  COBOL言語のバージョンの違いをコンバージョンとゆう作業でコンパイルして
 エラーを修正することで実施した例は別の言語に変換する例には当てはまらないで
 あろう。
  ここで述べた、C言語からJAVA言語への変換はあまり例がないと思うので、今後
 このような変換が必要となる人のために、大雑把な説明と結果の評価を述べて参考
 にしていただくことを期待する。
  JAVAは大変よくできた言語だと思う。コンパイルエラーを注意深く解決すると
 ほとんど問題なく C言語の時と同じ結果をだした。
  わたしも、作業しながら、こんな面倒で誤りやすい、かつ本当に正しく動く保証
 を証明できない作業を数ヶ月行うのは、正直に言って大変苦痛で何度のやめよう
 と思った。
  でも、一部を完成し、正しく動くのを確認し大変驚いた。
 それで、はずみがついて、ほとんどの変換を終了して、価値のある作業であったと
 実感した。
  オリジナルのC のプログラムは私が書いたのではないので、ほとんど関数単位
 の意味も解らずに変換した。
  オリジナルのC は数年かけて開発されたもので、今も修正と機能拡張が行われて
 いる囲碁の対局プログラムで、実際のプログラムはホームページにある。