CRC16コード作成プログラムの作成方法

このQ&Aのポイント
  • CRC16コード作成プログラムの作成方法について
  • CRC16コード作成プログラムを作成する際のポイント
  • CRC16コード作成プログラムの実装方法
回答を見る
  • ベストアンサー

CRC16コード作成プログラムについて

お世話なります。 PCと対象機械との通信を行おうと思っております。 内容としてCRC16のコードを使って、日時設定をPC→対象機器へ行いたいです。 CRC16の生成プログラムをいろいろ調べてみたところ、 今、自分のスキルでなんとかわかりそうなCRC16のソースが次の通りでした。 (行列の計算ぐらいならC言語で作れる程度です。。。) unsigned short crc_cal(unsigned short lng, unsigned char *str) { unsigned short crc, i, j, t; crc = 0xffff; for (i = 0; i < lng ; i++) { crc ^= (unsigned short) str[i]; for (j = 1; j <= 8; j++) { if (crc & 1) { // carry bit on crc = crc >> 1; crc ^= 0xa001; } else { // carry bit off crc = crc >> 1; } } } return crc; } “0C0C0C0C0C0C”と入力したら、CRCコードが算出されるプログラムを作りたく、 入力部分を作成してみたのですが・・・ int main(void) { unsigned short i,j, t; unsigned char str[256]; unsigned char str0; unsigned short crc; int k=0; printf("Please input key (HEX)\n"); for(k=0; k < 256; k++) { scanf("%c",&str0); // 文字列標準入力 if( str0=='\n') // Enterが押されたときの実行 { str[k]='\0'; // 文末にNULL文字 break; // for文のループ終了 } else { str[k]=str0; // NULLでなければ入力された文字を代入 } } crc = crc_cal(k,str); printf("crc=%X\n", crc); return 0; } 文字列を分解して・・・やるんだろうなってまではなんとなくわかるのですが、 どのようにしたらよいでしょうか。。。 ご教授よろしくお願いします。

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

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

>私ともう一人だけで使うプログラムなので、入力された文字数が奇数、16進数以外の入力は気を付けるって前提でやります(^_^;) 使う側が気をつける。 ということでエラー処理を省いていくなら…… int main(void) {  unsigned char str[256],data[128],hexstr[3];  unsigned short crc,len;  printf("Please input key (HEX)\n");  scanf("%255s", str);  hexstr[2]='\0';  for(len=0;len < (strlen(str)/2);len++)  {   hexstr[0]=str[len*2];   hexstr[1]=str[len*2+1];   data[len]=(unsigned char)strtol(hexstr, NULL, 16);  }  crc = crc_cal(len,data);  printf("crc=%04X\n", crc);  return 0; } こんなところでしょうかねぇ……。 # (strlen(str)/2)は変数に置き換えるかも知れませんが。 # まぁ、そのくらいはコンパイラの最適化が入りますかね……。 crc_cal()の中身に関しては…未検証ですけど……。

akibon1jp
質問者

お礼

お返事遅くなり、申し訳ございません! そしてありがとうございます! コンパイルできまして、すごく使えています!! ありがとうございました!

その他の回答 (1)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>“0C0C0C0C0C0C”と入力したら 文字列として扱いたいのですか? 0C 0C 0C 0C 0C 0C のバイナリ列として扱いたいのですか? >scanf("%c",&str0); // 文字列標準入力 ラインエディタを自作したい(BackSpace/Delete/カーソル移動キーとか押されたらどうします?)なら別ですが… "%s"で入力した方が楽かと思われます。 # scanf("%255s", str)としておけばバッファオーバーランしないでしょう。 # http://www.kijineko.co.jp/tech/superstitions/buffer-overrun-of-scanf.html バイナリ列として扱いたい場合は、入力されたHEX文字列からバイナリ列への変換が必要でしょう。 2文字切り取って16進文字列=>数値変換な関数で変換…ですかね。 # http://www1.cts.ne.jp/~clab/hsample/Func/Func12.html とか # strtol() とか(戻り値はlong型なので注意が必要ですが…)。 2文字ずつ切り出すことになるので入力された文字数が奇数だった場合をどうするか…というのもありますのでご注意を。 # 16進数文字列以外が入力された場合…なんてのもありますねぇ。 crc_cal()の第1引数に渡す値についても注意が必要…ですけどね。 # (strlen(str) + 1) / 2 とか。16進数文字以外があったりするとこの手は使えませんけどね…。

akibon1jp
質問者

お礼

お返事ありがとうございます! バイナリで扱いたかったですが、文字列でしか入力法がわからなかったってのが正直です。。。 私ともう一人だけで使うプログラムなので、入力された文字数が奇数、16進数以外の入力は気を付けるって前提でやります(^_^;) 戻す値の注意が必要となると・・・あきらめようかなぁ。。。

関連するQ&A

  • C言語のキャストについて

    お世話になります。 CRC-16の計算プログラムをC言語でつくりました。 例えば・・・1F 08 00 00 12 34 なら“1F0800001234”と入力すると【EEC2】と表示するプログラムです。 ただ・・・.Net SDKでコンパイルするとできたのですが、Visual C++2008でコンパイルするとエラーが出てしまいます。 (48) : error C2664: 'strlen' : 1 番目の引数を 'unsigned char [256]' から 'const char *' に変換できません。(新しい機能 ; ヘルプを参照) 1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。 (52) : error C2664: 'strtol' : 1 番目の引数を 'unsigned char [3]' から 'const char *' に変換できません。(新しい機能 ; ヘルプを参照) 1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。 型変換が必要ってことまではわかったのですが・・・必要なのはわかって行き詰まり状態です。。。 どのようしたらよいのでしょうか?ご教授をよろしくお願いします。 ソースは以下の通りです。 #include "stdafx.h" #include <stdio.h> #include <string.h> #include <stdlib.h> unsigned short crc_cal(unsigned short lng, unsigned char *str) { unsigned short crc, i, j, t; t= 0x0000; crc = 0xffff; for (i = 0; i < lng ; i++) { crc ^= (unsigned short) str[i]; t = (unsigned short) str[i]; for (j = 1; j <= 8; j++) { if (crc & 1) { // carry bit on crc = crc >> 1; crc ^= 0xa001; } else { // carry bit off crc = crc >> 1; } } } return crc; } int main(void) { unsigned char str[256],data[128],hexstr[3]; unsigned short crc,CRC,len; while(1) { printf("Please input key (HEX)\n"); scanf("%255s",str); hexstr[2]='\0'; for(len=0; len<(strlen(str)/2) ;len++) { hexstr[0]=str[len*2]; hexstr[1]=str[len*2+1]; data[len]=(unsigned char)strtol(hexstr, NULL, 16); } crc = crc_cal(len,data); CRC = (crc>>8) | (crc<<8); printf("\nCRC16 = %04X\n\n", CRC); } return 0; }

  • CRCの計算方法について

    色々なサイトを参考にして、自分なりにCRC-ITU-TでCRCを計算する関数を作成しました。 いまいち理解が浅く、そのCRCの値が正しいのか判断できずに困っています。 以下にソースを載せます。 アドバイスを、どうかよろしくお願いします。 unsigned short Crc(unsigned char *Data, unsigned long num) {   unsigned short vCrc;    //CRCを計算する変数   unsigned char vData;   unsigned long i;   int j;   vCrc = 0;   vData = 0;   //初期化   for(i = 0; i <= num; i++){     vData = *(Data+i);   //1byte読み込み     for(j = 0; j < 8; j++){       //CRC計算変数がシフトで桁あふれする場合       if((vCrc & 0x8000) != 0){         vCrc = vCrc << 1;   //1bitシフト         vCrc = vCrc ^ 0x1021;  //多項式とXOR       }       else{         vCrc = vCrc << 1;       }       if((vData & 0x80) != 0){         vData = vData << 1;   //データ変数1bitシフト                 vCrc = vCrc ^ 0x0001;  //CRC計算変数に1をXOR       }       else{         vData = vData << 1;       }     }   }   return(vCrc); }

  • プログラム(初心者)

    文字列を入力し中に含まれる空白を削除した文字列を作るプログラムなのですが #include <stdio.h> #include <stdlib.h> int main(void){ char str[100]; int i,j,c; printf("文字列を入力してください\n"); gets(str); i=j=0; do{ c=str[i++]; if(c!= ' ') str[j++]=c; }while(c); printf("空白を削除した文字列は%sです\n",str); return EXIT_SUCCESS; } do文の所何やってるかさっぱりわかりません 教えてください

  • プログラムのことで

    次のプログラムの変数の説明と処理の流れを素人でも理解できるように説明してもらえないでしょうか。 #include <stdio.h> #define MAX 128 int str_comp(char nx[], char ny[]){ int i, j, k=0; for(i=0; i<=MAX; i++){ if( nx[i]=='\0' ){ return 0; } else if( nx[i]==ny[0] ){ for( j=0; nx[i]==ny[j]; j++ ){ i++; } if( ny[j]=='\0' ){ return 1; } } } } int main(void) { char namex[MAX}; char namey[MAX}; int n; int i; printf("文字列x(64文字まで)? "); scanf("%s",namex); printf("文字列y(64文字まで)? "); scanf("%s",namey); n=str_comp(namex,namey); if(n==1){ printf("'%s'に'%s'は含まれます\n",namex,namey); } else if(n==0){ printf("'%s'に'%s'は含まれません\n",namex,namey); } return 0; } 実効結果 文字列x(64文字まで)? Katatsumuri  文字列y(64文字まで)? ta 'Katatsumuri'に'ta'は含まれます. エラーは出ないはずです。 よろしくお願いします。

  • RGBをCMYKに変換するプログラム

    Windows7 VS2008 SP1 RGBからCMYKに変換するプログラムを以下の様に書いている ([詳解]画像処理プログラミング という本に載っている ソースです) のですがうまくいきません。 おそらく型の扱い??だと思うのですが・・ 具体的にどの部分を修正すればいいのかご指摘お願いします。 INPUT:24bpp raw int RawToCMYK(WCHAR *filename,int width,int height) { FILE *fpt; FILE *fpt_C,*fpt_M,*fpt_Y,*fpt_K; unsigned char *layer; unsigned char *C,*M,*Y,*K; int i,j; _wfopen_s(&fpt,filename,L"rb"); if(fpt==0x00) { MessageBox(NULL,L"RawToCMYK Error",L"RawToCMYK Error",MB_OK); return -1; } else { layer=(unsigned char*)malloc(3*width*height); C=(unsigned char *)malloc(width*height); M=(unsigned char *)malloc(width*height); Y=(unsigned char *)malloc(width*height); K=(unsigned char *)malloc(width*height); fread(&layer[0],sizeof(unsigned char),3*width*height,fpt); fclose(fpt); _wfopen_s(&fpt_C,L"RawToC.raw",L"wb"); _wfopen_s(&fpt_M,L"RawToM.raw",L"wb"); _wfopen_s(&fpt_Y,L"RawToY.raw",L"wb"); _wfopen_s(&fpt_K,L"RawToK.raw",L"wb"); for(i=0;i<3*width*height;i+=3*width) { for(j=0;j<3*width;j+=3) { C[i/3+j/3]=255-layer[i+j]; M[i/3+j/3]=255-layer[i+j+1]; Y[i/3+j/3]=255-layer[i+j+2]; K[i/3+j/3]=min3(C[i/3+j/3],M[i/3+j/3],Y[i/3+j/3]); if(K[i/3+j/3]==0xff) { C[i/3+j/3]=0x00; M[i/3+j/3]=0x00; Y[i/3+j/3]=0x00; } else { C[i/3+j/3]=(C[i/3+j/3]-K[i/3+j/3])*255/(255-K[i/3+j/3]); M[i/3+j/3]=(M[i/3+j/3]-K[i/3+j/3])*255/(255-K[i/3+j/3]); Y[i/3+j/3]=(Y[i/3+j/3]-K[i/3+j/3])*255/(255-K[i/3+j/3]); } } } fwrite(&C[0],sizeof(unsigned char),width*height,fpt_C); fwrite(&M[0],sizeof(unsigned char),width*height,fpt_M); fwrite(&Y[0],sizeof(unsigned char),width*height,fpt_Y); fwrite(&K[0],sizeof(unsigned char),width*height,fpt_K); fclose(fpt_C); fclose(fpt_M); fclose(fpt_Y); fclose(fpt_K); free(C); free(M); free(Y); free(K); return 0;

  • プログラム(C)

    #include <stdio.h> #include <stdlib.h> #define FNAME "smp.bmp" #define WSIZE 256 #define HSIZE 256 #define BSIZE 1024 int main(void) { struct BMPFILEHEADER { ・   ・ }; struct BMPINFOHEADER { ・   ・ }; unsigned char img[HSIZE][WSIZE][3]; unsigned char buf[BSIZE]; struct BMPFILEHEADER lpHead; struct BMPINFOHEADER lpInfo; FILE *fp; int i; int j; int k; fp = fopen(FNAME,"rb"); if (fp==NULL) { printf("ファイルをオープンできません\n"); return 0; } fread(&lpHead.bfType, sizeof(unsigned short),1,fp); fread(&lpHead.bfSize, sizeof(unsigned int),1,fp); fread(&lpHead.bfReserved1, sizeof(unsigned short),1,fp); fread(&lpHead.bfReserved2, sizeof(unsigned short),1,fp); fread(&lpHead.bf0ffBits, sizeof(unsigned int),1,fp); fread(&lpInfo, sizeof(struct BMPINFOHEADER),1,fp); for(i=0;i<HSIZE;i++) { fread(buf,sizeof(unsigned char),WSIZE*3,fp); for(j=0;j<WSIZE;j++) { for(k=0;k<3;k++) { img[HSIZE-1-i][j][k]=buf[j*3+k]; } } } fclose; return 0; } このプログラムはBMP画像を読み込むプログラムなんですが このプログラムに画素値を出力するプログラムにしたいのですがうまくできません。 結果は(真っ白な画像の時)255255255・・・255255と出力したいのです。白黒画像なのでR=G=Bで1画素値は255だけでいいのですが。どうしても255255255や25500などとでてしまいます。 アドバイスお願いします。(800字までなので構造体の宣言は抜いてしましました) 。

  • 文字列の入力、数値変換について

    入力された数字を数値に変換するプログラムを作ったのですが、うまくいきません。 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <ctype.h> unsigned long long atollu(char[16]); void main(void){ unsigned long long input; char str[16]; char test[16] = "123456789012345"; int i,j=1; //atollu の動作確認・・・(1) printf("atollu test:%llu\n\n",atollu(test) ); //入力 NG: printf("%d回目 数値を入力(1~100000000000000 終了:exit)>",j); gets(str); input = atollu(str); //str と atollu(str) の確認 printf("%s %llu\n\n",str,atollu(str)); //exitと入力すると終了・・・(2) if(strcmp(str, "exit") == 0){ exit(0); } //数字以外がないか確認・・・(3) else { for( i=0; i<=15; i++){ if(isdigit(str[i]) == 0){ printf("NG\n"); for( i=0; i<=16; i++){ str[i]='\0'; } printf("moji\n"); j++; goto NG; } } } //範囲外 if(input>100000000000000 || input==0){ printf("NG\n"); printf("hani\n"); j++; goto NG; } printf("\n入力値は% llu",input ); } unsigned long long atollu(char str[16]){ unsigned long long t=0; int i,n; n = strlen(str) - 1; for( i=0; i<=15; i++){ if(str[i] == '\0'){ str[i] = 0;} else { t = t + (str[i] - '0') * pow(10.0,n-i);} } str[16] = '\0'; return t; } /* 数字を数値に変換する関数atolluは自分で作りました。 これの動作は(1)でちゃんとした値が出ているのでうまくできているようです。 (2)も"exit"と入力すれば終了するのでうまくいっています。 また、例えば "12" と入力したとき 12 9 NG moji 表示されますが、二回目以降は 12 12 NG moji となり、atollu(str)はうまく出力されている一方で、最後に「moji」と出てきているので、(3)でうまくいっていないようです。 どう直すべきなのか見当もつかないので困っています。 よろしくお願いします。

  • かぶった文字を消すプログラム

    文字列s2中の任意の文字に等しい文字をs1から除外するプログラムを以下の様に作りましたが、ビルトと入力は出来るものの、出力が出ません。何が間違っているのでしょう? #include <stdio.h> main() { int i,j,c; char s[100],t[100]; for( i = 0; (c = getchar()) != '\n'; i++){ s[i] = c; } for( i = 0; ((c = getchar()) != '\n') && (c != EOF); i++){ t[i] = c; } for( i = 0; s[i] != '\0'; i++){ for( j=0; t[j] != '\0'; j++){ if( s[i] == t[j] ){ s[i] = ' '; } } } for( i = 0; s[i] != '\0'; ++i ){ printf("%s", s[i]); } }

  • strstrを利用しない文字列検索について

    キーボードから入力した文字列 str に対し, This is~の文字列中に str が出現するかどうかを判定して表示するプログラムを作成したいのですが、うまくコンパイルができません。 条件ですが、、、 ・forループを利用し、0文字目、1文字目と順に検索していく ・strstr関数およびstring.hを利用しない です。このプログラムをいじって教えてほしいです。 ややこしくて答えづらい質問かと思いますが、有識者の知恵を拝借したいです。よろしくお願いします。 #include <stdio.h> int main(void) { char str[256]; char s[] = "This is a pen. That is an apple."; int i,j,k,checker; printf("This is a pen. That is an apple.\n\n"); gets(str); for(j=0;j<256;j++) { for(i=j,k=0;str[k]!='\0';k++,i++) { if(str[k]==s[i]) { checker=1; } else { checker=0; } } } if(checker==0) { printf("NG!その文字列は含まれていません。\n"); } else { printf("OK!その文字列は含まれています。\n"); } }

  • スタックのプログラムを作成しているのですが、うまく出来ません。

    プログラムの内容を簡単に言うと、配列s[100]と変数topを用いて、ファイルdata.datからgetc()を用いて文字を1文字ずつ読み込み、スタック(s[100])にpush-downするプログラムです。 細かく言うと、作成したプログラムによりファイルからキー(文字)を読み込みスタックにpush-downし、スタックの内容を表示した後に、キーボードからキー(文字)を1文字ずつ入力して、スタックを操作する。 ・スタック操作の仕様はキーボードからキー(文字)を1文字ずつ入力する際に、0を入力した場合、プログラム終了。1を入力した場合、1文字pop-upした後、pop-upした文字とスタックの内容を表示。その他の文字を入力した場合、その文字をpush-downした後、スタックの内容を表示。(スタックの内容の表示はprint_stack_mtrx(s,top)を使用する。) ・push-downとpop-upはそれぞれ1つの関数で定義する。 といった感じのプログラムを作成しているのですが、関数push,popの部分をどう書いたら良いのか良く分かりません。一応自分で書いてみたのですが、うまくいきませんでした。どなたか教えていただけないでしょうか? *ファイルdata.datからはリダイレクションを用いて読み込む。 <作成途中のソースプログラム> #include<stdio.h> #include<stdlib.h> #define MAX 100 char s[MAX]; int top; void init_stack(){ ______top = 0; _______return; } void print_stack_mtrx(char* s, int top){ __int i; ____if(top == 0){ ______printf("Stack is empty.\n"); ____} ____else{ ______printf("--- Contents of Stack ---\n"); ______for(i = 0; i < top; i++){ ________if(!i){ __________printf("%2c < -- Top (%2d)\n", s[top - i - 1], top); ________} ________else{ __________printf("%2c \n", s[top - i - 1]); ________} ______} ______printf("-------------------------\n"); ____} } char push(char* s, int top, char j){ ___s[top]=j; ___top++; } char pop(char* s, int top){ _char c; ___c = s[top]; ___top--; ___return c; } int main(void) { _int c; _char j; _char i; init_stack(); _______while(((c=getc(stdin))!=EOF) && top<MAX){ _______/* ファイルdata.dat からgetc()を用いて1文字ずつ読み込みスタックsに格納.ただしスタックの出入り口を示す top の値も監視すること*/ _________s[top] = c; _________top++; _______} _______print_stack_mtrx( s, top );/* スタック(配列)の内容を表示する関数*/ _______while(1){ _________scanf("%c\n", &j); _________if(j=='0'){ ___________break; _________} _________else if(j=='1'){ ___/* 1文字pop-upした後, pop-upした文字とスタックの内容を表示 */ ___________i = pop(s, top); ___________printf("pop-upした文字: %c\n", i); ___________print_stack_mtrx( s, top ); _________} _________else{ ___/* その他の文字を入力した場合, その文字をpush-downした後,スタックの内容を表示 */ ___________push(s, top, j); ___________print_stack_mtrx( s, top ); _________} _______} _______return 0; }

専門家に質問してみよう