• ベストアンサー

ビット列を走査するプログラムの関数化

char型の変数に0or1を入れて擬似的にビット列にした配列をLSBからMSBまで走査し、一致したらループを抜け終了するプログラムをCで書きたいと思っています。 他のプログラムでも使いまわし、かつ見やすくするためにこの部分を関数化したいのです。ソースにはbreakを使っているのですが、当然ながらbreakはforかwhile内で使わないとダメだと思いますが、ソース作成の都合上、for文は関数内に入れたくないのです。 (つまり、条件分岐を関数化したものをfor文内で用いたい) うまい方法が思いつかずに困っています。もし良い方法をお気づきの方がおられたらご助力下さい。 //===============================================// //=================以下ソース====================// //===============================================// //ビット配列correct_ciphertextとPbinを比較するプログラム //LSBからMSBまで順に走査を行い、違うビットが出てきた時点でbreakし、走査を止める //Pbinは固定値を与えている #include <stdio.h> #include <string.h> unsigned int mes[2]; unsigned int key[2]; char Pbin[64]; char Kbin[64]; char ciphertext[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}; void ConvertPtextToBin_ForHost(unsigned int mes[]){ unsigned int tmp_mes[2] = {mes[0], mes[1]}; int i, j; for(j=0;j<=1;j++){ for(i=0;i<=31;i++){ Pbin[j*32 + 31-i] = tmp_mes[j] % 2; tmp_mes[j] = tmp_mes[j] / 2; } } } int main(int argc, char *argv[]){ //initialize mes[0] = 0x00000000; mes[1] = 0x00000000; int i, j, k; int x=0, y=0; while(1){ printf("mes[1] = %d\n", mes[1]); ConvertPtextToBin_ForHost(mes); for(i=0; i<64; i++){ printf("%d", Pbin[i]); if((i+1)%8 == 0) printf(" "); } printf("\n"); //************************* //ビット走査 //************************* for(k=0; k<64; k++){ if( (ciphertext[63-k] == Pbin[63-k]) ){ //同じビットであれば、次のビットを走査する }else{ printf("Error\n");//後ろから走査していって、1ビットでも違うものがあれば違うビット列と判断する break; } } //ここに来たら違うビット列だったということ if(k != 64){ mes[1]++; printf("Not match ciphertext... %dth bit didn't match. (0bit:LSB)\n", k); printf("This was %d*%dth Search...\n\n", y, x); x++; if(x>=65535){i=0; y++;} }else{ //k=64つまり、最後のビットまで同じビットだったということ⇒つまり、「発見」 printf("Match ciphertext\n"); printf("This was %d*%dth Search...\n\n", y, x); break; } //*********************** //ビット走査の終了 //*********************** } }

質問者が選んだベストアンサー

  • ベストアンサー
  • BLK314
  • ベストアンサー率55% (84/152)
回答No.5

こんな感じでどうでしょうか 一応動作確認はしてあります //// ソースはここから /////////////////////////////////////////// // ChkBit.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 // #include "stdafx.h" //ビット配列correct_ciphertextとPbinを比較するプログラム //LSBからMSBまで順に走査を行い、違うビットが出てきた時点でbreakし、走査を止める //Pbinは固定値を与えている #include <stdio.h> #include <string.h> // 扱う最大ビット長 #define MAX_BIT_LENGTH 64 // ブロック化するビット長 #define BLOCK_LENGHT 8 unsigned int mes[2]; unsigned int key[2]; char Pbin[MAX_BIT_LENGTH]; char Kbin[MAX_BIT_LENGTH]; char ciphertext[MAX_BIT_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}; // 指定された配列(bitをエミュレート)の指定ビットに値を設定する static void SetBit(char Dest[], int Pos, int Bit) { Dest[Pos] = Bit; } static void ConvertPtextToBin_ForHost(unsigned int mes[]) { unsigned int tmp_mes[2] = {mes[0], mes[1]}; int i, j; for(j = 0;j <= 1;j++) { for(i = 0;i <= 31;i++) { SetBit(Pbin, j * 32 + 31 - i, tmp_mes[j] & 0x01); tmp_mes[j] >>= 1; } } } // 8ビットを1ブロックとして区切りながら表示する static void FmtDisp(char sec[]) { int i; for (i = 0; i< MAX_BIT_LENGTH; i++) { printf("%d", Pbin[i]); if (!((i+1) % BLOCK_LENGHT)) printf(" "); } printf("\n"); } // ビットパターン配列(char配列)を比較し // 配列[0]がMSB 配列[MAX_BIT_LENGTH - 1]がLSBとする // LSBから順にサーチするものとする // 最初に違いが見つかったビットの番号(MSB = 0)を返す // 全ビット一致した場合はLengthを戻す static int FindDiffBitNumber(char buf1[], char buf2[], int Length) { int i; for (i = 0; i < Length; i++) { int n; n = Length - 1 - i; // LSBを基準としたビット位置 if (buf1[n] != buf2[n]) return i; } return Length; } // ビット走査を行う // 違うなら0, 同一なら0以外を戻す static int SearchBit(char buf1[], char buf2[], int Length, unsigned int mes[], int* x, int* y) { long n; n = FindDiffBitNumber(buf1, buf2, Length); if(n < Length) { // 違うビットが検出された場合 mes[1]++; printf("Not match ciphertext... %dth bit didn't match. (0bit:LSB)\n", n); printf("This was %d*%dth Search...\n\n", *y, (*x)++); if (*x >= 65535) { (*y)++; } return 0; } else { // 同一だった場合 printf("Match ciphertext\n"); printf("This was %d*%dth Search...\n\n", *y, *x); return 1; } } int main(int argc, char *argv[]) { int x = 0, y = 0; //initialize mes[0] = 0x00000000; mes[1] = 0x00000000; do { printf("mes[1] = %d\n", mes[1]); ConvertPtextToBin_ForHost(mes); // 8ビットを1ブロックとして区切りながら表示する FmtDisp(Pbin); } while (!SearchBit(ciphertext, Pbin, MAX_BIT_LENGTH, mes, &x, &y)) ; } /// ソースはここまで /////// x, yはSearchBit()関数内のstatic変数として、 パラメータから除くことも考えました。 しかし、 SearchBit()が使いまわされることを考えると、 x, yのリセット処理が必要になります。 この辺は単なる関数化だけでなく、 "モジュール化"も考えたほうがいいかとも思います。 (C++のクラス化も大いにありです) そして x, yはstatic変数(C++ではメンバ変数)とし、 SearchBit()のパラメータから除く。 代わりにx,yをリセットする関数を設ける こちらのほうが使いやすいと思います。

その他の回答 (4)

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.4

>char型の変数に0or1を入れて擬似的にビット列にした配列をLSBからMSBまで走査し、一致したらループを抜け終了するプログラムを  ソースをみると、一致するかの変数 mes は0からインクリメントしているだけですよね。  乱数でもなく・・。  それに要する時間を計測する訳でもなく・・。  「走査し、一致したら」とは、取りも直さず、なにもせず、 ☆ ciphertext をそのまま8桁区切りで出力するだけ、ではないですか。 >他のプログラムでも使いまわし、  どのような利用用途があるのでしょうか、補足願います。 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 質問者様の意図をくみ取れないままに・・。 ・下の関数を main 関数の while 文内で呼び出したら如何でしょう。   1 で戻ったら while を break すればよろしいかと・・。 char ciphertext[ 128 ] = {   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   1, 0, 0, 0, 0, 0, 0, 0,   9 // ストッパー }; int Check64( void ) {  char *pP, *pC;  pP = Pbin;  pC = ciphertext;  while( 1 ){    if( 9 == *pC ) return( 1 );    if( *pP != *pC ) return( 0 );    pP++;    pC++;  }  return( 1 ); }

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

判定部を関数化してそれを呼び出す側の親ループを関数の中で制御したいってことですか? それって無理でしょ .... while( TRUE ) {   myFunc(...); } n++; といった具合で myFuncの中から n++へ直接行きたい ってことでしょうか 質問からその主旨がいまいち明確に見えないんですが 一般的な実装ならmyFuncの戻り値で成否の判定をしてことではないかと while( TRUE ) {   if ( myFunc(...) ) {     break;   } } n++;

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.2

プログラムの"仕様"の理解不足かもしれないですが memcmp() では用は足りないのでしょうか? 1ビット比較する都度、結果を出力しなくていけない仕様とか.... 単にビットパターン比較の結果だけが得たいなら memcmp() で実装すれば、ループなんか不要になり、 ずっと高速だと考えますが....

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

int CheckBit( int nBit, char* bitSrc, char* bitDes ) {   return bitSrc[nBit] != bitDes[nBit]; } メイン側で int bFlag; bFlag = FALSE; for(k=0; k<64; k++ ) {   if ( bFlag = CheckBit( 63-k, ciphertext, Pbin) ) {     break;   } } if ( bFlag ) {   // 違うと判定された } else {   // 同一 } ってことですか? # どの部分を関数かしたいのか明示しましょう

g47040
質問者

お礼

回答有難う御座います。 どこの部分を関数化したいか明示するのを忘れていました、失礼しました。 上記のソースはだいたい下のような構造になっていますが、関数化したいのは、「ビット走査」から「ビット走査の終了」までです。この中でbreakが2回使われていますが、2回目のbreakが問題でなっているのです(1回目のbreakはfor文内なので問題ない) 処理の途中に条件判定が発生していて、もしある条件に一致したら強制的にwhileループを抜ける、というプログラムなのでbreakが必要なのですが、while(1)を含まない部分を関数化したいのです。 また、書いていただいたソースはだいたいその通りです。「//同一」と書いてある部分でbreakを挟みたいのです。 よろしくお願いします。 <上記ソースの構造> int main(int argc, char *argv[]){ while(1){ ... for(i=0; i<64; i++){ ... } //************************* //ビット走査 //************************* for(k=0; k<64; k++){ if( (ciphertext[63-k] == Pbin[63-k]) ){ ... }else{ printf("Error\n"); break; } } if(k != 64){ ... }else{ ... break; //←ここのbreakが問題 } //*********************** //ビット走査の終了 //*********************** }

関連するQ&A