文字列反転日本語対応

先日の文字列をインプレイスで反転させるコードは、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;
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

*