【ATIONに関する技術的な問題】
(2004/3)
ver1.072の時点で次のような限界を認識しています。
(1)左辺が配列の場合、配列値から直接代入することができない。(2004/3)
つまり
不細工ですが、一度、非配列変数に入れるようにしてください。
すなわち、
char szA[]="abcdef"; char szB[7]; for(int i=0;i<6;i++) szB[5-i]=szA[i]; szB[6]='\0'; Printf("%s\r\n", szB);というような代入はできません。
不細工ですが、一度、非配列変数に入れるようにしてください。
すなわち、
char szA[]="abcdef"; char szB[7]; char cTmp; for(int i=0;i<6;i++) szB[5-i]=cTmp=szA[i]; szB[6]='\0'; Printf("%s\r\n", szB);という処理にしてください。
(2)関数の再帰呼び出しに関していくつか制限がある(2000/5)
(A)再帰呼出しをする関数内の変数に対して文字列演算をすると値がおかしくなる。文字列演算は使わず、C言語風のStrcpy, Strcat Strncpyなどをお使いください。
(B)再帰呼出しをする関数内の変数に対して、メモリ領域の再割り当てが生じると、値がおかしくなる。
(C)再帰呼出しをする関数内では、FindFirstFile/FindNextFile/FindCloseではなく、ver1.040で新設した、FindFirstFileNS/FindNextFileNS/FindCloseNSを使わなければならない。
まとめて例で説明ます。まず悪い例です。
上の例は次のように書いてください。
(A)再帰呼出しをする関数内の変数に対して文字列演算をすると値がおかしくなる。文字列演算は使わず、C言語風のStrcpy, Strcat Strncpyなどをお使いください。
(B)再帰呼出しをする関数内の変数に対して、メモリ領域の再割り当てが生じると、値がおかしくなる。
(C)再帰呼出しをする関数内では、FindFirstFile/FindNextFile/FindCloseではなく、ver1.040で新設した、FindFirstFileNS/FindNextFileNS/FindCloseNSを使わなければならない。
まとめて例で説明ます。まず悪い例です。
void DisplayFileName(char& szBaseDir[]) { char szName[1]; // メモリの再割り当てが生じるので× char szFile[1];// メモリの再割り当てが生じるので× char szNowFile[1];// メモリの再割り当てが生じるので× int arAttr[9]; szFile=szBaseDir . "*"; //文字列演算は× // FindFirstFile/FindNextFile/FindCloseは× if(FindFirstFile(szFile, szName, arAttr)) { do { if(!arAttr[FA_DIRECTORY] ){ Printf("%s%s\n", szBaseDir, szName); } else if(Strcmp(szName, ".") && Strcmp(szName, "..")){ szNowFile =szBaseDir . szName . "\\"; // 文字列演算は× DisplayFileName(szNowFile); } }while(FindNextFile( szName, arAttr)); } FindClose(); }
上の例は次のように書いてください。
void DisplayFileName(char& szBaseDir[]) { char szName[300]; // 充分な大きさを確保 char szFile[300]; // 充分な大きさを確保 char szNowFile[300]; // 充分な大きさを確保 int arAttr[9]; Sprintf(szFile, "%s*", szBaseDir); // 文字列演算を使わない。 // FindFirstFileNS/FindNextFileNS/FindCloseNSを使用 int nFCookie=FindFirstFileNS(szFile, szName, arAttr); if(nFCookie){ do { if(!arAttr[FA_DIRECTORY] ){ Printf("%s%s\n", szBaseDir, szName); } else if(Strcmp(szName, ".") && Strcmp(szName, "..")){ Sprintf(szNowFile, "%s%s\\", szBaseDir, szName); // 文字列演算を使わない。 DisplayFileName(szNowFile); } }while(FindNextFileNS(nFCookie, szName, arAttr)); } FindCloseNS(nFCookie); }
(3)パターンマッチングを&&や||の項にできない。(2000/5)
つまり
これは、
if( nNum<1 && $_=~/^\s+/) { ... }という表現はできません。
これは、
if( nNum<1) { if($_=~/^\s+/) {...} }というように書いてください。
(4)インクリメント、デクリメントに制限がある。(2000/12)
(A)do〜 while構文での問題。
(B)ループ後の値の問題。
いずれもATIONのヘルプの「演算子」の項に説明があります。詳しくはそれをお読みください。
(B)ループ後の値の問題。
いずれもATIONのヘルプの「演算子」の項に説明があります。詳しくはそれをお読みください。
(5)ファイル読み込み演算子を&&や||の項にできない。(2000/5)
たとえば、次のような書き方はできません。
for(i=0; i<5 && <FH>; i++){ Printf($_); }
(6)ファイル読み込み演算子が、条件節に入る度に初期化されてしまう。(2000/5)
たとえば、上例を次のように書き換えたとします。
for(i=0; i<5 ; i++){ if(<FH>) Printf($_); }こうすると構文エラーは解消されますが、if文に入る度に初期化されてしまうので、最初の行ばかりが5回表示されて、終了します。
(7)文字列演算の左辺値はchar型の1次元配列でなければなりませんが、多次元配列の部分配列を左辺値にしても、エラー表示しない。(メモリの再割り当てが発生しないように充分な大きさの領域をあらかじめ確保しておけば、問題は生じないでしょう。)(2000/5)
たとえば、次のような例です。
char szStr[2][32]; szStr[1] ="This is "; szStr[1] .="a pen.";
(8)""で囲まれたなかの\は必ず\\と書かなければならない。(2000/5)
PATH指定で多くでてきます。
char szPath[]="c:\\temp\\foo.txt";
(9)ひとつのスクリプトのなかで長大な正規表現をいくつも使うと、オーバーフローを起こす場合がある。(2000/5)
どの程度というのは、一概にはいえません。
たとえば \={100,} という正規表現は、= の100個以上の連なりを意味しますが、ATION内部では、この正規表現に対して、瞬間的にですが、(100×?)個のノードを作っています。つまり、この正規表現は、ある瞬間ひどく長大になるわけです。
オーバーフローした場合は、その旨を表示します。
たとえば \={100,} という正規表現は、= の100個以上の連なりを意味しますが、ATION内部では、この正規表現に対して、瞬間的にですが、(100×?)個のノードを作っています。つまり、この正規表現は、ある瞬間ひどく長大になるわけです。
オーバーフローした場合は、その旨を表示します。
以上です。