• 締切済み

文字の並び替え

今、全角文字と半角文字が混在した文字列の並び替えをしています。 また、皆様のお力をおかしください。 例:CBABD → ABBCD 色々調べて以下の関数を使うことはわかったのですが、これをどう使えば、並び替えることが出来るのかがわかりません。教えてください。 例があれば、とてもうれしいのですが・・・ int ZenkakuHantei(unsigned char c) { return (((c >= 0x81) && (c <= 0x9f)) || ((c >= 0xe0) && (c <= 0xfc))); }

みんなの回答

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.1

えーと,まず問題が不明確です. > 今、全角文字と半角文字が混在した文字列の並び替えをしています。 > 例:CBABD → ABBCD (1) 文字コードは何ですか?   シフトJIS? EUC-JP? ISO2022-JP? UTF-8/16/32? …   まあ,ZenkakuHantei() の中身から判断すると   シフトJISのはずですが,その点は合ってますか?   (もしシフトJISじゃなかったら,ZenkakuHantei()    を持ってきたことは大ハズレですよ.) (2) 例には全半角の英大文字しか書かれていませんが,   それ以外の文字はどういう順番に並べますか? 文字コードの昇順?   また,半角は全角より先に並べるということでいいですか? > 色々調べて以下の関数を使うことはわかったのですが、 > これをどう使えば、並び替えることが出来るのかがわかりません。 > 教えてください。 うーん,ハードルがいくつもありますねぇ…. 一応,シフトJISを前提とします.シフトJISの文字は1~2バイトの 可変長なので,これをそのまま並べ替えるのは結構面倒です. 一つの方法は,各文字を同じ長さ (2バイト(以上)) の整数値に変換し, その配列をソートすることです. (1) シフトJIS文字列から1文字 (1~2バイト可変長) ずつ取り出す. (2) 各文字を固定長整数に変換し,配列に格納する.   ただしこの変換は,整数値の大小が文字のソート順に一致するよう   に考える必要がある. (3) その配列をソートする. (4) 各整数値を文字に戻す.((2) の逆変換) 今の hatenan114 さんには (1)~(4) のそれぞれが難問だと思いますので, まずは (1),(2)と(4),(3) を別々に解いてみてください. 例えば (1) については,"CBABD" という文字列から1文字ずつ読み取り, 次のように出力できますか? 'C' = 0x82 0x62 'B' = 0x82 0x61 'A' = 0x41 'B' = 0x42 'D' = 0x82 0x63 あ,それからついでに一言. ZenkakuHantei() をどこから持ってきたのか知りませんが, 関数名の付け方がアレですね…. その情報源は,文字コードの理解度に疑問符が付くので, あまりアテにしないほうがよさそう…. ZenkakuHantei(c) の処理内容自体は正しいのですが, 関数名の付け方が間違いとまでは言えないものの, 本質から外れていて誤解を招くおそれがあります. この関数の本当の意味は,cがシフトJISの2バイト文字 (事実上全角文字には違いない) の第1バイトか否かを判定することです. (cは1「文字」ではなく2バイト文字の1バイトにすぎない.) Windows であれば,ZenkakuHantei() に相当する関数として _ismbblead() や isleadbyte() などが標準で使えるので, これらの名前で検索すれば使い方が見つかるでしょう.

関連するQ&A

  • 全角文字を含んだ文字の並びを逆順にするには?

    こんにちは。 C言語において、以下のような2つの関数を利用して、全角文字を含んだ文字列の並びを逆順にする事を考えました。 ちなみにコンパイラは、borlandのC++コンパイラを使っています。 文字コードがShift_JISの場合、全角文字の上位バイトが0x81~0x9F、0xE0~0xFCの範囲に収まるという事を聞いたので、まず、以下のように、渡された文字が、全角文字の上位バイトかどうかを判定する関数を作りました。 ____________________________________________________________ int is_2byte(unsigned char c){ return ( ( (c >= 0x81) && (c <= 0x9f) ) || ( (c >= 0xe0) && (c <= 0xfc) ) ); } ____________________________________________________________ 次に、上の関数を利用し、以下のように、渡された文字列の、文字の並びを逆順にする関数を作りました。 ____________________________________________________________ void rev_str(char *str) { char temp[1000]; char tmp; int i, j; for(i=strlen(str)-1, j=0; i>=0; i--, j++){ temp[j]=str[i]; if(is_2byte(temp[j])){ tmp=temp[j-1]; temp[j-1]=temp[j]; temp[j]=tmp; } } temp[j]='\0'; strcpy(str, temp); } __________________________________________________ この関数を、あいうえお順に試して行った所、ひらがなの 「あいうえお かきくけこ さしすせそ たちつてと なにぬねの はひふへほ まみむめ」 という文字列は、逆順にする事ができたのできました。 しかし、「も」以降の文字を含ませた途端、実行時エラーが発生し、プログラムがストップしてしまいます。 また、カタカナの場合は、「メ」以降の文字を含ませた場合に、実行時エラーとなります。 何が問題なのかが全然分からないので、困っています。 何かいい方法を知っておられる方がいらっしゃれば、是非アドバイスを頂きたいと思います。 では、よろしくお願い致します。

  • 半角数字が入ったデータで、半角数字を全角数字に変化関したいのですが

    半角数字が入ったデータで、半角数字を全角数字に変化関したいのですが うまくいきません。 文字コードはUTF-8です。 下記のような、関数を使ってまず半角の1を全角の1に変換しようとしました。 int substitute(unsigned char *s, int n){ int num; num= atoi(s); switch(num) { case '1': s[n] = 0xEF; s[n+1] = 0xBC; s[n+2] = 0x91; s[n+3] = 0x0d; break; defult: break; } return 0; } この関数をかましても半角は全角になりませんでした。 誰か、ご教授願えませんか?

  • 文字列をint型にキャスト

    文字列をunsigned int型キャストし,それをある演算をして 正の整数に変換したいのですがどうすればいいですか? int ca(char *s) { unsigned int h; int key; h = (unsigned int)s; //文字列を演算し 0~254 の整数にする// key = h % 254; return key; } int main() { char moji[32]; moji = "moji"; unsigned int c; c = ca(moji); }

  • 全角文字と半角文字を判別して文字列を追加

    全角文字と半角文字が混合している文字列に文字を追加するプログラムを考えています。 仕様としては全角から半角に変わる際には全角文字の後ろに1234を、 半角から全角に変わるときは半角文字の後ろに4321をつけるというものです。 例1 文字列が「あxxxお」ならば出力結果は「あ1234xxx4321お」 そこで質問なのですが 文字列から全角文字と半角文字をプログラム上で判別して 上記のように出力するにはどうしたらいいんでしょうか? ヒント等ございましたらどうぞお願いします。 とりあえず作ってみた例1の結果を無理やり出力するプログラムのコードを載せておきます。 こちらをうまく改変してくださっても結構ですのでよろしくお願いいたします。 #include <stdio.h> #include <string.h> int main(void){ unsigned char str0[256] = "あxxxお", str1[256] = "1234",str2[256]= "4321"; unsigned int zh,hz, len0 = strlen(str0),len1=strlen(str1),len2=strlen(str2); printf("挿入前:%s\n",&str0); zh=2; //全角から半角に変わる位置 hz=5; //半角から全角に変わる位置 //1234を挿入/// memmove(&str0[zh+len1], &str0[zh], len0 - zh+1); memcpy(&str0[zh], str1, len1); //4321を挿入/// memmove(&str0[hz+len1+len2], &str0[hz+len1], len0); memcpy(&str0[hz+len1], str2, len2); printf("挿入後:%s\n",&str0); return 0; }

  • JISの全角判定処理について

    お世話になっております。 C++初心者です。 今、JISの全角判定処理を作っているのですが、 フォームのイベントでKeyPressに関数をセットしてあるのですが、 関数のフォーマットが void *********(char &Key); ※[*]は任意の文字列 になっており、半角ならこの関数を1回通り、 全角なら2回通ります。(引数の変更はできません) そこで下記のような関数を作成しました。 void pressKeyFullPitch(char &Key){   static bool fullFlag = false;   if(fullFlag){     fullFlag=false;     Key='*'     return;   }   if( Key >= 0x81 && Key <= 0x9f) || (Key >= 0xe0 && Key <= 0xfc ){     fullFlag = true;     Key = '*';   }      } 全角で入力された2byte文字は2byteとも[*]にするようにしています。 ここて関数内にstatic boolを宣言していますが、 static変数は関数終了時にも値を保持しているため あまり使わないほうがいい気がするので質問させていただきます。 ※すいません、経験が少ないのでstatic変数について知識が足りないかもしれません。 この場合、static変数を使わずうまく処理できる方法が ありましたら、お願いします。

  • 漢字の第1バイト検証

    今、文字判定関数について勉強しているのですが、 unsingned char uch にgetchar()の値を入れ if(uch >= 0x81 && uch <= 0x9f || uch >= 0xe0 && uch <= 0xfc) とうコードで、なぜ漢字コードは「0x81~0x9f」と「0xe0~0xfc」の 二つの範囲があるのか解りません。 よろしくお願いします。

  • 全角数字、アルファベット大小を認識させたいのですが上手くいきません

    入力文字列が、全角数字なのか、全角アルファベットなのか、或いはそれ以外なのかを判断させたいのですが、 以下の「testfunc」では、全角数字、全角アルファベットの大文字のみ判断可能で、全角アルファベットの小文字が、全角英数以外と認識されてしまいます。 どうすれば、全角アルファベットの小文字も認識できるようになるでしょうか? どなたかよいアドバイスをください。 #include <stdio.h> int testfunc (char *c) { unsigned a, b; a = c[0];//上位バイト b = c[1];//下位バイト if ((a >= 0x82) && ((b >= 0x4f) && (b <= 0x58))){//全角0~9 return 2; } else if ((a >= 0x82) && ((b >= 0x60) && (b <= 0x9a))){//全角A~z return 1; } else { return 0; } }

  • 問題文に対してこのプログラムは正しいか

    文字列を先頭から1文字ずつ表示する関数を作成せよ。 void gput(const char *s, int speed); ここで、sは表示する文字列、speedはミリ秒単位の表示速度である。たとえば、 gput("ABC", 100); と呼びだすと、まず'A'を表示し、その100ミリ秒後に'B'を表示し、さらにその100ミリ秒後に'C'を表示する。このようにして"ABC"の全文字を表示すると呼び出し元に戻ること。 /* 課題2-1 */ #include <time.h> #include <stdio.h> #include <stdlib.h> /* gput関数の宣言 */ void gput(const char *s, int speed); /* sleep関数の宣言 */ int sleep(unsigned long x); int main (void) { gput("ABC", 1000); return (0); } /* gput関数の定義 */ void gput(const char *s, int speed) { int i; int c = strlen(s); for(i=0; i<c; i++){ putchar(s[i]); fflush(stdout); sleep(speed); } } /* sleep関数の定義 */ int sleep(unsigned long x) { clock_t c, s = clock(); do{ if((c = clock()) == (clock_t)-1) return (0); }while(1000UL * (c - s) / CLOCKS_PER_SEC < x); return (1); } 演習問題に解答が無いので質問します。 呼び出し元に戻ることとは、gput関数を呼び出した後にmain関数に戻ることを言っているのでしょうか。 またsleep関数では、return 0とreturn1を使い分けていますがそれぞれどういった意味があるのですか。 関数の返り値は理解できるのですが、本にmain関数のreturn0についてなど何も触れられていないので混乱しています。

  • 全角文字の判定

    現在C言語を勉強しております。 そこで、キーボードから入力された文字列のチェックを行う関数を作成したいのですが、実装方法が分かりません・・・。 以下に仕様と私の作成したソースを貼ります。 【許可する文字】は、 全角のひらがな 全角の英語(大文字も小文字もOK) 全角の数字 です。 チェックする関数を作成したいのですが、以下ではうまくいかず・・・ 教えてくださいorz 比較の仕方がおかしいでしょうか? 関数は、引数として渡された文字列に許可以外の文字が含まれている場合は1を、そうでなければ0を返す、という仕様にしたいです。 int checkName(char *str) { int i; for(i = 0; str[i] != '\n'; i++){ /* 奇数バイトをチェック */ if(str[i] == 0x82){ i++; /* ひらがなの場合 */ if(str[i] >= 0xa0 && str[i] <= 0xf1) printf("ひらがな\n"); return 0; /* 英語(大文字)の場合 */ if(str[i] >= 0x60 && str[i] <= 0x79) printf("英語大\n"); return 0; /* 英語(小文字)の場合 */ if(str[i] >= 0x81 && str[i] <= 0x9a) printf("英語小\n"); return 0; /* 数字の場合 */ if(str[i] >= 0x50 && str[i] <= 0x58) printf("数字\n"); return 0; } return 1; } return 0; } 以上、よろしくお願いいたします。

  • 文字列の扱い方

    初歩的な質問ですみません… str文字列からcという文字を見つけたら添字を返すという関数を作ったのですが、 iにこの関数を代入して、if文の制御式にiを使って比較するまでは正常なのですが、 真文にiを使うと何故か偽文(という言い方でいいのでしょうか…この場合("そんな値はありません。"というところです)が実行されてしまいます。 よろしければご教授お願い致します。 #include <stdio.h> int str_char(const char str[],int c) { int len = strlen(str); int i; for (i = 0;i < len;i++) { if (str[i] == c) return i; } return -1; } int main() { char str[64] = "Fucking Brutal Death Metal"; int ch,i; printf("どの文字を調べますか?"); scanf("%c",&ch); i = str_char(str,ch); if (i >= 0) printf("その文字は%d番目にあります。",str_char(str,ch) + 1); //何故かiだと動かない else printf("そんな値はありません。"); return 0; }