• ベストアンサー

データの比較の仕方について

--宣言-- typedef struct { int len;/* ptrの長さ */ unsigned char *ptr; } aaa; char abc[128]; --宣言end---- HIKAKU(aaa *d1,char *d2) { d1,d2にはそれぞれデータが入力されてくる。 d2はabcのポインタ。 } d1,d2の実体を比較し一致するか否か判定したいのですが、 何分初心者なもので・・・ アドバイス頂けないでしょうか? 宜しくお願い致します。

  • sting
  • お礼率12% (35/274)

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

  • ベストアンサー
  • lan-c
  • ベストアンサー率80% (4/5)
回答No.4

>できればstr系ではなく、mem系を使用する >ようにと言われているのですが・・・。 ずいぶんと、イジワルなことを言われちゃいましたね。 では、がんばってみましょう。 { char *ptr1, *ptr2; int maxleng; maxleng = (d1->len - strlen(d2) < 0)?strlen(d2):d1->len ; ptr1 = malloc((size_t)maxleng+1); ptr2 = malloc((size_t)maxleng+1); memset(ptr1, 0x00, maxleng+1); memset(ptr2, 0x00, maxleng+1); memcpy(ptr1, d1->ptr, d1->len); memcpy(ptr2, d2, strlen(d2)); if( memcmp( ptr1, ptr2, maxleng ) == 0 ) { // 一致した場合の処理 } else { // 一致しなかった場合の処理 } free(ptr1);free(ptr2); } ----------------------------------------------- どうでしょう?判りにくくなったでしょ?(笑) memcmpで比較する2つの領域のサイズが、memcmpの第3パラメータ で指定する数値よりも小さいと、落っこちる可能性が あるんで、maxlengを求めるようにしました。 私なら、間違い無くstrcmp()を使います。楽だし。見やすいし。 それか、whileしながら1文字ずつ比較する内部関数を作ります。 >比較対照がunsigned char と charのためキャストしなけ >ればコンパイルエラーとかなりませんか? エラーにはなりませんが、気になるなら、 strcmp((char *)ptr, d2) または、 memcmp((void *)ptr1, (void *)ptr2, (size_t)maxlen) にしてみましょう。でも、ここまでするのはヤリスギな気がします。 何にキャストするのが正解かは、string.hとかmemory.hの中を 見たり、HELP(とかman)を見れば判ります。

その他の回答 (4)

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.5

strlen(d2)とd1->lenが違えば(=長さが違えば)既に一致しないわけですから比較する必要はありません。 よって、比較はmemcmp(d2, d1->ptr, d1->len)でオッケーです。 if (strlen(d2) == d1->len) { if (!memcmp(d2, d1->ptr, d1->len)) { /* 一致 */ return ; } } /* 不一致 */ キャストについては C:viod*は全てのポインタを受け入れるので必要なし C++:void*とunsigned char *,char *の変換についてワーニングがでるので(void*)へのキャストをしてもよい。 標準C/C++の時ですのでコンパイルオプションによってはCでもワーニングになったりエラーになったりします。

  • lan-c
  • ベストアンサー率80% (4/5)
回答No.3

先ほどの私の回答にバグがありました。ごめんなさい。 たとえば、 d1->ptr が "abc" で、 d2が "abcd"の場合、 d1->lenは、d1->ptrの長さなので、 3 になりますよね。 そうすると、 strncmp( "abc", "abcd", 3 ) になります。 これでは、先頭の3文字しか比較していないため、「一致している」 となってしまいます。(gccで確認しました) やっぱり、d1->ptrをヌルターミネートしている別変数にいれた方が よさそうですね。(頭悪くてごめんなさい) ---------------------------------------- { char *ptr; ptr = malloc((size_t)d1->len + 1); memset(ptr, 0x00, d1->len+1); memcpy(ptr, d1->ptr, d1->len); if( strcmp( ptr, d2 ) == 0 ) { // 一致した場合の処理 } else { // 一致しなかった場合の処理 } free(ptr); } ------------------------------------------ きっと、もっとスマートなやり方あるんでしょうね。 でも、比較自体はカンペキになったでしょ?

sting
質問者

補足

ありがとうございます。 ただちょっと補足なのですが、 できればstr系ではなく、mem系を使用する ようにと言われているのですが・・・。 また、比較対照がunsigned char と char のためキャストしなければコンパイルエラー とかなりませんか?

  • lan-c
  • ベストアンサー率80% (4/5)
回答No.2

わざわざ、d1->lenで、長さをもっているんで d1->ptrはヌルターミネートしていない可能性 がありますね。 ---------------------------------------------- if( strncmp( d1->ptr, d2, d1->len ) == 0 ) { // 一致した場合の処理 } else { // 一致しなかった場合の処理 } ---------------------------------------------- こっちの方が安全かも知れません。 ただし、strncmp()はクセがある関数なので、 HELPなどを良くみてください。 もし、d1->ptrがヌルターミネートされているのなら、 cockyさんの方法の方が安全確実で、お勧めです。

参考URL:
http://flex.ee.uec.ac.jp/www/japanese/edu/95IC2/C-nyuumon/strncmp.html
  • cocky
  • ベストアンサー率57% (232/402)
回答No.1

単純に if( strcmp( d1->ptr, d2 ) == 0 ) { // 一致した場合の処理 } else { // 一致しなかった場合の処理 } でいいんじゃないですか?

関連するQ&A

  • 基本的な領域確保の仕方について

    下記のような構造体が宣言されている場合、 A.c.e ←を配列扱いにし、 A.c.e[0].g.h ←を配列扱いにし、 A.c.e[0].g.h[0].iにデータを設定するには、 どのように領域を確保すれば良いのでしょうか? eee型はポインタ宣言のみされていて配列宣言されて いません。(Max10配列) typedef struct { int len; char *i; } hhh; typedef struct { int number; hhh *h; } ggg; typedef struct { fff f; ggg g; } eee; typedef struct { int number; eee *e; } ccc; typedef union { aaa a; bbb b; ccc c; ddd d; } A;

  • 1バイトデータの読み出しについて

    こんばんは。 すみません。文字操作?ポインタ操作が苦手なので教えてください。 以下のような構造体があり、その構造体から1バイトずつ読み出して 自作の関数のパラメータ(1バイト指定領域)に渡したいのですが、 構造体から1バイトずつデータを読み出すには、どのようにすればいいのでしょうか? typedef struct { PACKET_HEADER head; unsigned char Sp_Pr_St[1]; unsigned char ctrl_flow[1]; unsigned char product_org[10]; unsigned char product_name[10]; unsigned char product_ver[3]; }PRODUCT_RESPONS; typedef struct { unsigned char head; unsigned char type; unsigned char data_len; } HEADER; どうぞよろしくお願いします。

  • ポインタ代入のoperator演算子のオーバロードの仕方

    下記、unsigned char*型を自前のクラスで作成した場合 どの様なoperator演算子が必要になりますでしょうか。 目的は、下記compにアクセスした回数をカウントさせたい為です。オーバロード関数の内部にカウンタを持たせたい。 unsigned char* と互換性を持たせるため、クラスはポインタとして定義して使用したいと思っています。 unsigned char comp[1000] ; int main( int, char** ){ unsigned char *v_ptr ; v_ptr = &comp[0] ; <- ここ *v_ptr = (unsigned char)100 ; <- ここ *v_ptr++ = *sw_ptr++ ; <- ここ return 0; } 下記のように使いたい unsigned char comp[1000] ; int main( int, char** ){ count * v_ptr ; v_ptr = &comp[0] ; <- ここ *v_ptr = (unsigned char)100 ; <- ここ *v_ptr++ = *sw_ptr++ ; <- ここ return 0; } class count{ public: unsigned char* operator*() { return ptr ; }  v_ptr& operator=()?? private: unsigned char* ptr ; } ; 色々調べてみましたが、自前クラスが右辺にある時のポインタ、アドレスオーバロードはありましたが、左辺のポインタ代入、値代入を見つける事が出来ませんでした。

  • ループを使用して変数に格納したい

    ====宣言===== typedef struct{ int a; int b; int c; }ABC; typedef struct{ int d; //e配列の個数 ABC e[10]; }DEF; char vvv[BUFSIZ]; ====宣言===== 上記宣言がされている場合、 vvvにカンマ編集でa,b,c,a,b,c・・・ というデータをsprintfでdの数分代入したい のですが、何か良い方法はありませんでしょうか? よろしくお願いします。

  • 構造体の宣言について

    今解析しているC言語のプログラムで以下の様な構造体の宣言があります。 typedef struct { unsigned char :3; unsigned char aaa :1; unsigned char bbb :1; unsigned char ccc :1; unsigned char ddd :1; unsigned char eee :1; } tTSR ; :3や:1の部分の意味がわかりません。 御存知の方ご回答よろしくお願いします。

  • リトルエンディアン→ビッグエンディアン

    (1)リトルエンディアン typedef struct recvData{  int a;  unsigned char b[16]; unsigned char c[8]; unsigned int d[4]; } recvData_t; recvData_t rData; (2)ビッグエンディアン typedef struct sendData{  int a;  unsigned int b[4]; unsigned int c[2]; unsigned int d[4]; } sendData_t; sendData_t sData; 上記のようなリトルエンディアンの構造体の各メンバのデータを、ビッグエンディアンの構造体の各メンバのデータにそれぞれ格納するには どうしたらよいでしょうか?

  • 仮引数の変数をローカル変数に格納する理由について

    プログラムの多くは、仮引数のポインタを一度ローカル変数に格納して使っていますが、なぜでしょうか?データが壊れてしまったりするのでしょうか・・・ typedef struct _LIST{ int value; struct LIST *next; struct LIST *prev; }LIST,*LIST_PTR; void func(LIST_PTR list, char *str){ LIST_PTR wk_list; char *wk_str; wk_list = list; wk = str;

  • 構造体・ビットフィールドのvolatileに関して。

    以下のような構造体があったとする。 -(1) -----------------------------  typedef volatile struct ABC{    char x;    char y;  }stABC; -(2) -----------------------------   typedef struct ABC{    volatile char x;    volatile char y;  }stABC; --------------------------------- ■質問  -------------   stABC abc;   abc.x // ←volatileは有効?   abc.y // ←volatileは有効?  ------------- ・このとき、メンバx,y は(1)/(2)の構造体型宣言どちらでも  同じ意味合いになっているのでしょうか。  ※特に(1)の場合、volatileは有効になっているのでしょうか。 ・ビットフィールド時も同じと考えて問題ないでしょうか。   (1)typedef volatile struct ABC{      char x: 1 ;      char x: 7 ;    }stABC;   (2)typedef struct ABC{      volatile char x: 1 ;      volatile char x: 7 ;    }stABC;

  • char* を渡したとき、不適切なPtrが出る問題

    こんばんは。プログラムを勉強中の学生です。 詰まった部分があり、関連しそうな部分を勉強しましたが、問題が解決しなかったので、 こちらで質問させて頂きます。 今、とあるクラスで、 class Test{ ........................................ public: int Func1(char* str,){ unsigned int n = 0; while(str != "\0"){ n += *str; str++;}          ←ここに<不適切なPtr> return n % 3; } void Func2(char* str){ int i; i = Calc(str); ..................................... ............................ } }; のように宣言し、main()関数で、 int main(){ Test test; test.Func2("ABC"); // Case1: エラーは起こらない char s[]={"ABC"}; //Case2:不適切なPtrとなる。 test.Func2( s ); } としていますが、上記のように、"ABC"を直接入れたときのみ、うまくいき、 他の方法で、char型のポインタを代入した際には、不適切なPtrと出てしまいます。 この原因を教えていただけないでしょうか? 最終的には、 cin >> s ; などのように、キーボードから入力した値(文字列)を使いたいのですが、 現段階ではmain関数で "ABC"のように書かなければならず困っています。

  • ポインタ配列の動的確保

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。