• ベストアンサー

排他的論理和 BCC(水平パリティ《偶数》)の算出

排他的論理和 BCC(水平パリティ《偶数》)の算出 VC++6.0 MFCダイアログベースでプログラミングの勉強をしています。 RS232Cを使って、相手側の機器から送られてきた、 受信データが正しいか水平パリティチェックを行いたいと思っています。    下記のように作り、 bcc[0] ^= pszBuf; この部分で受信した データの排他的論理和の計算をしているのですが、これでは中身ではなくアドレスを 計算しているようでした・・・。 どのように直したら良いでしょうか? char Buf[32]; // 読み出しデータバッファ int i; // BCCチェックループ回数 char bcc[1] = {0}; // BCC計算結果 // 受信 ReadFile(m_hComm,  // ファイルハンドル (LPCVOID*)Buf, // バッファアドレス (DWORD)dwCount, // サイズ &dwRead, // 実際のサイズを格納する変数 NULL); // OVERLAPPED構造体 // 該当範囲の排他的論理和XORを取る pszBuf++; // 最初の[STX]は計算除外なのでインクリメント for(i = 0; i < 9; i++) { // 9回計算する。 bcc[0] ^= pszBuf; pszBuf++; } 受信するデータは JIS/ASCIIコード です。 受信する形式は  [STX] X X Y Y Y Y Y Y [ETX] [BCC] です。 BCCの計算は  X ^ X ^ Y ^ Y ^ Y ^ Y ^ Y ^ Y ^ [ETX] = [BCC]

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★アドバイス ・『ReadFile』関数のキャストは必要ありません。 ・『Buf』はポインタではないので『buf++』は出来ません。 ・『dwCount』には『32』がセットされていますか? ・『dwCount』と『dwRead』は DWORD 型ですよね。 ・下にサンプルを載せますので、これを参考にソースを見直して下さい。 サンプル: TCHAR bcc[ 1 ] = { 0 }; TCHAR Buf[ 32 ]; DWORD dwRead; INT i; if ( ReadFile(m_hComm,Buf,sizeof(Buf),&dwRead,NULL) ){  LPTSTR lpBuf = Buf + 1; // 最初の[STX]は計算除外なのでインクリメント    for ( i = 0 ; i < 9 ; i++ ){ // 9回計算する。   bcc[ 0 ] ^= *lpBuf++;  } } 最後に: ・ソースを載せるのならば省略しない方がいいでしょう。 ・以上。おわり。

hagimoto
質問者

補足

Oh-さん返事遅くなりました。 無事期待通りの結果をえることが出来ました。 本当にありがとうございました。 win32 console applicationでも試しにやってみましたが うまくいきました。 #include <stdio.h> #include <afx.h> int main() { TCHAR bcc[ 1 ] = { 0 }; TCHAR Buf[ 32 ] = "00000000000";//受信データの代わり int i; LPTSTR lpBuf = Buf + 1; // 最初の[STX]は計算除外なのでインクリメント //bcc[0] = 0^0^0^0^0^0^0^0^0 =0x30 for ( i = 0 ; i < 9 ; i++ ){ // 9回計算する。 bcc[ 0 ] ^= *lpBuf++; } printf("bcc = %x\n",bcc[0]); return 0; }

その他の回答 (3)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.4

LPCVOID自体がVOID*なので (LPCVOID*)Buf は (VOID**)Buf になっちゃいますよ

hagimoto
質問者

お礼

php504さんありがとうございます。 最初 (LPCVOID)Buf とした所、 2 番目の引数を 'char' から 'void *' に変換できません。 とエラーが出たので、安易に*を付けてしまいました。 下記コードを使うことにしました。 if ( ReadFile(m_hComm,Buf,sizeof(Buf),&dwRead,NULL) ){

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

コードを見て疑問に思ったこと: その「pszBuf」ってのは, どこでどのように定義されてるの? ReadFile で受信するときにはバッファアドレスとして Buf を使ってるんだけど, それと pszBuf とはどのような関係なの?

hagimoto
質問者

補足

Tacosanさん回答ありがとうございます。 せっかく読んでいただいたのに失礼なことをしてしまい申し訳ございません。 誤記です。 pszBuf = Buf バッファなんで余計なpszなくても良いかと思って削除したのですが、中途半端でした。 以下が修正版です。 char Buf[32]; // 読み出しデータバッファ int i; // BCCチェックループ回数 char bcc[1] = {0}; // BCC計算結果 // 受信 ReadFile(m_hComm,  // ファイルハンドル (LPCVOID*)Buf, // バッファアドレス (DWORD)dwCount, // サイズ &dwRead, // 実際のサイズを格納する変数 NULL); // OVERLAPPED構造体 // 該当範囲の排他的論理和XORを取る Buf++; // 最初の[STX]は計算除外なのでインクリメント for(i = 0; i < 9; i++) { // 9回計算する。 bcc[0] ^= Buf; Buf++; }

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★『pszBuf』はポインタですよね。 ・それならば『bcc[0] ^= *pszBuf;』としないとアドレスを計算することになります。 ・『*』文字でポインタの内容を参照できます。 ・以上。おわり。

hagimoto
質問者

補足

Oh-さん回答ありがとうございます。 最初の段階でアドレスを計算しているのに気がついたので、 実は bcc[0] ^= *pszBuf はやってみたのですが、 error C2100: 間接指定演算子 (*) の使い方が不正です。 とエラー表示が出てしまいました。

関連するQ&A

  • TCP/IP通信の送信データについて

    TCP/IP通信の開発をしています。 開発はVS 2005 VB.net です。 送信データは下記の通りとなっていますが、BCCの算出方法が分かりません。 送信データ:[STX TEXT ETX BCCH BCCL CR] 制御文字は下記の通りです。 STX 02H(hex) テキストの開始 ETX 03H(hex) テキストの終了 BCC 水平パリティとして誤り検出に使用する CR 0DH(hex) キャリッジリターン ※1)BCCは、STXの後からETXの前までバイト単位でXORを行い、結果を上位と下位の4ビットに分け、それぞれASCIIに変換して上位下位の順で転送する。 ※2)BCC計算範囲はTEXT部です。 ※1)の部分を同コーディングすればよいか分かりません。 ご教授いただければと思います。

  • 友達の質問に回答したいんですが、ネットワークに関することです。

    友達の質問に回答したいんですが、ネットワークに関することです。 ネットワークの最初のくだりになるんですが、 「あ」という文字をネットワークで送信する。 「あ」はUNICODEの「3042」です。これを2進数で表示すると、「1001110110010」です。これを2バイトで表示すると、「0001001110110010」です。それに、ベーシック手順で送信なれらば、SOH(ヘッディング開始)【0000001】ヘッディング【0000001】、STX(テキスト開始)【0000010】データ、ETX(テキスト終了)【0000100】BCC【偽りチェックということで、水平パリティ、垂直パリティとあります。それによってデーターが変わります。】これだけのデータを送信します。 「あ」=  「00010011101100100000001000000100000100000100」これにパリティチェックです。 これで、いいのでしょうか?

  • RS-422Aの通信

    三菱電機のQJ71C24N-R4でチラーとの通信をしたのですが 通信できないで困っています、チラーの通信仕様は、 スタートビット 1、データビット 8 パリテイー なし  ストップビット 1 誤り制御 水平パリテイー です、送信は EOT アドレス 職別子  ENQ    受信は STX 職別子 データ ETX BCC です、三菱電機のQJ71C24N-R4は垂直パリティー ですので、通常のOUTPUTで送信しても、。相手から 何もかえってきません、どうしたらいいのか大変こまっています 通信プロトコルは。無手順でしています 経験のある方、ご教授お願いします

  • winsockで送受信されるデータの効率的な扱い方について

    Winsock2.hを使って通信プログラムを作っています。 座標などのパラメータを短いスパンで送受信して処理をするものなのですが、 send()で送れるデータ型がchar*型ということなのでパラメータをwsprintf()を使って SOCKET s; int x=100; int y=100; int z=100; char buf[16]; wsprintf(buf,"#%04d#%04d#%04d",x,y,z); send(s,buf,strlen(buf),0); のようにして送信して、受信されたデータはstrtok()で区切りながらそれぞれ格納しています。 SOCKAT s; int x,y,z; int nResult; char buf[16]; char *tp; nResult = recv(s,buf,sizeof(buf),0); tp = strtok(buf,"#"); x=atoi(tp); tp = strtok(buf,"#"); y=atoi(tp); tp = strtok(buf,"#"); z=atoi(tp); という感じなのですが、パラメータが増えていくにつれなんというか冗長というか、 もうちょっと賢いやり方があるような気がしていろいろ調べてはみたものの… あまりデータの扱い方に関しての解説が見つからなかったので質問させていただきました。 ということで、他に複数の変数を纏めて送受信して処理する手法(できれば高速に)をご存知でしたらご教授お願いします。

  • 16進数から10進数に変換

    いつもお世話になります。 先日バイナリデータを読み込み、ある特定のデータを検索し、 そのデータを10進数に変換する処理がしたいです。 FILE *fp; char buf[1024]; fp = fopen("sample.jpg","rb"); fread(buf, siZeof(char), 1024, fp); for( int i=0; i<1024; i++ ){ if( (buf[i]==0xff) && (buf[i+1] == 0xe0) ){ //※質問詳細下記します。 } } ※ f文で、buf[i+2]buf[i+3]、例えばprintf("%02x,%02x",buf[i+2],buf[i+3]); で出力すると、所望の(11 00 )の16進数で得られています。 このbuf[i+2] buf[i+3]の値を10進数に変換して得るには、 どうしたらいいでしょうか? 0x1100→4352 どうぞよろしくお願い致します。

  • C言語で文字列をポインタ名にしたい

    C言語で文字列をポインタ名にしたい 題名のとおりですが、C言語で文字列をポインタ名にする方法はありますか? 具体的にはxの配列の個々の要素を、計算回数による計算結果の推移をファイルに出力したいと考えています。 ファイル名は「test_x_1.data」、「test_x_2.data」、…「test_x_50.data」のようになっています。 (要素分のファイルを作成するということです。) ここでそれぞれの「test_x_1.data」、「test_x_2.data」、…「test_x_50.data」には、 x[i]の計算回数と計算結果が格納されていますが、 現状では、fopenとfcloseを計算回数分繰り返しているため、計算時間がかかってしまっています。 よって、計算を行う前の最初にfopen、最後にfcloseを行うようにしたいのですが、 ファイルポインタを開く作業を手動で行うと、xの要素分ファイルポインタを用意しなくてはならなくなります。 (現状のようにファイルポインタを使いまわすのではなく、 要素分(=ファイル数)のファイルポインタを、常に開きっぱなしにしたいということです。) そのため、文字列をポインタ名にすることで、その作業を自動で行えるようにできればと考えています。 実際にchar型の配列が文字列になっているため、「FILE *buf」のように宣言しようと試みたのですが、 bufは既に文字列型の配列として宣言されているため、使用することができませんでした。 (文字列そのものをファイルポインタ名にできなくても、 この場合、要素数分のファイルポインタを自動で用意できれば問題ないのですが…) 下は簡単なプログラム例です。詳しい方のご助言を戴ければ幸いです。 よろしくお願い致します。 -------------------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <math.h> #define CAL 10000 /*計算回数*/ #define ELE 50 /*配列の要素数*/ #define NUM_CHAR 20 /*char型で確保する文字数*/ int i,j,n; /*forループ用*/ double x[ELE]; /*計算結果の配列*/ char buf[ELE][NUM_CHAR]; /*文字列*/ int main(void){ char filename[] = "test_x_"; char fileext[] = ".data"; /*「test_x_数字.data」という文字列の出力*/ for(i=0;i<ELE;i++){ sprintf(buf[i],"%s-I%d%s",filename,i,fileext); } for(n=1;n<CAL;n++){ /*計算部分*/ for(i=0;i<ELE;i++){ x[i] = 2*n+i; } /*ファイルに出力*/ for(i=0;i<ELE;i++){ FILE *fp; /*このファイルポインタ名を要素数分用意したい*/ if(n==1){ if((fp = fopen(buf[i],"w"))==NULL){ printf("The program can't create a file. : buf[i] \n"); exit(1); } } if(n>=2){ if((fp = fopen(buf[i],"a+"))==NULL){ printf("The program can't read a file. : buf[i] \n"); exit(1); } } fprintf(fp,"%d %f\n",i,x[i]) fclose(fp); } } return 0; } --------------------------------------------------------------------------------

  • VBでRS232Cの制御について。

    通信のデータ長やパリティ、ポーレート等の設定を”SETTINGS”でおこない、ポートをオープンして外部機器にデータを送る際、ここでは、データをバイナリデータで送らなければなりません。 STX,アドレス,チェックサム,ETXの順にそれぞれアスキーコードで16進数に変換して送ってますが、うまく通信できません。 教えて頂けませんか。 素人でごめんなさい。 この部分のサンプルプログラムがあれば最高なんですが・・・。

  • 配列の配列をmemcpyやmemcmpしたいです

    【環境】WindowsXP(SP2)、VisualStudio2005++(MFC) タイトルの通りなんですが、配列の配列を比較したりコピーしたいのですが、以下に質問を3つ記載させていただきますので、どなたかご教授お願いいたしますm(__)m 1.宣言と初期化について char **buf; buf = new char*[3200]; for(int i=0; i < 3200; i++) { buf[i] = new char[4]; } これで、buf[1]、buf[2]、buf[3]、buf[4]に、それぞれ3200のchar型の配列が宣言された事になりますでしょうか? ※buf[4][3200] なのか buf[3200][4]なのかよく分からないです。 2.上記の方法で定義した2つの配列(bufとtmp)の比較 for(int i =0; i < 4; i++) { memcmp (buf[i], tmp[i], sizeof(tmp[i])); } これで比較出来ますでしょうか? 3.上記の方法で定義した2つの配列(bufとtmp)のコピー for(int i =0; i < 4; i++) { memcpy_s(buf[i], sizeof(buf[i]), tmp[i], 3200 * sizeof(char)); } これではバッファオーバーランエラーが発生してしまうのですが、どこがおかしいでしょうか? 以上3点、初心者の質問なので意味が分からないような箇所があるとは思いますが、どうかご教授お願いいたしますm(__)m  

  • 同じコードがある初期化について教えてください。

    シューティングゲームのサンプルを勉強しています。 下記のこの部分のコードが二つあります。 memset(buf,0,sizeof(buf)); 気になっています。 なぜ二つあるのかを意味を知りたいです。 よろしくお願いします。 コードは以下に記述します。 CONTROL::CONTROL() { player = new PLAYER; back = new BACK; FILE *fp; ENEMYDATA data[ENEMY_NUM]; char buf[100]; int c; int col=1; int row=0; memset(buf,0,sizeof(buf)); fp = fopen("enemydata1.csv","r"); while(fgetc(fp)!='\n'); while(1){ while(1){ c=fgetc(fp); if(c==EOF) goto out; if(c!=','&& c!='\n') strcat(buf,(const char*)&c); else break; } switch(col){ case 1: data[row].type=atoi(buf); break; case 2: data[row].stype=atoi(buf); break; case 3: data[row].m_pattern=atoi(buf); break; case 4: data[row].s_pattern=atoi(buf); break; case 5: data[row].in_time=atoi(buf); break; case 6: data[row].stop_time=atoi(buf); break; case 7: data[row].shot_time=atoi(buf); break; case 8: data[row].out_time=atoi(buf); break; case 9: data[row].x=atoi(buf); break; case 10: data[row].y=atoi(buf); break; case 11: data[row].speed=atoi(buf); break; case 12: data[row].hp=atoi(buf); break; } memset(buf,0,sizeof(buf)); ++col; if(c=='\n'){ col=1; ++row; } } out: for(int i=0;i<ENEMY_NUM;++i){ enemy[i]=new ENEMY( data[i].type, data[i].stype, data[i].m_pattern, data[i].s_pattern, data[i].in_time, data[i].stop_time, data[i].shot_time, data[i].out_time, data[i].x, data[i].y, data[i].speed, data[i].hp, data[i].item); } }

  • 強制終了されていまいます。

    標準入力された1行を"<"から">"までと文字のところにわけるプログラムを書いたのですが、コンパイルして実行して入力すると、画面が黒くなって止まってしまいます。以下のところが問題の部分だと思うんですが、理由がわかりません。よろしくお願いします。 while(fgets(buf, 1024, stdin) != NULL){ i = 0; j = 0; while(buf[i] != '\n' || buf[i] != '\0'){ if ((x = (char *)malloc(sizeof(char))) == NULL){ printf("malloc error\n"); exit(1); } if(buf[i] == '<'){ j = i; while(buf[j] != '>'){ j++; } strncpy(x, &buf[i], j-i+1); i = j + 1; x[strlen(x)] = '\0' putRear(deq, x); } else if(isalpha(buf[i])){ j = i; while(buf[j] != '>'){ j++; } strncpy(x, &buf[i], j-i); i = j + 1; x[strlen(x)] = '\0'; putRear(deq, x); } } }

専門家に質問してみよう