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: }