プロが教える店舗&オフィスのセキュリティ対策術

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

教えてください。

A 回答 (7件)

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);

}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。


作動確認出来ました。

お礼日時:2003/02/01 19:57

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」を参考にしました。
動作は未確認です。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。


main関数がなかったので確認出来ませんでした。
すみません。

お礼日時:2003/02/01 20:13

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#sjis
http://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
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。


"strlib.h"がないというエラーが出てしまいました。

対応策を教えていただけたらありがたいです。

環境:VC++6.0 WIN98

お礼日時:2003/02/01 20:06

”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;
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。


作動確認出来ました。

お礼日時:2003/02/01 20:03

多バイト文字を扱う場合、その文字コードが何であるかによって処理方法が変わってきます。



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;
  }
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

なぜかエラーが出て、全然ログオン出来なくて返事が遅れてしましました。


main関数がなかったので確認出来ませんでした。
すみません。

お礼日時:2003/02/01 19:56

”aいbうえお”のように、1バイト文字と2バイト文字が


混在している場合は、「その文字のバイト数」を意識し
ながら行わないといけません。
    • good
    • 0
この回答へのお礼

回答有難う御座います。

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

お礼日時:2003/01/31 12:38

<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に注意。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

本やネットで相当探したのですが、半角英数文字のことは有るのですが、漢字等は難しいとあるのみで、実際はどうするのかやり方が載ってなかったので質問させていただきました。

意外と簡単に、教えていただいた以下コードで実現できましたが、

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);

}

お礼日時:2003/01/31 09:21

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!