アプリ版:「スタンプのみでお礼する」機能のリリースについて

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;
}
//***********************
//ビット走査の終了
//***********************
}
}

A 回答 (5件)

こんな感じでどうでしょうか


一応動作確認はしてあります

//// ソースはここから ///////////////////////////////////////////
// ChkBit.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

//ビット配列correct_ciphertextとPbinを比較するプログラム
//LSBからMSBまで順に走査を行い、違うビットが出てきた時点でbreakし、走査を止める
//Pbinは固定値を与えている
#include <stdio.h>
#include <string.h>

// 扱う最大ビット長
#define MAX_BIT_LENGTH64
// ブロック化するビット長
#define BLOCK_LENGHT8


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をリセットする関数を設ける
こちらのほうが使いやすいと思います。
    • good
    • 0

>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 );
}
    • good
    • 0

判定部を関数化してそれを呼び出す側の親ループを関数の中で制御したいってことですか?


それって無理でしょ ....

while( TRUE ) {
  myFunc(...);
}
n++;
といった具合で myFuncの中から n++へ直接行きたい ってことでしょうか

質問からその主旨がいまいち明確に見えないんですが
一般的な実装ならmyFuncの戻り値で成否の判定をしてことではないかと
while( TRUE ) {
  if ( myFunc(...) ) {
    break;
  }
}
n++;
    • good
    • 0

プログラムの"仕様"の理解不足かもしれないですが


memcmp()
では用は足りないのでしょうか?

1ビット比較する都度、結果を出力しなくていけない仕様とか....

単にビットパターン比較の結果だけが得たいなら
memcmp()
で実装すれば、ループなんか不要になり、
ずっと高速だと考えますが....
    • good
    • 0

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 {
  // 同一
}
ってことですか?

# どの部分を関数かしたいのか明示しましょう
    • good
    • 0
この回答へのお礼

回答有難う御座います。
どこの部分を関数化したいか明示するのを忘れていました、失礼しました。
上記のソースはだいたい下のような構造になっていますが、関数化したいのは、「ビット走査」から「ビット走査の終了」までです。この中で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が問題
}
//***********************
//ビット走査の終了
//***********************
}

お礼日時:2009/04/30 00:28

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!