--宣言--
typedef struct
{
int len;/* ptrの長さ */
unsigned char *ptr;
} aaa;

char abc[128];
--宣言end----

HIKAKU(aaa *d1,char *d2)
{
d1,d2にはそれぞれデータが入力されてくる。
d2はabcのポインタ。

}

d1,d2の実体を比較し一致するか否か判定したいのですが、
何分初心者なもので・・・
アドバイス頂けないでしょうか?
宜しくお願い致します。

A 回答 (5件)

>できれば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)を見れば判ります。
    • good
    • 0

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でもワーニングになったりエラーになったりします。
    • good
    • 0

先ほどの私の回答にバグがありました。

ごめんなさい。
たとえば、
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);
}
------------------------------------------
きっと、もっとスマートなやり方あるんでしょうね。
でも、比較自体はカンペキになったでしょ?

この回答への補足

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

補足日時:2001/04/13 12:14
    • good
    • 0

わざわざ、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/ …
    • good
    • 0

単純に



if( strcmp( d1->ptr, d2 ) == 0 ) {
// 一致した場合の処理
}
else {
// 一致しなかった場合の処理
}

でいいんじゃないですか?
    • good
    • 0

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

このQ&Aと関連する良く見られている質問

Qchar *str; と char* str;

char *str; と char* str;
どっちも同じことを意味しているんですか?

Aベストアンサー

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染むのでしょう。ちなみにそういう風な人たちは

char *str1, *str2;

とは、書けない体になっています。

char* str1;
char* str2;


変数の宣言だと、C に慣れていれば、char* str というのはちょっと違和感があるのは
私も分かりますが、関数のプロトタイプ宣言だと、どちらの方がすっきりしますか?

extern char *memcpy(char *, const char *);

extern char* memcpy(char*, const char*);


# まあ、どっちが正しい、っていうんじゃ無いんですよね

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染む...続きを読む

Qchar AA[]{"全角文字"};から"全"という一字を取り出したい

 今晩は、Cの初心者です、宜しくお願いします。
 全角文字の入ったchar AA[]{"全角文字"};から"全"という文字一字を取り出す時にAA[0]とかくとエラーになります。
 どのようにしたら取り出せるのでしょう。
 ポインタを使う方法と使わない方法を教えて下さい。
 宜しくお願いします。

Aベストアンサー

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出す必要があります。

>char AA[]={'全','角'};

char AA[]="全角";
とし
>printf("%s%s\n" , AA[0],AA[1] ) ;

printf("%c%c\n" , AA[0],AA[1] ) ;
とすれば、「全」だけを表示する事が可能と思われます。

日本語を文字列で表示する為の文字コードについては
Shift-JISだけでなく、UnicodeやUTF・EUC・JISなどがあります。

もう少し詳しく記載してあるホームページはないか探してみましたが、ちょっと無理でした。

参考URL:http://marupeke296.com/CPP_charUnicodeWideChar.html

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出...続きを読む

Qchar* を渡したとき、不適切な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"のように書かなければならず困っています。

こんばんは。プログラムを勉強中の学生です。
詰まった部分があり、関連しそうな部分を勉強しましたが、問題が解決しなかったので、
こちらで質問させて頂きます。

今、とあるクラスで、

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){
...続きを読む

Aベストアンサー

>while(str != "\0")

while(*str != '\0')
じゃないですか?
つまり
while(*str)
でも良し。

Qtry{}catch(){}とデストラクタの関係を教えてください。

try-catchでメモリ確保を含むクラスをスローした場合、デストラクタはどの時点で働くのか、教えてください。たとえば、↓の使いかたは大丈夫でしょうか?

【1】
try{
 throw(CError(100, "エラー情報"));
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
}

【2】
try{
 CError err(100, "エラー情報");
 throw(err); // (1)
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
 //まだデストラクタはちゃんと動作するのでしょうか?
 //catchが呼び出し元のメンバであったりしても大丈夫なのでしょうか?
}

宜しくお願いします。

Aベストアンサー

【1】【2】どちらの場合も問題がありません。
コンパイラが必要に応じてerrオブジェクトのコピーを作成します。
デストラクタが呼び出されるタイミングはコンパイラに依存するところもあると思いますが、
例えばVC7.1では【2】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) CErrorクラスのテンポラリオブジェクト(以下a)のコピーコンストラクタが呼び出される。
(3) errオブジェクトのデストラクタが呼び出される
(4) catch文まで到達
(5) aオブジェクトのデストラクタが呼び出される。

VC7.1では、【1】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) catch文まで到達
(3) errオブジェクトのデストラクタが呼び出される。

コンパイラがオブジェクトのコピーを省略しているようです。

Qchar *(*)[3];について

#include <iostream.h>
main(){
char *(*pp)[3];
printf("%lu", sizeof(char*));
printf(" pp%lu", pp);
printf(", ++pp%lu", ++pp);
}

これを実行して
4 pp6660000, ++pp???????
のように表示されたときに、???????の部分が何になるか考えました。
ppはchar[3]を指すポインタのポインタだから、ppをインクリメントすれば、「char[3]を指すポインタ」の大きさだけ大きくなるはずだから、「char[3]を指すポインタ」の大きさである4バイト大きくなるはずだから
4 pp6660000, ++pp6660004
になると思いました。
どこを勘違いしていてどう考え直せばよいか教えて下さい。

Aベストアンサー

pp は、3コのポインタの配列へのポインタです。
ポインタのサイズが4バイトの時、
pp をインクリメントすると12バイト増えることになります。

例えば、次の様に書くとわかりやすいと思います。
#include <cstdio>

using namespace std;
// CHAR3 は、3のサイズを持つchar の配列
typedef char CHAR3[3];

int main(){
CHAR3 *pc3;//pc3 は、char[3]を指すポインタ
char test[3];
pc3=&test;
printf("%p\n",pc3);
pc3++;
printf("%p\n",pc3);//+3(サイズ分)される

CHAR3 **ppc3;//ppc3 は、char[3]を指すポインタのポインタ
ppc3=&pc3;
printf("%p\n",ppc3);
ppc3++;
printf("%p\n",ppc3);//+4(ポインタサイズ分)される

return 0;
}

pp は、3コのポインタの配列へのポインタです。
ポインタのサイズが4バイトの時、
pp をインクリメントすると12バイト増えることになります。

例えば、次の様に書くとわかりやすいと思います。
#include <cstdio>

using namespace std;
// CHAR3 は、3のサイズを持つchar の配列
typedef char CHAR3[3];

int main(){
CHAR3 *pc3;//pc3 は、char[3]を指すポインタ
char test[3];
pc3=&test;
printf("%p\n",pc3);
pc3++;
printf("%p\n",pc3);//+3(サイズ分)される

CHAR3 **ppc3;//p...続きを読む


人気Q&Aランキング

おすすめ情報