2011年09月04日

NSStringとC文字列(2)

さて、前回に続きNSStringからC文字列を取り出す変換について。今回のが書きたかったこと。

簡易な変換方法では文字列の保存領域確保が不要な反面、いずれ勝手に解放されてしまう不便があります。

ですから、メモリ解放が自動ではない方法があればそれにこしたことはない。それがこれ。


- (BOOL)getCString:(char *)buffer maxLength:(NSUInteger)maxBufferCount encoding:(NSStringEncoding)encoding


bufferはあらかじめ呼び出し側で確保したメモリなので誰も勝手に解放しません。そこにC文字列+NULL終端文字を含めて返してくれます。文字列エンコーディングはencodingで指定します。指定する定数は前回示したもの。

ただし、確保したメモリより変換後の文字列が長ければ不正なメモリアクセスなどよろしくないことが起こるかもしれません。そのために確保したメモリのサイズをmaxBufferCountで示します。

ここでポイントはmaxBufferCountは、確保したメモリサイズを与えるということ。つまり文字列長+NULL文字分必要です。メソッド名の引数指定部分がmaxLength:なので文字列長かと間違えやすいので要注意です。間違えない?私は間違えてかなり時間を無駄にしました。

バッファが短すぎたり、指定した文字列のエンコーディングでは変換できない場合、戻り値でNOが戻ります。成功した場合にはYESが戻ります。

ではどれだけのサイズのメモリを確保すればいいのでしょうか?




NSStringの文字列長を示すメソッドは以下があります。

- (NSUInteger)length


ですが、これは内部表現(unicode)での文字列長なので変換後の文字列長ではありません。変換後の文字列長を求めるのはこちら。


- (NSUInteger)lengthOfBytesUsingEncoding:(NSStringEncoding)enc


encには取り出したい文字列のエンコーディングを指定する。ただし、ここで戻る値は「文字列長」であって保存するのに必要なメモリサイズではありません。つまりNULL文字分を含まない値です。

よって実際のコードはこうなります。

NSStringEncoding encoding;
NSUInteger length = [aString lengthOfBytesUsingEncoding:encoding];
char *buffer = malloc(length+1);
if ( buffer == NULL ) return;
if ( ![aString getCString:buffer maxLength:length+1 encoding:encoding] ) {
free(buffer);
return;
}


もちろん、自分で確保したメモリの解放は忘れないようにしてください。


ところで、似たようなメソッドでこんなのがあります。

- (NSUInteger)maximumLengthOfBytesUsingEncoding:(NSStringEncoding)enc


これの違いがわかりません。リファレンスを見てもmaximumという語があるかどうかしか違いが見当たりません。一体なんなんでしょうか?Unicodeなどで文字列を表現する場合に正規化の仕方によってバイト長が変わってくるとかいうのに対応しているのでしょうか?でも変換するときのオプションでどういう分解をするか指定する方法がないと思うので、これを示しても意味がないような気がするので、違うことなんじゃないかな?

誰か分かる人がいたら教えてください。

このテーマはまだ続きます。
タグ:NSString Char
posted by 永遠製作所 at 14:27| 東京 ☀| Comment(0) | TrackBack(0) | Cocoa | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

※ブログオーナーが承認したコメントのみ表示されます。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/224225769
※ブログオーナーが承認したトラックバックのみ表示されます。
※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック