• ベストアンサー

”あいうえお” を ”おえういあ”にするには?

C言語にて、”あいうえお” を ”おえういあ”に変換するには、どのようにすればよいのでしょうか? 教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • kawa100
  • ベストアンサー率83% (5/6)
回答No.4

2バイトの判定の範囲がleaz024さんのと違っています。 僕も心配だから、スレが閉じられる前にどちらが正しいか知りたいです。 leaz024さんは、"aいbうえお"で、{1,2,1,2,2,2}という配列を用意しますが 僕は、2バイトを調べたらそのまま処理をするアルゴリズムにしています。 2バイトの判定は"aいbうえお"の先頭から。 最初は1バイトだから、outは?????????aになり、 次のループで、outは???????いaになり、 次のループで、outは???????いaになり、 次のループで、outは??????bいaになり、 次のループで、outは????うbいaになり、 次のループで、outはおえうbいaになり、 最後に0x0を付けています。 #include<stdio.h> void main(){  char strin[] = "aいbうえお";  char out[11];  for(int i=0; i<11; i++){   if((unsigned char)strin[i] > 0x80 && (unsigned char)strin[i] < 0xA0 || (unsigned char)strin[i] > 0xDF && (unsigned char)strin[i] < 0xF0){    out[9-i-1] = strin[i];    out[9-i] = strin[i+1];    i++;   }else{ out[9-i] = strin[i];   }  }  out[10] = 0;  printf("%s\n",out); }

mk1234
質問者

お礼

回答ありがとうございます。 なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。 作動確認出来ました。

その他の回答 (6)

  • jmh
  • ベストアンサー率23% (71/304)
回答No.7

int mbcsize(unsigned char *s) {   if ((0xa0 <= *s && *s <= 0xff) || *s == 0x8e)     return 2;   else if (*s == 0x8f)     return 3;   else     return 1; } void strnrev(unsigned char *s, int n) {   int i, j;   for (i = 0, j = n - 1; i < j; ++i, --j) {     unsigned char c = s[i];     s[i] = s[j];     s[j] = c;   } } void strrev(unsigned char *s) {   unsigned char *t = s;   while (*t != '\0') {     int i = mbcsize(t);     strnrev(t, i);     t += i;   }   strnrev(s, t - s); } 文字コード(EUC)は、No.6 の leaz024 様の「参考URL」を参考にしました。 動作は未確認です。

mk1234
質問者

お礼

回答ありがとうございます。 なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。 main関数がなかったので確認出来ませんでした。 すみません。

  • leaz024
  • ベストアンサー率75% (398/526)
回答No.6

No.4 kawa100さんの回答より > leaz024さんは、"aいbうえお"で、{1,2,1,2,2,2}という配列を用意しますが > 僕は、2バイトを調べたらそのまま処理をするアルゴリズムにしています。 そうですね。バイト数の配列なんて要りませんでしたね^^; というわけで、「調べたらそのまま処理する版」です。   char *strrev(char *s)   {     long len;     int bytes, i;     char *buf, *p;     unsigned char uc;     len = strlen(s);     /* バッファに文字列をコピー */     buf = (char *)malloc(len + 1);     strcpy(buf, s);     /* 文字列を逆順にコピー */     for (p = buf; len > 0; ) {       uc = *(unsigned char *)p;       if (0x81<=uc && uc<=0x9F || 0xE0<=uc && uc<=0xFC) bytes = 2;       else bytes = 1;       len -= bytes;       for (i = 0; i < bytes; i++)         s[len + i] = *p++;     }     free(buf);     return s;   } さっき書き忘れましたが、上記コードのコンパイルには strlib.h と string.h が必要です。 ちなみに main 関数は次のような感じになります。   int main() {     char strin[] = "aいbうえお";     char out[11];     strcpy(out, strin);        /* コピーして */     printf("%s\n", strrev(out));   /* ひっくり返す */     return 0;   } また、同じく No.4 kawa100さんの回答より > 2バイトの判定の範囲がleaz024さんのと違っています。 > 僕も心配だから、スレが閉じられる前にどちらが正しいか知りたいです。 とのことですが、これは間違いなく 0x81~0x9F 及び 0xE0~0xFC です。 (↑これ専門分野なんで^^) ついでに2バイト目の範囲は 0x40~0x7E 及び 0x80~0xFC です。 参考URLも2つほど挙げておきますね。 ・http://www.kanzaki.com/docs/jcode.html#sjishttp://www.opengroup.or.jp/jvc/cde/sjis.html

参考URL:
http://www.kanzaki.com/docs/jcode.html#sjis,http://www.opengroup.or.jp/jvc/cde/sjis.html
mk1234
質問者

お礼

回答ありがとうございます。 なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。 "strlib.h"がないというエラーが出てしまいました。 対応策を教えていただけたらありがたいです。 環境:VC++6.0 WIN98

回答No.5

”aいbうえお”の場合、一旦 UNICODE に変換というのもアリかと。 // sample, C++ #include <iostream> #include <locale> #include <algorithm> #include <cstdlib> // mbstowcs/wcstombs int main() { std::locale::global(std::locale("ja")); char input[] = "aいbうえお"; wchar_t wbuf[32]; size_t len = mbstowcs(wbuf, input, 32); // to UNICODE std::reverse(wbuf, wbuf+len); // 反転 char output[32]; wcstombs(output, wbuf, 32); // from UNICODE std::cout << output << std::endl; return 0; }

mk1234
質問者

お礼

回答ありがとうございます。 なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。 作動確認出来ました。

  • leaz024
  • ベストアンサー率75% (398/526)
回答No.3

多バイト文字を扱う場合、その文字コードが何であるかによって処理方法が変わってきます。 Windowsで標準の文字コード「シフトJIS」では、全角文字の1バイト目が 0x81~0x9F 及び 0xE0~0xFC となっているので、文字列の頭から1バイトずつチェックして文字の並びを保存し、それにしたがって逆順にコピーします。 ※2バイト目には、1バイト目やASCIIと重複するコードが含まれるので、後ろからチェックすることはできません。 ※半角カナ(1バイト)は 0xA1~0xDF となっているので、上記のチェックだけで半角カナにも対応できます。 プログラムはこんな感じ。(動作確認済み)   char *strrev(char *s)   {     long len;     int *bytes, index, i;     char *buf, *p;     unsigned char uc;     len = strlen(s);     /* 文字の並びを検査(Shift_JIS) */     bytes = (int *)malloc(len * sizeof(int));     for (p = s, index = 0; *p != '\0'; index++) {       uc = *(unsigned char *)p;       if (0x81<=uc && uc<=0x9F || 0xE0<=uc && uc<=0xFC) bytes[index] = 2;       else bytes[index] = 1;       p += bytes[index];     }     /* バッファに文字列をコピー */     buf = (char *)malloc(len + 1);     strcpy(buf, s);     /* bytes[ ] にしたがって、文字列を逆順コピー */     for (p = s; --index >= 0; ) {       len -= bytes[index];       for (i = 0; i < bytes[index]; i++)         *p++ = buf[len + i];     }     free(bytes);     free(buf);     return s;   }

mk1234
質問者

お礼

回答ありがとうございます。 なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。 main関数がなかったので確認出来ませんでした。 すみません。

  • asaichi
  • ベストアンサー率21% (37/171)
回答No.2

”aいbうえお”のように、1バイト文字と2バイト文字が 混在している場合は、「その文字のバイト数」を意識し ながら行わないといけません。

mk1234
質問者

お礼

回答有難う御座います。 ”aいbうえお”のように既知の場合は、1バイト文字と2バイト文字を意識しすればよいのですが、既知でないときは、プログラム上でどのようにして1or2バイト文字を判断するのでしょうか?

  • kawa100
  • ベストアンサー率83% (5/6)
回答No.1

<script language="JavaScript"> strin = "AaBbCcDdEe".split(""); strout = new Array(); for(i=0; i<10; i+=2){  strout[i] = strin[8-i];  strout[i+1] = strin[9-i]; } strkakunin = "" for(i=0; i<10; i++){  strkakunin += strout[i]; } alert(strkakunin); </script> C言語では最後の0x0に注意。

mk1234
質問者

お礼

回答ありがとうございます。 本やネットで相当探したのですが、半角英数文字のことは有るのですが、漢字等は難しいとあるのみで、実際はどうするのかやり方が載ってなかったので質問させていただきました。 意外と簡単に、教えていただいた以下コードで実現できましたが、 char strin[] = "aいbうえお"; の場合は、どうすればよいのでしょうか? 追加質問で申し訳ありませんが、宜しくお願い致します。 #include<stdio.h> void main(){ char strin[] = "aいbうえお"; char out[11]; int i; for(i=0; i<10; i+=2){ out[i] = strin[8-i]; out[i+1] = strin[9-i]; out[10]='\0'; } printf("%s\n",out); }

関連するQ&A

専門家に質問してみよう