C 文字列操作 新しいページはコチラ
提供: yonewiki
(→文字列長取得) |
(→文字列比較) |
||
471行: | 471行: | ||
=='''文字列比較'''== | =='''文字列比較'''== | ||
− | + | 数値の比較は配列でないかぎりは単純な1変数同志の比較ですが、文字列は配列全体が一致しているかを確認することになります。かといって、自分で配列全体を相互に比較するようなプログラムを組むという必要はなく、標準で準備されている関数を使う事で比較できます。VB、PHP、Perlのような関数では関数を使わずに、数値と数値を1変数で比較するかのように比較ができる仕組みになっていますが、C言語では関数を使って比較する必要があります。面倒だ(´Д`;)。<br /> | |
− | + | ||
− | + | ||
− | + | この厳密さも、C言語を難しく感じる一つの要素だと思います。配列をひとつづつ確認する作業なんだという意識づけを忘れないという意味では大事なようにも感じます。だから、ちょっとした変更の伴う比較でも、どうすればよいかを考えることができるのだと思います。VBやPHP、Perlのような便利な比較ばかりをやっているとふと、大文字小文字区別なし変換をしたいとか、半角全角区別なし変換をしたいときに、思考が止まってしまう。 | |
− | + | そういうときにはPHPやPerl、VBでも一生懸命調べて、C言語の考え方にたどり着いて、比較することになるんでしょうけど…さいしょから、文字列比較とは、こういうものだと知っておけば、それでいいのですから、ネガティブに考えず、これを覚えれば、潰しが効くとポジティブにとらえてやっていきましょう。比較は英語でcompairと表現するため、関数名にはcmpが使われます。半導体製造工程のcmpとは違います。Chemical Micro Polisherだっけ?違った。Chemical Mechanical Polishingだった。<br /> | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
例によって比較の関数もマルチバイト文字、ワイド文字、マルチバイト2バイト文字対応といろいろな関数があります。<br /> | 例によって比較の関数もマルチバイト文字、ワイド文字、マルチバイト2バイト文字対応といろいろな関数があります。<br /> | ||
strncmp、wcsncmp、_mbsncmp、_mbsncmp_l<br /> | strncmp、wcsncmp、_mbsncmp、_mbsncmp_l<br /> | ||
506行: | 498行: | ||
<br /> | <br /> | ||
多い!更に多い。<br /> | 多い!更に多い。<br /> | ||
− | + | けどicmpってついてるやつは、大文字小文字を区別しないと考えればいいし、cmpで終わらない、collはコードページという特殊な考え方が使われること、ncpmは比較する文字数指定あり、_lはロケール個別指定、と考えればかなりすっきり。collによる比較はあとで考えましょう。<br /> | |
− | + | ||
− | + | ||
<syntaxhighlight lang="cpp" line start="1"> | <syntaxhighlight lang="cpp" line start="1"> | ||
#include <iostream> | #include <iostream> | ||
696行: | 688行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | と、こんな感じです。結果を見るとわかるのですが、1,-1, | + | と、こんな感じです。結果を見るとわかるのですが、1,-1,0で結果が表現され、先頭から比較して、一番最初に異なる文字同志を比較したときの結果、文字コードの値が大きかったか小さかったかで、1と-1とに結果が分かれます。これを使って昇順に並べたりすることも出来ます。もちろん0が返ってきたときは、完全一致です。等しかったということになります。<br /> |
− | + | ||
− | + | ||
− | + | 少し変わっているのは、関数によっては、文字コードの差分値を返すものもあるという点です。_mbs系では文字コードの差分を返すことは無いようです。cmpの前にiが付く関数は差分を返すようです。ただし_mbsnicmpや_mbsicmpのような関数は差分は返しません。wcs系の関数は差分を返します。このことで差分が数値コードによる部分である場合は、その差は数字の差でもあり、一文字(一桁)の数学的な差を計算するのと同様の処理になったり、アルファベットによる連番と考えた場合でも、その差を計算していることにもなります。2バイト文字では差が大きな数値になりますが、符号付きint型で十分に収まる値です。今回は実験的にlongを使いましたが、無駄足でした。仕様のとおりに動作しますね。<br /> | |
− | + | ||
− | + | ||
− | + | 但し、差分の件については、仕様に明記されていませんので、実際に利用する関数での動作を確かめてから使う方が良いと思います。仕様に明記されているのは0より大きい値を返すか小さい値を返すかのどちらかとなっています。正確なVisual C++に限らない言語仕様を検索してみたのですが、わかりませんでした。coll系の比較関数は現在のコードページに従いますので、locale情報を指定しない状態では、各PCのコードページに従います。コードページというのはcp932のような具体的な文字コードのことです。cpの後に続く数字で文字コードセットは分類されています。特段の理由がなければ、使うことは無いでしょう。selocale関数でも引数を指定しなければ各PCのコードページに従いますから、setlocaleで指定できない理由があるという特殊なケースになりそうです。それか、cmpという関数が嫌いでcollが良いと思うかとかですね。ひょっとしたら差分戻り値の件で動作が異なるかもしれません。あとで確認をしておきたいと思います。とてつもなく長いですが、その確認をしてみた結果が以下のものでして、<br /> | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
<br /> | <br /> | ||
[[文字列操作 文字列比較 実行結果1]]<br /> | [[文字列操作 文字列比較 実行結果1]]<br /> | ||
<br /> | <br /> | ||
− | 528行目から534行目のように同じ'Y'0x79大文字と'y' | + | 528行目から534行目のように同じ'Y'0x79大文字と'y'0x89小文字の比較でありながらも、strcollでは1とstrcmpでは-1とでは結果が異なります。asciiコードでは小文字の方が大きな数字の文字コードが割り振られているため、strcmpのように Y と y の差は0x89 - 0x79で負の数値となり -1 となることを期待しますが、collは現在のコードページかつ辞書式順序を使うために小文字よりも大文字が後ということで1になります。辞書式順序って何だ?と思いつつあるのが131202時点の状況でして、さらに調査をすすめたものが<br /> |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
<br /> | <br /> | ||
[[文字列操作 文字列比較 実行結果2]]<br /> | [[文字列操作 文字列比較 実行結果2]]<br /> | ||
745行: | 722行: | ||
:stricmp/_strnicmp<br /> | :stricmp/_strnicmp<br /> | ||
<br /> | <br /> | ||
− | + | という具合の動作であります。collの特徴的なのは辞書順と呼んでいる比較の概念だと思います。ASCIIコードでは大文字と小文字とでは、小文字の方が大きい文字コード番号が付与されていますが、wcs**coll系の比較をする関数では、小文字の方が値が小さいものとして判定してくれます。漢字の範囲になるとロケールで指定したcp932の文字コード順で比較してくれます。阿という文字と哀という文字はUnicode(UTF16)では阿-0x963F 哀-0x54C0 表-0x8868であり、Shift_JISのcp932では阿-0x88A2 哀-0x88A3 表-0x955Cと定義されていますから、阿<nowiki><</nowiki>哀<nowiki><</nowiki>表 のように比較をしてくれます。coll系の関数を使わない場合は 哀<nowiki><</nowiki>表<nowiki><</nowiki>阿のように比較されます。この阿や哀や表という名前のファイル名のテキストをWindowsのエクスプローラで昇順表示すると、この順番になることも確認できます。Shift_JISコード順でソートされてるんだなぁと確認が出来ると思います。Cp932の半角記号あたりの辞書順ってのは、どうなってるんでしょうね。これもまた今度しらべてみたいと思います。ファイル名に使えない文字あたりはどんな順番なんだろうか? | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
'''★豆知識''' | '''★豆知識''' |