• ベストアンサー

CStringのFindで文字列検索を行いたいのですが

こんにちは。 いつもお世話になっております。 CStringのFindメソッドで文字列検索を行っているのですが、文字列ではなくコードで検索が行われてしまい困っています。 ------------------------------------------------------- CString TargetStr; TargetStr = "ハヒフヘホ"; if(TargetStr.Find("z", 1) != -1){ return FALSE; } ------------------------------------------------------- 上記で文字"ホ"のコードが「837A」で"z"が「7A」のため、 文字列が存在するという結果が帰ってきます。 コードではなく文字そのものの検索をするにはどうしたらよいでしょうか? 基本的なことで申し訳ありませんが、ご教示下さい。 <環境> Windows 2000, VC6.0

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

  • ベストアンサー
  • circuit
  • ベストアンサー率72% (13/18)
回答No.4

CString::Findメソッドは、1バイトごとの検索を行うので、そのような結果になってしまいます。 このような処理を避けるには、CString::Findではなく、_mbsstrを利用します。 詳しくは、MSDNを参照のこと。 http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/vclib/html/_crt_strstr.2c_.wcsstr.2c_._mbsstr.asp どちらかといえば、_tcsstrを利用してUnicodeとMBCSの両方に対応できるようにしておいたほうがいいです。 #この場合、_UNICODEもしくは_MBCSのどちらかが設定されていないと正しく動きません。 *注意* この関数はANSIに互換性がないようですので、Windows以外では利用できない可能性があります。 また、上記のような関数を使わず、自分で実装するなら、以下の参考URLを参考にしてください。 参考URL:シフトJIS文字列の文字検索

参考URL:
http://katsura-kotonoha.sakura.ne.jp/prog/c/tip0002d.shtml
sputnik8823
質問者

お礼

circuitさん、コメントありがとうございます。 返事遅くなり申し訳ありません。 _mbsstrを使用する方向で行きたいと思いますがつまづいています。 また機会があればご教示下さい。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

  • circuit
  • ベストアンサー率72% (13/18)
回答No.5

#4です。 > *注意* > この関数はANSIに互換性がないようですので、Windows以外では利用できない可能性があります。 を以下のように訂正。 *注意* この関数はANSIに互換性がないようですので、VC以外では利用できない可能性があります。 VC6.0はもっていないのでわかりませんが、 VS.NET2005及びBorlandC++Complierにて動作を確認しました。

全文を見る
すると、全ての回答が全文表示されます。
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.3

#2です。ミスがあったので訂正します。  CStringW TargetStrW = L"ハヒフヘホ";  if(TargetStrW.Find(L"z",+)!=-1){   return FALSE;  }

全文を見る
すると、全ての回答が全文表示されます。
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.2

VC6でCStringWが使えるかどうかはわかりませんが(手元にVC8(2005)しかありません) 使えるなら  CStringW TargetStrW = L"";  if(TargetStrW.Find(L"ハヒフヘホ",1)!=-1){   return FALSE;  } とする方法があります。もちろんこれだとUNICODE→ANSIに変換するプロセスも必要になるでしょう。 そうでなければCStringを継承するなりして 自作する必要があります。 継承ではありませんが以下のようにして判定できます。  CString TargetStr = "ハヒフヘホ";  const char *searchstr = "z";  for( int i = 0 ; i < TargetStr.GetLength() ; i++ ){   if ( *(TargetStr.GetBuffer()+i) < (char)0 ){    i++;    continue;   }   if ( strncmp( TargetStr.GetBuffer()+i , searchstr , strlen(searchstr) ) == 0 ){    return FALSE;   }  }

参考URL:
http://www.doumo.jp/postgretips/tips.jsp?tips=18
sputnik8823
質問者

お礼

sha-girlさん、コメントありがとうございます。 返事遅くなり申し訳ありません。 残念ながら、VC6でCStringWは使用できませんでした。

全文を見る
すると、全ての回答が全文表示されます。
  • FAY
  • ベストアンサー率49% (95/193)
回答No.1

デフォルトでお望みの動作をするものは、少なくとも私の記憶にはありません。 検索されたインデックスの位置にある文字がマルチバイト文字の一部か否かを判定して、もしマルチバイト文字の一部ならば次を検索・・・みたいな感じでしょうか。 #判定の仕方はキャラクタセットによって変わってくるので割愛します

sputnik8823
質問者

お礼

FAYさん、コメントありがとうございます。 返事遅くなり申し訳ありません。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • キャストについて str = (CString*)("999") ;

    環境 WIN98 VC++6.0 MFC にて いつもお世話になります。 先日質問したばかり(QNo.682705)なのですが、やはり納得できないことがあるのでお願いします。 分かっている人からみれば、おかしな疑問と思われるかも知れませんが、私にとっては素朴に疑問が生じてしまいます。 *************************** 以下2つのコードのうち、<A>は文法的にOKで<B>がNGな理由が知りたいです。 <A> CString* str ; str = (CString*)m_array.GetAt(i) ; //OK <B> CString* str ; str = (CString*)("999") ; //NG <A>は、m_arrayの要素にCString*を入れていて、初めて成り立つ式です。 と教わりましたが、むしろ私にはCString*以外が入っているため、CString*のキャストしていると思える。 CString*が入っているのなら、キャストする必要は無いのではないでしょうか? ネット上で見つけたコードなため、実際の値やm_arrayの宣言がどうなっているかは確認出来ません。 そして、<A>がおかしなコードでは無いという大前提にたつと、<A>は別の表現をすると <A> str = (CString*)(CString*以外のポインタ) ; となります。 そうすると<B>のコードも、"999"は999の文字列が入っているアドレスを指すポインタであるという考えが正しいとすると、 <B> str = (CString*)(999をさすポインタ) ; となり、おかしなコードではないと思えるのですが、考え方のどこがおかしいのでしょうか? ************************** 以下のことを教わった上であえて聞いています。 str = (CString*)("999"); は、リテラル文字列をつっこもうとしています。 リテラル文字列とCStringはまったく別物です。

  • CStringについて

    CStringにおいてFindではエラーが出ないのに、ReverseFindだとエラーがでます。 error C2664: 'ReverseFind' : 1 番目の引数を 'char [4]' から 'char' に変換できません。 (新しい機能 ; ヘルプを参照) この変換には reinterpret_cast, C スタイル キャストまたは関数スタイルのキャストが必要です。 キャストするとエラーは出ませんが文字列の検索は失敗してしまいます。 Findはまったく問題無いのにどうしてこのようなことが起きるのでしょう? どう対処すれば良いか教えてください。 CString ddd; ・ ・ nn=ddd.Find("DOW");     ←エラーなし nn=ddd.ReverseFind("DOW"); ←エラーあり 環境はWIN98 VC++6.0 MFCです。

  • 検索値に数値や文字列で検索してもエラーになる

    WIN7 EXCEL2007でマクロ作成中の初心者です。  A列(セルA3からA20)に  組、 Z3、 B4(1)、45、8 などの文字列や数値が表示されています。  (セルA列には、VLOOKUPで他の表から検索したものです。)   そして、C列に(セルC3からC20) セルA3が 組のときは   セルC3に 5:00 を入れなさい セルA4が Z3のときは   セルC4に 6:00 を入れなさい セルA5が B4(1)組のときは セルC5に 9:00 を入れなさい    セルA6が 45  のときは セルC6に 11:00を入れなさい という式をいれたいのです。 ちなみに自分で以下の式をいれて確認したところ =VLOOKUP(A3,データ範囲名,2,FALSE) =VLOOKUP(A4,データ範囲名,2,FALSE) =VLOOKUP(A5,データ範囲名,2,FALSE) 以下つづく するとセルA3の表示が W3 のときは #N/Aになり W3のとき正常に表示されます。 45という数字も出来ました。 検索値は文字列でも数値でもOKと聞いてますが、なぜ出来ないのでしょうか? 他のfindとか別の方法でも出来る方法教えていただきたいです。

  • C++(VC6)で、CString型を配列へ

    C++(VC6)で、CString型の文字列をCString型の配列へセットする方法を教えてもらえませんか? キーワード検索で、AND検索・OR検索を実現する為に、まずはCString型の文字列をCString型の配列にセットしたいです。 例えば、 □阪神□□□野球□赤松□□ と入力されたCString型の文字列を、 keyword[0] = 阪神 keyword[1] = 野球 keyword[2] = 赤松 と、セットしたいのです。 ※文字列中の"□"は全角空白、または半角空白を表しています。 よろしくお願い致します。

  • CString型の文字列連結について

    質問させて頂きます。 開発環境はVC++.netです。 CString型の文字列連結について教えて頂きたく。 CString Test[_MAX_FNAME+1]; という変数にがあるとします。 Test変数のデータは Test[0]には"2" Test[1]には"1" が格納されてるとします。 Test変数のデータをCString Text1という変数に 以下のようなソースで文字列連結処理を行ったのですが、だめでした。 何がいけないのでしょうか? for(int i = 0; i <= 2; i++) { Text1 += Test[i]; } 実行結果は Text1には"2"が格納されたままでした。 実際はText1には、"2""1"となってほしい。 分かりにくい説明とは思いますが、 回答、ヒントなどを頂けますでしょうか 宜しくお願い致します。 それと、もしよかったら、Text1の格納データは "2","1"としたいので、カンマ区切りのやりかたなども ヒントを頂けたら幸いです。 以上です。 宜しくお願い致します。

  • CString データの文字数カウントができない

    VusualStudioのMFCでクリップボードのデータの文字数をカウントしようとしています。 Webにあったように以下のようなクラスを作成し、 =========================================================== CString CClipboard::GetClipboardText() { CString strText; strText.Empty(); // クリップボードにテキストデータが入っているかを調べる if( !::IsClipboardFormatAvailable(CF_UNICODETEXT) ) return strText; // クリップボードのオープン if( !::OpenClipboard(NULL) ) return strText; // クリップボードからデータを取得し、strTextへコピー HANDLE hMem = ::GetClipboardData(CF_UNICODETEXT); LPTSTR pMem = (LPTSTR)::GlobalLock(hMem); ::lstrcpy((LPTSTR)(LPCTSTR)strText, pMem); ::GlobalUnlock(hMem); ::CloseClipboard(); return strText; } =========================================================== 適当にメモ帳などでコピー操作をしたのち、 CClipboard board; CString a = board.GetClipboardText(); int b = a.GetLength(); 上記コードが含まれた操作を実行するとaという文字列自体はデバッガ上から"test"のように 認識されているのですが、bの値が0になってしまいます。 ちょっとわけがわからず途方に暮れています。 アドバイスがあればよろしくお願いします。

  • 文字列の検索

    先日同じ質問をして、プログラムの内容を修正したのですが、今度は2つ文字列を入力した後0が無限にでてきます… どなたか解説・指摘・模範解答などおねがいします。 内容は最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char *c,*d; char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(c!='\0'){ c=a; d=b; while(c!='\0' && d!='\0'){ if(c!=d) printf("0"); break; c++; d++; } } if(d='\0') printf("1"); a++; return a; return NULL; } 例 検索対象文字列:asdfghjkl 検索文字列:sdf 1と出力 検索対象文字列:asdfghjkl 検索文字列:qwer 0と出力

  • find結果で文字列検索?

    RedHatLinux7.2です。 シェルコマンドで複数のテキストファイルからある文字列を含むファイルだけリストアップしたいのですが、文字列検索の対象となるテキストファイルが色々なディレクトリにまたがっている場合はどうやってやればよいでしょうか? 多分findで抽出したファイルパスをgrepに渡せばいいんでしょうけどパイプとか?がまだ不勉強ですぐにわかりません。 初歩的なことだと思いますがよろしくお願いします。

  • VBA/FIND関数を使っての先頭文字列の検索方法

    エクセルVBAにてFIND関数を使って、 文字列検索⇒コピー&ペーストのマクロを作成しているのですが、 どうしても、先頭文字列から検索をする方法がわかりません。 たとえば、 あいうえお いうえおあ おあいうえ えおあいう という文字列から「あいう*」を検索したい場合、 1行目だけを抽出したいのですが、 1,3,4行目が抽出されてしまいます。 find関数では先頭文字からの検索はできないのでしょうか? もし、不可能な場合、先頭文字からの検索を行うにはどのように行えばよいでしょうか? アドバイス、よろしくお願いいたします。

  • ブック全体の文字列検索について

    Excelでセルに任意の文字列をペーストします。そのセルは別のブックにリンクしているのでペーストする度にリンク先のセルでは文字列が更新されます。リンク先のブックにはワークシートが10あっていづれかのシートのA列にその文字列がある事になっています。更新された文字列を検索する作業を繰り返すのでマクロで組み込もうと思ったのですがFIND関数にしても、VBでCell.Find(What:=....と書くにも参照する文字列を直接指定してやらないと動きません。参照する文字列が相対的に変化するので「特定のセルの中に入力された文字列」を参照してブック内を検索したいということなのですが、実現するにはどうしたらようでしょうか?と質問して moji = "B1" Set c = Range("A:A").Find(What:=moji, LookIn:=xlValues, LookAt:=xlWhole) If Not c Is Nothing Then c.Select というコードをしめしていただきました。このままだと検索対象がRangeオブジェクトになっているのでActivesheet上でしか検索がかからないのでCellsにすればブック内のすべてのシートに検索がかけられるかな?と思っていたのですがエラーがでます。ブック内を検索範囲に入れるためにはどうしたらよいでしょうか?