• 締切済み

全角文字列のソートについて・・・全角のIと半角の2ではどちらが先ですか?

よろしくお願い致します。C++Builder3を使って開発をしています。 ファイル名の比較を行うプログラムをしていましたら、?と思うことに遭遇してしまいました・・・。 例えば、ファイル名"I_(フツウ)1-2.CSV"と"2pin-futsuu.CSV"の比較を行いました。 そうしたらコンポーネントTListBoxのsortedプロパティをtrueにして 並べた時は(1)"I_(フツウ)1-2.CSV"、(2)"2pin-futsuu.CSV"と 全角Iファイルの方が先に来ました。 しかし、stricmpを使用して二つのファイルを比較すると、"2pin-futsuu.CSV"ファイルの方が小さいと判断されました。 また、AnsiStrICompを使用して比較すると"I_(フツウ)1-2.CSV" ファイルの方が小さいと判断されます。 これは全角&半角の比較だということなのでしょうか? しかし、1,2の間にIが来るのは変なような気がしますが、 そういったものなのでしょうか? エクスプローラで見てもやはり"I_(フツウ)1-2.CSV"の方が先にきます。 やはりそちらの表示の方が正しいのでしょうね・・・。 そうであれば、stricmpを使用する事は避けた方が良いのでしょうか? 初心者の質問で申し訳ありません。 二つのファイルの比較結果が正しくできる方法のアドバイスを いただければ嬉しく思います。お願いします。

みんなの回答

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.3

StrCmpLogicalWだとどうでしょうか?

sanquu
質問者

お礼

ありがとうございます。 お返事が遅くなってすみませんでした。 StrCmpLogicalWはAPIのようですが、C++Builderで使用する時に 必要なインクルードファイルとかはありますか? そのまま使ってみようとしたら、エラーになってしまいまして・・・。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

一般的というのが一番困るんですが、たとえばエクスプローラーで ファイル名順に並べたときだと ・ラテンアルファベット(A~Zとか)の大小文字の違いは無視する ・全半角の違いも無視する ・ファイル名の途中(末尾?)に数字列があったら特別扱いする。 とかいうルールだったと思います。 この通りに並べ替える比較関数はたぶんAPIとしては用意されていなかったような。 んで、適当な例ですけど #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <stdio.h> #include <locale.h> int cmp1(const void* lhs, const void* rhs) { int cchCount1; int cchCount2; int result, ret; LPCTSTR lpString1 = *((LPCSTR *)lhs); LPCTSTR lpString2 = *((LPCSTR *)rhs); DWORD dwCmpFlags = 0 //| NORM_IGNORECASE //| NORM_IGNOREKANATYPE //| NORM_IGNORENONSPACE //| NORM_IGNORESYMBOLS //| NORM_IGNOREWIDTH //| SORT_STRINGSORT ; cchCount1 = strlen(lpString1); cchCount2 = strlen(lpString2); result = CompareString(LOCALE_USER_DEFAULT, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2); if (result == CSTR_LESS_THAN) ret = -1; else if (result == CSTR_EQUAL) ret = 0; else if (result == CSTR_GREATER_THAN) ret = 1; else abort(); return ret; } int cmp2(const void* lhs, const void* rhs) { const char* s1 = *((const char**)lhs); const char* s2 = *((const char**)rhs); return strcmp(s1, s2); } int cmp3(const void* lhs, const void* rhs) { const char* s1 = *((const char**)lhs); const char* s2 = *((const char**)rhs); return lstrcmp(s1, s2); } void sort_and_print(int num, const char* strings[]) { int i, j; int (*fp)(const void*, const void*); int (*funcs[])(const void*, const void*) = { cmp1, cmp2, cmp3, NULL, }; for (i=0; i<num; i++) { printf("%3d: %s\n", i, strings[i]); } puts("#####"); for (i=0, fp=funcs[0]; fp; i++, fp = funcs[i]) { qsort(strings, num, sizeof (char *), fp); for (j=0; j<num; j++) { printf("%3d: %s\n", j, strings[j]); } puts("-----"); } } int main() { const char* sample_strings[] = { "I_(フツウ)1-2.CSV", "i_(フツウ)1-2.CSV", "j_(フツウ)1-2.CSV", "J_(フツウ)1-2.CSV", "file1.csv", "file2.csv", "file100.csv", "2pin-futsuu.CSV", "1pin-futsuu.CSV", }; const int num = sizeof sample_strings/ sizeof sample_strings[0]; setlocale(LC_ALL, ""); sort_and_print(num, sample_strings); return 0; } 結果: 0: I_(フツウ)1-2.CSV 1: i_(フツウ)1-2.CSV 2: j_(フツウ)1-2.CSV 3: J_(フツウ)1-2.CSV 4: file1.csv 5: file2.csv 6: file100.csv 7: 2pin-futsuu.CSV 8: 1pin-futsuu.CSV ##### 0: 1pin-futsuu.CSV 1: 2pin-futsuu.CSV 2: file1.csv 3: file100.csv 4: file2.csv 5: i_(フツウ)1-2.CSV 6: I_(フツウ)1-2.CSV 7: j_(フツウ)1-2.CSV 8: J_(フツウ)1-2.CSV ----- 0: 1pin-futsuu.CSV 1: 2pin-futsuu.CSV 2: I_(フツウ)1-2.CSV 3: J_(フツウ)1-2.CSV 4: file1.csv 5: file100.csv 6: file2.csv 7: i_(フツウ)1-2.CSV 8: j_(フツウ)1-2.CSV ----- 0: 1pin-futsuu.CSV 1: 2pin-futsuu.CSV 2: file1.csv 3: file100.csv 4: file2.csv 5: i_(フツウ)1-2.CSV 6: I_(フツウ)1-2.CSV 7: j_(フツウ)1-2.CSV 8: J_(フツウ)1-2.CSV ----- こういうので調べてみると、 CompareString, lstrcmp, strcmp で結果が違うのが分かると思います。 つまり何が正しいということではなくて、どのような基準で並べるかというのがあるだけなのです。 > 全角が入っているファイル名の比較にstricmpを使うのはやめた方が良いのでしょう? これはそうです。 ShiftJISを使っている場合、二バイト目に英小文字が隠れている場合がありますから ShiftJISであることを考慮しない stricmpを使うと、全角文字列で 予想外の結果になる可能性があります。 >AnsiStrICompを使用して比較すると"I_(フツウ)1-2.CSV"ファイルの方が小さいと判断されます。 これはよくわかりません。 SysUtils.AnsiStrIComp 関数 http://docs.codegear.com/docs/radstudio/radstudio2007/RS2007_helpupdates/HUpdate4/JA/html/delphivclwin32/SysUtils_AnsiStrIComp.html を見る限りではそのような結果になる理由がわかりません。

sanquu
質問者

お礼

お礼が遅くなってすみませんでした。 それに、例まで書いていただいてありがとうございました。 確かに『一般的』という言い方はあやふや過ぎてすみませんでした。 使っている人が見ておかしくない並び順というのを考えてました・・・ (って余計に混乱する日本語になっていたらごめんなさい・・・) TListBoxを使用してソートした時と、stricmpを使ってソートした時とで 結果が変わってしまうのが一番困っていたことでしたので、 やはりstricmpを使用するのは避けるようにします(ファイル名には全角文字が入ることは必須なので)。 私は結果として1番目と3番目のように並べ変えられると良い と思いますので、あとは全ての処理で並べ替えが統一されるように 修正していきたいと思います。 ご意見ありがとうございました。 参考にさせていただきます。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

>二つのファイルの比較結果が正しくできる方法のアドバイスを どのように並ぶのが「正しい」ものですか? それと >しかし、1,2の間にIが来るのは変なような気がしますが、 これはどの状態を指していっているのでしょうか?

sanquu
質問者

補足

早速のお返事ありがとうございます。 >二つのファイルの比較結果が正しくできる方法のアドバイスを どのように並ぶのが「正しい」ものですか? ⇒反対に、一般的にどのように並ぶのが正しいのかが知りたいのですが・・・。 ファイル名をソートすると「1***」、「I***」、「2***」と並ぶのがWindowsで一般の並び方なら、stricmpを使うと「1***」、「2***」、「I***」と並んでしまうので、使えないのかな?と思いました。 全角が入っているファイル名の比較にstricmpを使うのはやめた方が良いのでしょう?

関連するQ&A

  • Web上における全角/半角について

    Web上における全角/半角について http://bekkoame.okwave.jp/qa6240322.html の回答7氏のお礼欄にて質問者が >コンピュータの世界で半角を使用するのは、ファイル名や、コーディングのときです。一般文章では、なるべくなら、全角を使うべきです。これは、コンピュータでなく、文章をを綺麗に見せるためのマナーですね。 と述べています。 私個人の経験ではWebに限らずコンピュータで作成する文書は、ひらがな・カタカナ・漢字は全角、英数字・記号は半角(もちろん一部例外はあり)にしたほうが読みやすいと思うのですが、一般的には上記質問者の言い分は正しいのでしょうか?

  • 全角文字列を挿入するには

    エクセルVBAで以下のことを効率よくやるにはどうしたらよいでしょうか? 等幅フォントの文字列に全角文字列を挿入(置換え)します。 具体的に言うとホストコンピュータのリスト(等幅フォント半角文字132桁、A列のみ使用)に全角文字コメントを自動挿入します。 ホストリストは2つのファイルを比較するリストで16進数表記になっています。1行目が比較内容、2行目がファイル1の内容、3行目がファイル2の内容、4行目が空白行なっており、4行目にコメントを挿入します。                      * IN1 F1000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F1000000CF1F1F2020070430CF0F0F0F0F5000000                COL8,5発生日 コメント挿入は同じ行に複数回入れることがあります。 入れようとする位置に既にコメントがある場合、空白行を追加してから 挿入します。 最初にコメントを入れる場合、特に問題は発生しませんが、2回目に入れる場合、コメントがあるかどうか該当位置を特定しなければなりませんが、全角文字が発生していると単純に位置を決定できません。 該当位置の決め方、そして挿入した場合、後続をズレないようにする必要があります。何故なら後続にコメントが既に入っているケースもあるからです。 一応自分なりにVBAは作っています。 (1)配列を作って1文字づつ配列のマスに入れる。 (2)全角文字の場合配列の2マスに(同じ内容を)入れる。 (3)追加文字列は該当の配列内容を見て、空白の場合、置き換える。  その時も同じように全角文字は2マス分使用する。 (4)以上がおわったら配列から取り出す。  取り出す際、全角文字の場合、次のマスを読み飛ばす。 ホストリストは数万行になる場合があり、配列を使わないでもっと効率よくやるにはどうしたらよいでしょうか。 もう少し考えれば出来るような気がしますが、これだけ考えるだけで疲れてしまいました。 よろしくお願い申し上げます。

  • 全角英数字を半角に変換

    WindowsXPでファイルやフォルダが数千あり保存名がバラバラなので 統一しようと試みています。力を貸してください。 作業1.全角英数字を半角に変換 作業2.半角カタカナを全角カタカナに変換 現在) フォルダ名:実験資料01_012 ファイル名:実験結果プリント01.xls 改正) フォルダ名:実験資料01_012 ファイル名:実験結果プリント01.xls 例の様に一括変換ソフトやスクリプトをご存知の方いませんか。 参考にしたURL:http://okwave.jp/qa281720.html ここでは、フォルダ名は確かに変わりましたが、全角と半角が混ぜると 半角が削除されてしまいました。

  • 全角スペースを文字として検索するには?

    Finderからファイル名(あるいはフォルダ名)に全角スペースを使用しているファイルを検索することは可能でしょうか? 半角スペースと同じ扱いがされているようで、 文字として扱ってくれないようなのですが、 検索する手段をご存知の方がおられましたら どうかご教示よろしくお願いいたします。

    • 締切済み
    • Mac
  • ASP.Net 全角文字コード

    大変お世話になっております。 現在、ObjectDataSource のデータをCSVファイルにしたいと思い、まずは固定データをテストとしまして下記のプログラムを書きました。(ほとんど受け売りです^^;)   Protected Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click     Dim csvStr As String     csvStr = "1,AAA,これはテスト" + vbCrLf _      + "2,BBB,これもテスト"     Response.ContentType = "application/octet-stream"     'Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode("CSVファイル.csv"))     Response.AddHeader("Content-Disposition", "attachment; filename=" + Server.UrlEncode("CSVファイル.csv"))     Response.Write(csvStr)     Response.End()   End Sub HttpUtility.UrlEncode と Server.UrlEncode 両方でファイルを出力しました。 メモ帳で開くと何も問題なく開けるのですが、Excelで直接開くと、3項目目の全角文字がバケてしまいます。Excelの外部データの取り込みで、Csvファイルを選択していく方法だと問題ないのですが、これだと面倒なので、 CSVファイルをダブルクリック → Excelで開く → ふつうにデータを表示させたい 上記を行うためには、どのような文字コードで出力させればよいでしょうか? 上記プログラムでご指摘の箇所やご教授をいただけますと大変うれしい限りでございます。 何卒よろしくお願い申し上げます。

  • 全角文字のファイル名の使用方法はありますか?

    ホームページを作っています。 自分のパソコンでは上手く作動して画像が表示されますが、 プロバイダーにアップロードして試してみましたが、 画像が表示されません。 クリックして新たな画像を表示するところなどは、ファイルが見つかりませんのエラーが表示されます。 画像は漢字名のjpgです。「東京タワー.jpg」のような全角文字のファイル名は使用できないのでしょうか? 使用できないのであれば、何か方法はありますか? 勿論、文章の全角文字の漢字は正しく表示できます。

  • ファイル名を半角大文字にする方法?

    すみません。実はすごく基本的なので、ちょっと恥ずかしいのですが、 質問があります。 新しく作ったファイル名をつける際なのですが、 半角でつけた場合に、大文字(例:CANDLE.txt)と入力した場合ですが、 半角小文字(例:Candle.txt)となる事があります。 無論、全角ならば入力した、そのまんまファイル名になるのですが、 半角の場合だけ全角で入力しても、半角になる事があります。 たまに、ちゃんと半角大文字で入力した通りにファイル名が出来る事があるので、 いったいこれはどういう法則でなるのかが不思議に思いました。 ちなみに、OSはNT、9×、2000他を使用しています。 宜しくお願いいたします。

  • ブラウザー。全角入力から半角にしても戻ってしまう

    こんにちは。 現在、win10を使用しています。(アニバーサリーでは無いですが…) そこでブラウザー起動時は、日本語入力モードにしたいと思い、調べた末に以下の記述をしたファイルを指定することにより、確かに最初から全角になりました・・・。 しかし、問題が出ました。 input,textarea{ime-mode:active} ◆問題 途中で半角入力したい場合も当然あり、半角にすると直ぐに勝手に全角入力に戻ってしまうのです。 これを改修する方法は、無いのでしょうか? ◆やりたいことは、シンプルです。 ・ブラウザー起動時に(前回と関係なく)最初から全角入力モードになって欲しい。 ・途中で半角入力モードに切り替えたら、ユーザーが切り替えるまでそのままのモードでいて欲しい。  (入力途中で勝手に全角入力モードに戻らないで欲しい) たったこれだけなんですが、何故出来ないのでしょうか? 誰も不便に思われていないのでしょうか? どなたか解決された方が居られましたアドバイスをお願い申し上げます。

  • カウントイフ関数についてですが、半角や全角空白にお

    カウントイフ関数についてですが、半角や全角空白においても、区別してくれる関数なのでしょうか。それともしないものなのでしょうか。 とある2列を比較するため、イフ関数・カウントイフ関数➕トリム関数を使用したのですが、トリム関数には、真ん中の空白が残っています。それゆえ、その真ん中の箇所に半角全角が混在しており、カウントイフ関数では、それを別物と考えるとしたら、ジス関数などで加工する必要があると考えたので、この質問をさせていただきました。 どなたか ご存知の方がいたら、ご教示いただけないでしょうか。

  • 列のセル文字を最初から全角に指定する方法

    下記の質問事項の解決方法をご存知の方、ご指導をよろしくお願い致します。 使用機種等は、Windows 8 Excel 2013 です。 表の中の住所・番地・マンション名を全角・半角に統一する関数(ASC・JIS)がありますが、 最初からその列を全角又は半角に指定しておき、その列の入力時にうっかりして半角で入力しても自動的に全角になって表示される方法は無いのでしょうか。 ご存知の方、ご指導の程よろしくお願い致します。

専門家に質問してみよう