質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.19%

C言語 全角文字と半角文字

解決済

回答 2

投稿 ・編集

  • 評価
  • クリップ 1
  • VIEW 7,452

deluhi0905

score 29

ご質問いたします。
入力した全角文字列と半角文字列を配列に格納し区別をつける処理を作成しましたが、
全角と半角文字列を配列に格納してから「逆」に表示させることは可能でしょうか。

下記ソースコードは全角・と半角の区別をつけています。
--------------------------------------------------------------------
int utfcheck(unsigned char c)   /* 符号付き無しの文字ビット */
{
    if(c&0x80)
    {
        return 1;               /* 全角文字なら1を返す */
    }
    return 0;                   /* 半角文字なら0を返す */
}
--------------------------------------------------------------------
OSはLINUX、コンパイラはgcc、
文字コードはUTF-8で、半角文字が1文字1バイト、全角文字が1文字3バイト配列に格納されます。

ご回答お願いいたします。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

逆とは、"あいう" => "ういあ" のようなことですかね。
そういうの書いたことないので、書いてみました。

#include <stdio.h>
#include <string.h>

main(){
    int c;
    char *p, *q;
    char in[] = "あaい01";
    char out[100];
    char work[6], *w;

    q = out;
    w = work;
    for(p=in+strlen(in)-1; p>=in; p--){
        if((*p&0x80)==0){ /* 1バイト文字 */
            *q++ = *p;
        }else if((*p&0xC0)==0x80){ /* 複数バイトの2バイト目以降 */
            *w++ = *p;
        }else{ /* 複数バイトの先頭 */
            *q++ = *p;
            while(w>work){
                *q++ = *--w;
            }
        }
    }
    *q = 0;

    printf("%s\n",out);
}

工夫すれば、work無しで出来ると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2014/11/03 18:36

    otn さん
    ご回答いただきありがとうございます。

    ---------------------------------------------------------------------
    for(p=in+strlen(in)-1; p>=in; p--){
    if((*p&0x80)==0){ /* 1バイト文字 */
    > *q++ = *p;
    }else if((*p&0xC0)==0x80){ /* 複数バイトの2バイト目以降 */
    > *w++ = *p;
    }else{ /* 複数バイトの先頭 */
    > *q++ = *p;
    while(w>work){
    > *q++ = *--w;
    }
    }
    }
    > *q = 0;
    ---------------------------------------------------------------------

    ソースコードですが、バイト文字の比較を行っているのは理解できたのですが、
    「>」の個所の流れが掴めません。「複数バイトの2回目以降」は何をやっているのでしょうか。
    恐れ入りますが、それぞれの役目が何を行っているのか教えていただけないでしょうか。

    キャンセル

  • 2014/11/03 19:49

    方針として、(私にとって)わかりやすくするために、バイト配列を1バイトずつ逆順に見ていき、後戻りしない(一度見た配列要素を二度と見ない)ということにしました。

    なので、複数バイト文字の一部であるとわかったものを別のwork配列に保存しておきます。3バイト目を保存して次に2バイト目を保存します。
    複数バイト文字の先頭バイトが出てきた段階で、まず先頭バイトを出力して、さっきwork配列に保存したバイト列を逆順に取り出します。最後に保存した2バイト目を最初に取り出して先頭バイトの次に出力、さらにその前に保存した3バイト目を取り出して出力します。

    最初に書いた方針でなくて、入力配列の複数バイト文字の末尾位置を記憶するポインタを使うとwork配列無しで出来ると思います。状態を持つことになるので考えるのがめんどくさいと思ったのですが、いま考え直すとそんなに面倒ではないですね。

    勉強のためでなく実用のためなら、他の方が書いているようにライブラリを使うんでしょうね。

    キャンセル

  • 2014/11/04 23:42

    otn さん
    コメント頂きありがとうございます。

    ソースコードの説明ありがとうございます。処理の流れが掴めました。
    自分が解りやすくして、尚且つ第三者が見ても解りやすいソースを作成していきます。

    ご回答頂きありがとうございました。

    キャンセル

0

C 言語で日本語を扱うのは結構大変なので、すべて自分で実装するのは現実的ではないです。
普通はライブラリーやフレームワークの関数を使います。

その際の方針としては次の 2 つです。

1. 入力、出力の際に変換し、内部では 16 または 32 ビット Unicode (wchar_t) で扱う
2. UTF-8 で統一し、文字列操作は専用の関数群を使う


1 の方針だと日本語も 1 文字として扱えて処理しやすいので、こちらが主流だと思います。

ただ、 linux で C 言語だとすると glib が使えるのですが、こちらは 2 の方針です。
glib を使うのであれば g_utf8_strreverse() という関数があるので、これで反転できます。

Unicode の取り扱い#g-utf8-strreverse

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2014/11/04 23:48

    yohshiy さん
    ご回答頂きありがとうございます。

    1,2の方針の説明、ありがとうございました。
    今回は配列やポインタ等を使用して全角・半角文字を逆順に表示するやり方で行きますが、1や2の方針でも試してみようと思います。

    ご回答頂きありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.19%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る