MUSASHI C source: xtcombi.c


0001: /*============================================================================*/ 
0002: /* 変更履歴                                                                   */ 
0003: /*----------------------------------------------------------------------------*/ 
0004: /* 1.0 : 新しいAPIに対応 2003/06/20                                           */ 
0005: /*============================================================================*/ 
0006:  
0007: #include <musashi.h
0008: #include <stdlib.h> 
0009:  
0010: #include <xtcombiHelp.h> 
0011: struct mssComHelp comHelp={ 
0012:   "xtcombi",      /* コマンド名       */ 
0013:   "1.0",          /* バージョン       */ 
0014:   HELPT,          /* コマンドタイトル */ 
0015:   HELPS,          /* 要約             */ 
0016:   HELPE,          /* 利用例           */ 
0017:   HELPR,          /* 参照コマンド     */                                       
0018:   HELPA,          /* 作者情報         */ 
0019:   HELPB,          /* バグレポート情報 */ 
0020:   HELPH           /* ホームページ     */                                     
0021: };   
0022:      
0023: extern struct mssGlobalVariables mssGV; 
0024:  
0025: static char **FldStr; 
0026: static int    FldCnt; 
0027: static struct mssStrList *StrList; 
0028: static int Line; int K;     /* (nCk) Line Combination K */ 
0029: static struct mssFPW *Fpw; 
0030: static int Permutation; 
0031: static int  CombiList[MssFieldMaxCnt]; 
0032:  
0033: /*順列の出力*/ 
0034: /*アルゴリズム事典 pp.119-120 */ 
0035: void perm(int i){ 
0036:   int j,k; 
0037:   if(i>0){ 
0038:     perm(i-1); 
0039:     for(j=i-1; j>=0; j--){ 
0040:       mssSwapInt(&CombiList[i],&CombiList[j]); 
0041:       perm(i-1); 
0042:       mssSwapInt(&CombiList[i],&CombiList[j]); 
0043:     } 
0044:   }else{ 
0045:     mssWriteFld(FldStr,FldCnt,"",Fpw); 
0046:     for(k=0; k<K; k++){ 
0047:       mssWriteDlm(Fpw); 
0048:       mssWriteStr(mssGetStrList(StrList,CombiList[k]),Fpw); 
0049:     } 
0050:     mssWriteRet(Fpw); 
0051:     mssGV.outCnt++; 
0052:   } 
0053: } 
0054:  
0055: void combi( int from, int depth){ 
0056:  
0057:   int i; 
0058:  
0059:   if(depth>=K){ 
0060:     /*順列出力*/ 
0061:     if(Permutation){ 
0062:       perm(K-1); 
0063:     /*組合出力*/ 
0064:     }else{ 
0065:       mssWriteFld(FldStr,FldCnt,"",Fpw); 
0066:       for(i=0; i<depth; i++){ 
0067:         mssWriteDlm(Fpw); 
0068:         mssWriteStr(mssGetStrList(StrList,CombiList[i]),Fpw); 
0069:       } 
0070:       mssWriteRet(Fpw); 
0071:       mssGV.outCnt++; 
0072:     } 
0073:     return; 
0074:   } 
0075:  
0076:   /*再帰処理*/ 
0077:   for(i=from; i<Line; i++){ 
0078:     CombiList[depth]=i; 
0079:     combi(i+1,depth+1); 
0080:   } 
0081: } 
0082:  
0083: void writeCombi( 
0084:   struct mssFldRecDbl *frd,   /*項目-二行バッファ構造体*/ 
0085:   struct mssStrList *strList, /* 各行の値リスト        */ 
0086:   int k,                   /*組み合せ数             */ 
0087:   int permutation,         /*順列フラグ             */ 
0088:   struct mssFPW *fpw){ 
0089:  
0090:   if(k>strList->cnt) return; /* nCk で k>nなら何も出力しない*/ 
0091:  
0092:   /*グローバル変数のセット*/ 
0093:   FldStr=frd->pnt[frd->old]; 
0094:   FldCnt=frd->fldCnt; 
0095:   StrList=strList; 
0096:   Line=strList->cnt; 
0097:   K=k; 
0098:   Fpw=fpw; 
0099:   Permutation=permutation; 
0100:  
0101:   /*再帰処理*/ 
0102:   combi(0,0); 
0103:  
0104: } 
0105:  
0106: int main(int argc, char *argv[]){ 
0107: /*============================================================================*/ 
0108: /* オプション宣言&定義                                                       */ 
0109: /*============================================================================*/ 
0110: /*----------------------------------------------------------------------------*/ 
0111: /* キー項目                                                                   */ 
0112: /*----------------------------------------------------------------------------*/ 
0113:   MssOptKEY optKEY={ 
0114:     OKEY,   /* オプションタイプ                                             */ 
0115:     "k",    /* キーワード(複数文字は不可)                                   */ 
0116:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0117:     MssFieldMaxCnt, /* 指定可能な最大項目数                                 */ 
0118:     "i",    /* 対象とする入力データのキーワード(GUIで利用)                  */ 
0119:     2,      /* デフォルト(このオプションが指定されなかったときの動作を指定) */ 
0120:             /* 1:全ての行を異るキー値として扱う                             */ 
0121:             /* 2:全ての行を同じキー値として扱う)                            */ 
0122:     KEYT,   /* このオプションのタイトル(Helpで表示)                         */ 
0123:     KEYC    /* このオプションのコメント(Helpで表示)                         */ 
0124:   }; 
0125:      
0126: /*----------------------------------------------------------------------------*/ 
0127: /* 対象項目                                                                   */ 
0128: /*----------------------------------------------------------------------------*/ 
0129:   MssOptFLD optFLD={ 
0130:     OFLD,   /* オプションタイプ                                             */ 
0131:     "f",    /* キーワード(複数文字は不可)                                   */ 
0132:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0133:     1,      /* 指定可能な最大項目数                                         */ 
0134:     "i",    /* 対象とする入力データのキーワード(GUIで利用)                  */ 
0135:     0,      /* 正規表現を許可するかどうか(0:不可,1:可)                      */ 
0136:     0,      /* 新項目名を指定できるかどうか(0:不可,1:可)                    */ 
0137:     NULL,   /* 項目オプション(%以下)で指定可能な文字                        */ 
0138:             /* ex) 指定不可の場合はNULL, "nr": "-f 項目名%rn"の指定可能     */ 
0139:     FLDT,   /* このオプションのタイトル(Helpで表示)                         */ 
0140:     FLDC,   /* このオプションのコメント(Helpで表示)                         */ 
0141:     FLDF    /* フラグについての説明(Helpで表示)複数の場合はカンマで区切る   */ 
0142:   }; 
0143:  
0144: /*----------------------------------------------------------------------------*/ 
0145: /* 組合せ数                                                                   */ 
0146: /*----------------------------------------------------------------------------*/ 
0147:   MssOptINT optNUM={ 
0148:     OINT,   /* オプションタイプ                                             */ 
0149:     "n",    /* キーワード(複数文字は不可)                                   */ 
0150:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0151:     0,      /* デフォルト(数値として指定)                                   */ 
0152:     2,      /* 最小値                                                       */ 
0153:     50,     /* 最大値                                                       */ 
0154:     NUMT,   /* このオプションのタイトル(Helpで表示)                         */ 
0155:     NUMC    /* このオプションのコメント(Helpで表示)                         */ 
0156:   }; 
0157:  
0158: /*----------------------------------------------------------------------------*/ 
0159: /* 順列                                                                       */ 
0160: /*----------------------------------------------------------------------------*/ 
0161:   MssOptFLG optPER={ 
0162:     OFLG,   /* オプションタイプ                                             */ 
0163:     "p",    /* キーワード(複数文字は不可)                                   */ 
0164:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0165:     PERT,   /* このオプションのタイトル(Helpで表示)                         */ 
0166:     PERC    /* このオプションのコメント(Helpで表示)                         */ 
0167:   }; 
0168:  
0169: /*----------------------------------------------------------------------------*/ 
0170: /* 新項目名                                                                   */ 
0171: /*----------------------------------------------------------------------------*/ 
0172:   MssOptSLS optFNM={ 
0173:     OSLS,   /* オプションタイプ                                             */ 
0174:     "a",    /* キーワード(複数文字は不可)                                   */ 
0175:     2,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0176:     NULL,   /* デフォルト(文字列)                                           */ 
0177:     50,     /* カンマで区切られる要素数の最大値                             */ 
0178:     1,      /* 各要素の文字列長の最小値                                     */ 
0179:     MssFieldNameMaxLen,/* 各要素の文字列長の最大値                          */ 
0180:     0,      /* 1:要素にコロンを指定できる,0:不可  ex) aaaa:xxxxx            */ 
0181:     FNMT,   /* このオプションのタイトル(Helpで表示)                         */ 
0182:     FNMC    /* このオプションのコメント(Helpで表示)                         */ 
0183:   }; 
0184:  
0185: /*----------------------------------------------------------------------------*/ 
0186: /* シーケンシャル処理                                                         */ 
0187: /*----------------------------------------------------------------------------*/ 
0188:   MssOptFLG optSEQ={ 
0189:     OFLG,   /* オプションタイプ                                             */ 
0190:     "q",    /* キーワード(複数文字は不可)                                   */ 
0191:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0192:     SEQT,   /* このオプションのタイトル(Helpで表示)                         */ 
0193:     SEQC    /* このオプションのコメント(Helpで表示)                         */ 
0194:   }; 
0195:  
0196: /*----------------------------------------------------------------------------*/ 
0197: /* 入力ファイル                                                               */ 
0198: /*----------------------------------------------------------------------------*/ 
0199:   MssOptINF optINF={ 
0200:     OINF,   /* オプションタイプ                                             */ 
0201:     "i",    /* キーワード(複数文字は不可)                                   */ 
0202:     0,      /* 0:オプション, 1:必須                                         */ 
0203:     1,      /* 指定可能の最大ファイル数                                     */ 
0204:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0205:     INFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0206:     INFC    /* このオプションのコメント(Helpで表示)                         */ 
0207:   }; 
0208:  
0209: /*----------------------------------------------------------------------------*/ 
0210: /* 出力ファイル                                                               */ 
0211: /*----------------------------------------------------------------------------*/ 
0212:   MssOptOTF optOTF={ 
0213:     OOTF,   /* オプションタイプ                                             */ 
0214:     "o",    /* キーワード(複数文字は不可)                                   */ 
0215:     0,      /* 0:オプション, 1:必須                                         */ 
0216:     OTFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0217:     OTFC    /* このオプションのコメント(Helpで表示)                         */ 
0218:   }; 
0219:  
0220: /*----------------------------------------------------------------------------*/ 
0221: /* 圧縮出力                                                                   */ 
0222: /*----------------------------------------------------------------------------*/ 
0223:   MssOptFLG optZIP={ 
0224:     OFLG,   /* オプションタイプ                                             */ 
0225:     "z",    /* キーワード(複数文字は不可)                                   */ 
0226:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0227:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0228:     ZIPC    /* このオプションのコメント(Helpで表示)                         */ 
0229:   }; 
0230:  
0231: /*----------------------------------------------------------------------------*/ 
0232: /* plain text                                                                 */ 
0233: /*----------------------------------------------------------------------------*/ 
0234:   MssOptFLG optTXT={ 
0235:     OFLG,   /* オプションタイプ                                             */ 
0236:     "t",    /* キーワード(複数文字は不可)                                   */ 
0237:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0238:     TXTT,   /* このオプションのタイトル(Helpで表示)                         */ 
0239:     TXTC    /* このオプションのコメント(Helpで表示)                         */ 
0240:   }; 
0241:  
0242: /*----------------------------------------------------------------------------*/ 
0243: /* ワークファイル用ディレクトリ名                                             */ 
0244: /*----------------------------------------------------------------------------*/ 
0245:   MssOptSTR optTMP={ 
0246:     OSTR,   /* オプションタイプ                                             */ 
0247:     "T",    /* キーワード(複数文字は不可)                                   */ 
0248:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0249:     MssTempDir, /* デフォルト                                               */ 
0250:     1,      /* 文字列の最小長                                               */ 
0251:     MssFileNameMaxLen,  /* 文字列の最大長                                   */ 
0252:     TMPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0253:     TMPC    /* このオプションのコメント(Helpで表示)                         */ 
0254:   }; 
0255:  
0256: /*----------------------------------------------------------------------------*/ 
0257: /* オプションをまとめる                                                       */ 
0258: /*----------------------------------------------------------------------------*/ 
0259:   void *opt[]={&optKEY,&optFLD,&optNUM,&optPER,&optFNM,&optSEQ, 
0260:                &optINF,&optOTF,&optZIP,&optTXT,&optTMP,NULL}; 
0261:  
0262: /*============================================================================*/ 
0263: /* 変数宣言&定義                                                             */ 
0264: /*============================================================================*/ 
0265:   struct mssHeader    *hdi; /*入力ファイル用<head>タグ格納構造体*/ 
0266:   struct mssHeader    *hdo; /*出力ファイル用<head>タグ格納構造体*/ 
0267:   struct mssFPR       *fpr; /*入力ファイル構造体                */ 
0268:   struct mssFPW       *fpw; /*出力ファイル構造体                */ 
0269:   struct mssFldRecDbl *frd; /*項目-二行バッファ構造体           */ 
0270:   struct mssFields    *sf;  /*ソート項目構造体                  */ 
0271:   int sorted;               /*ソート済チェック用                */ 
0272:  
0273:   struct mssStrList *strList; 
0274:  
0275: /*----------------------------------------------------------------------------*/ 
0276: /* 前処理                                                                     */ 
0277: /*----------------------------------------------------------------------------*/ 
0278:   mssInit(argc,argv,&comHelp);       /* シグナル処理などの初期化              */ 
0279:   mssHelpDoc(opt,&comHelp,argc,argv);/* ヘルプ                                */ 
0280:   mssSetOption(opt,argc,argv);       /* コマンドオプションの設定              */ 
0281:   fpr=mssOpenFPR(optINF.str,4);      /* 入力ファイルオープン                  */ 
0282:   hdi=mssReadHeader(fpr);            /* ヘッダの読み込み                      */ 
0283:   mssSetOptKey(&optKEY, hdi);        /* -k 項目をヘッダー項目に関連づける     */ 
0284:   mssSetOptFld(&optFLD, hdi);        /* -f 項目をヘッダー項目に関連づける     */ 
0285:          
0286:   /*ソート項目の作成*/ 
0287:   sf=mssInitFields(); 
0288:   mssAddFieldsByFields(sf,optKEY.flds); /* -k 項目をソート項目としてセット    */ 
0289:   mssSetFieldsSortPriority(sf);         /* ソート優先順位番号を登録順にふる   */ 
0290:   sorted=mssChkSorted(sf,hdi);          /* ソート済かチェック                 */ 
0291:      
0292: /*mssShowFields(sf);*/ 
0293: /*mssShowOption(opt);*/ 
0294: /*mssShowHeader(hdi);*/ 
0295:  
0296:   /*組合せ数と新項目の数のチェック*/ 
0297:   if(!mssGV.txtFlg){ 
0298:     if( optNUM.val != optFNM.cnt ){ 
0299:       mssShowErrMsg("number of new fields must be %d",optNUM.val); 
0300:       mssEnd(mssErrorNoDefault); 
0301:     } 
0302:   } 
0303:  
0304: /*----------------------------------------------------------------------------*/ 
0305: /*出力ヘッダーの作成と出力                                                    */ 
0306: /*----------------------------------------------------------------------------*/ 
0307:   /*出力ヘッダーの初期化(タイトル等のコピー)*/                                 
0308:   hdo=mssInitCpyHeader(hdi); 
0309:    
0310:   /*入力ヘッダの全項目を追加*/ 
0311:   mssAddFieldsByFields(hdo->flds,hdi->flds); 
0312:    
0313:   /*新項目名を追加する*/ 
0314:   mssAddFieldsByStrList(hdo->flds,optFNM.strList,optFNM.cnt); 
0315:      
0316:   /*ソートする必要があるならばsfのソート情報を反映*/     
0317:   if(!optSEQ.set && !sorted){ 
0318:     mssSetFieldsSort(hdo->flds,sf);  
0319:   } 
0320:    
0321:   /*標準出力オープン+ヘッダーの出力*/ 
0322:   fpw=mssOpenFPW(optOTF.str,optZIP.set,0); 
0323:   mssWriteHeader(hdo, fpw); 
0324:      
0325: /*----------------------------------------------------------------------------*/ 
0326: /*メインルーチン                                                              */ 
0327: /*----------------------------------------------------------------------------*/ 
0328:   strList=mssInitStrList(); 
0329:  
0330:   /*ソートが必用ならばソートしてソート済みファイルとしてオープン*/ 
0331:   if( !optSEQ.set && !sorted) 
0332:     fpr=mssReopenFPRsort(fpr,4,sf,hdi->flds->cnt,optTMP.str); 
0333:  
0334:   /*FRD構造体の初期化*/ 
0335:   frd=mssInitFRD(hdi->flds->cnt); 
0336:  
0337:   while( EOF!= mssReadFRD(fpr,frd) ){ 
0338:     /*キーブレイク時の処理*/ 
0339:     if(mssKeyBreak(frd, &optKEY)){ 
0340:  
0341:       /*一行書き出し*/ 
0342:       writeCombi(frd, strList,optNUM.val,optPER.set,fpw); 
0343:  
0344:       /*集計値の初期化*/ 
0345:       mssFreeStrList(strList); 
0346:       strList=mssInitStrList(); 
0347:  
0348:       if(frd->eof) break; 
0349:     } 
0350:  
0351:     mssGV.inCnt++; 
0352:  
0353:     /*通常行の処理*/ 
0354:     if( !MssIsNull(*(frd->pnt[frd->new]+MssFlds2num(optFLD.flds,0))) ){ 
0355:       mssPutStrList( strList,*(frd->pnt[frd->new]+MssFlds2num(optFLD.flds,0)) ); 
0356:     } 
0357:   } 
0358:   mssFreeStrList(strList); 
0359:   mssFreeFRD(frd); 
0360:  
0361: /*----------------------------------------------------------------------------*/ 
0362: /*フッター出力&終了処理                                                       */ 
0363: /*----------------------------------------------------------------------------*/ 
0364: /*printf("allocCnt=%d\n",getAllocCnt());*/ 
0365:   mssWriteFooter(fpw);  /* フッターの出力             */ 
0366:   mssCloseFPR(fpr);     /* 入力ファイルのクローズ     */ 
0367:   mssCloseFPW(fpw);     /* 出力ファイルのクローズ     */ 
0368:   mssFreeFields(sf);    /* ソート項目構造体の領域開放 */ 
0369:   mssFreeHeader(hdi);   /* 入力ヘッダ領域開放         */ 
0370:   mssFreeHeader(hdo);   /* 出力ヘッダ領域開放         */ 
0371:   mssFreeOption(opt);   /* オプション領域開放         */ 
0372:   mssShowEndMsg();      /* 完了メッセージ             */ 
0373:   return(0);            /* to avoid warning message   */ 
0374: }