a.cpp
# include <stdio.h>
# include <stdlib.h>
# include <iconv.h>
# include <errno.h>
# include <string.h>
# include <sys/types.h>
# include <string>
std::string encode( const u_char *input_string, size_t input_length, std::string input_code, std::string output_code ) {
if( input_string == NULL ) {
fprintf( stderr, "input string is empty.\n" );
return( "" );
}
if( input_length == 0 ) {
fprintf( stderr, "input length is zero.\n" );
return( "" );
}
if( input_code.empty() ) {
// iconvに文字列判定機能は無い。
// 入力した文字列の文字コードを与える必要がある。
fprintf( stderr, "input code is empty.\n" );
return( "" );
}
if( output_code.empty() ) {
// 変換したい文字コードが無い場合は、
// ひとまず、自分の環境の文字コードに変換されるようにしておく。
output_code = "UTF-8";
}
iconv_t ic;
size_t str_in_length = input_length;
size_t str_out_length = input_length * 3; // 変換後のバイト数がどうなるか分からない。1バイトが3バイトになることを考慮しておく。
char str_in[str_in_length+1];
char str_out[str_out_length+1];
memset( str_in, 0, sizeof( str_in ) );
memset( str_out, 0, sizeof( str_out ) );
// const u_char -> char
for( size_t i = 0; i < input_length; ++i ) {
str_in[i] = (char)input_string[i];
}
// iconvに渡すのは、charの配列の先頭を指すポインタ、のポインタ。
char *ptr_in = str_in;
char *ptr_out = str_out;
errno = 0;
ic = iconv_open( output_code.c_str(), input_code.c_str() );
if( errno ) {
fprintf( stderr, "iconv_open failed. %s\n", strerror( errno ) );
return( "" );
}
// それぞれポインタを渡す。
iconv( ic, &ptr_in, &str_in_length, &ptr_out, &str_out_length );
if( errno ) {
fprintf( stderr, "iconv failed. %s\n", strerror( errno ) );
iconv_close( ic );
return( "" );
} else {
iconv_close( ic );
return( str_out );
}
}
int main( int argc, char **argv ) {
// input_stringで期待する文字列は、16進数文字列。大文字でも小文字でもかまわない。
if( argc != 4 ) {
printf( "./a.out input_code output_code input_string\n\n" );
printf( "example:\n" );
printf( "\t./a.out SHIFT-JIS UTF-8 4e69636520626f61742e\n\n" );
return( 1 );
}
// 16進文字列を、数値に戻し、charの配列にする。
size_t input_length = strlen( argv[3] );
size_t input_length_half = input_length / 2;
if( input_length_half == 0 ) {
// 1文字も無い?
fprintf( stderr, "input_string empty.\n" );
return( 1 );
}
u_char input_string[input_length_half];
u_char *input_string_p = input_string;
for( size_t i = 0, ii = 0; i < input_length_half; ++i, ii += 2 ) {
char tmp[2];
strncpy( tmp, argv[3] + ii, 2 );
tmp[2] = '\0';
long num = strtol( tmp, NULL, 16 );
*input_string_p++ = (u_char)num;
}
std::string ret = encode( input_string, input_length_half, argv[1], argv[2] );
printf( "%s\n", ret.c_str() );
return( 0 );
}
ノリで書いてみました。
細かいエラーチェックはしてないです。
実行すると以下のような感じに。
[todanano@localhost samba]$ g++ ./a.cpp
[todanano@localhost samba]$
[todanano@localhost samba]$
[todanano@localhost samba]$ ./a.out SHIFT-JIS UTF-8 82a0829f5e8160905382aa82d282e582f182d282e582f182b782e982f182b682e1829f5e8160
あぁ^~心がぴょんぴょんするんじゃぁ^~
[todanano@localhost samba]$
[todanano@localhost samba]$
[todanano@localhost samba]$ ./a.out UTF-8 UTF-8 e38182e381815eefbd9ee5bf83e3818ce381b4e38287e38293e381b4e38287e38293e38199e3828be38293e38198e38283e381815eefbd9e
あぁ^~心がぴょんぴょんするんじゃぁ^~
[todanano@localhost samba]$
[todanano@localhost samba]$
[todanano@localhost samba]$ ./a.out EUC-JP UTF-8 a4a2a4a15ea1c1bfb4a4aca4d4a4e7a4f3a4d4a4e7a4f3a4b9a4eba4f3a4b8a4e3a4a15ea1c1
あぁ^~心がぴょんぴょんするんじゃぁ^~
[todanano@localhost samba]$
文字列を16進数文字列にするには、以下のサイト様とかで。