先日の文字列をインプレイスで反転させるコードは、ASCII文字専用でした。
軽量言語では str.reverse() みたいな感じで多バイト文字でも簡単に反転できますが、C/C++ でやるとなると、かなり難しいです(私にとっては)。
まず、文字コードの判定から始まって、1バイト文字と多バイト文字の混在にも配慮しないといけないし、Shift_JISなどは2バイト目に’5C’が来るいわゆるダメ文字もあったりして、非常に厄介です。
まあ、しかし頭の体操には丁度よいのではないかということで、ぼちぼち書いてみたのが以下のコードです。
#include <stdlib.h>
char * revStr( char * str ){
int len = strlen( str );
char *buf;
buf = (char *)malloc(sizeof(str));
int j = 0;
for( int i = len-1; i >= 0; i-- ){
if (str[i]>=(char)0x00 && str[i]<(char)0x7F) {
buf[j] = str[i];
j += 1;
}else if(str[i]>=(char)0xC2 && str[i]<=(char)0xDF){
buf[j] = str[i];
buf[j+1] = str[i+1];
j += 2;
}else if(str[i]>=(char)0xE0 && str[i]<=(char)0xEF){
buf[j]= str[i];
buf[j+1] = str[i+1];
buf[j+2] = str[i+2];
j += 3;
}else if(str[i]>=(char)0xF0 && str[i]<=(char)0xF4){
buf[j]= str[i];
buf[j+1] = str[i+1];
buf[j+2] = str[i+2];
buf[j+3] = str[i+3];
j += 4;
}
}
buf[j] = '';
return buf;
}
int main () {
char *str = revStr("グンミーチャ デー リブラ!");
printf("%s", str);
free(str);
return 0;
}
文字コードはUTF-8に決め打ちです。と言うのも、UTF-8は先頭が0x00…0x7Fだったら1バイト、0xC2…0xDFなら2バイトというふうに確定できるので、扱いやすいのです。そのかわり、仮名・漢字は1文字で3バイト、一部の記号は4バイトだったりします。
インプレイスを維持するのはさすがに無理でした。普通にバッファを確保しています。
—
次に Objective-C というか、Cocoa フレームワークを使ってみました。若干非効率になってしまってますが、バイト数だのに煩わされなくていいのでラクですね。
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSMutableString *str = [NSMutableString stringWithString:@"まにわしらさぎ"];
NSString *tmp;
int len = [str length];
for( int i = 0; i < len/2; i++ ){
tmp = [str substringWithRange:NSMakeRange(i,1)];
[str replaceCharactersInRange:NSMakeRange(i,1) withString:[str substringWithRange:NSMakeRange(len-i-1,1)]];
[str replaceCharactersInRange:NSMakeRange(len-i-1,1) withString:tmp];
}
NSLog(@"%@", str);
[pool drain];
return 0;
}









