ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

C言語コミュの[課題]Converting Character Strings

  • mixiチェック
  • このエントリーをはてなブックマークに追加
Converting Character Strings


Write a program that does the inverse of the program you wrote in 04A1.

Keywords: nested if/switch, (circular) buffer
Details
If the input contains the strings "<", ">", "&", """, or "'", your program outputs this respectively as '<', '>', '&', '"', or '\''. Any other input should be output without changes.

Use single-character input. Do not rely on limited line lengths.

Hint:
Use input/output redirection and the diff command for testing. Use 04-080in.txt as the input file and 04-080check.txt as the checking file. Try to get more and more lines of the test files to work correctly.

Hint:
There are two main strategies to solve this problem: nested if (or switch) statements, or a small buffer.

04-080in.txt ↓
<
<xyz
&lghik
&hahaha;
>
>
&g
>gt
&ghik
'
&aposososo
&apu
&alu
&
&le
風林火山&m; 風林火山
&ahaha
風林火山"風林火山
&風林火山;
"e
"
&quodlibet
&qu
&qq
&q
&bc
&
<&"'>
haba ' futa
haba'futa
amp;&
風林火山風林火山aaaaaa風林火山<b>c"d&e'ffff風林火山
風林火山風林火山aaaaaa風林火山nthoauerh.oschoarsukchsarochpusraohusrcoahpurscho.aurunh風林火山風林火山aaaaaa風林火山nthoauerh.oschoarsukchsarochpusraohusrcoahpurscho.aurun




04-080check.txt ↓

<
<xyz
&lghik
&hahaha;
>
>
&g
>gt
&ghik
'
&aposososo
&apu
&alu
&
&le
風林火山&m; 風林火山
&ahaha
風林火山"風林火山
&風林火山;
"e
"
&quodlibet
&qu
&qq
&q
&bc
&
<&"'>
haba ' futa
haba'futa
amp;&
風林火山風林火山aaaaaa風林火山<b>c"d&e'ffff風林火山
風林火山風林火山aaaaaa風林火山nthoauerh.oschoarsukchsarochpusraohusrcoahpurscho.aurunh

コメント(10)

#include<stdio.h>

int main(void)
{
int c;

while((c = getchar()) != EOF){
if(c == '<'){
printf("<");
}else if(c == '>'){
printf(">");
}else if(c == '&'){
printf("&");
}else if(c == '"'){
printf(""");
}else if(c == '\''){
printf("'");
}else{
putchar(c);
}
}
return(0);
}
問題文が実体参照によって変換されてしまっているので、
そのまま読むと意味わからないです。

&lt; を < に
&gt; を > に
&amp; を & に
&quot; を " に
&apos; を ' に
逆変換するプログラムを作りなさい。

ってことであってますか?
この手の処理って状態を持たせて受理状態になるまで一向読んで状態遷移させるので普通にやるとでっかいswitch文が必要になってしまいますね。

#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

enum STATUS {
    NONE,
    ENC_START,
    LT_L, LT_T,
    GT_G, GT_T,
    AMP_OR_APOS_A, 
    AMP_M, AMP_P,
    APOS_P, APOS_O, APOS_S,
    QUOT_Q, QUOT_U, QUOT_O, QUOT_T,
};

#define    CHARBUF_INIT_SIZE    8
static int *charbuf = NULL;
static size_t charbuf_size = 0;
static int charbuf_head = 0;

static void
clear_buffer(void)
{
    charbuf_head = 0;
}

static void
print_buffer(void)
{
    int i;
    for (i = 0; i < charbuf_head; i++)
        printf("%c", charbuf[i]);
    clear_buffer();
}

static void
push_buffer(int c)
{
    if (charbuf_size <= charbuf_head) {
        charbuf_size = (charbuf_size == 0)?CHARBUF_INIT_SIZE:charbuf_size*2;
        charbuf = reallocf( charbuf, charbuf_size);
        if (charbuf == NULL)
            err(errno, "realloc");
    }
    charbuf[charbuf_head++] = c;
}

続き。
int
main(void)
{
    enum STATUS status;
    status = NONE;
    while (!feof(stdin)) {
        int c = getchar();
        push_buffer(c);
        switch (c) {
        case '&':
            status = ENC_START;
            break;
        case ';':
            switch (status) {
            case LT_T:
                printf("<");
                break;
            case GT_T:
                printf(">");
                break;
            case AMP_P:
                printf("&");
                break;
            case APOS_S:
                printf("'");
                break;
            case QUOT_T:
                printf("\"");
                break;
            default:
                print_buffer();
            }
            clear_buffer();
            break;
続き その2
        case 'a':
            if (status == ENC_START)
                status = AMP_OR_APOS_A;
            else
                print_buffer();
            break;
        case 'g':
            if (status == ENC_START)
                status = GT_G;
            else
                print_buffer();
            break;
        case 'l':
            if (status == ENC_START)
                status = LT_L;
            else
                print_buffer();
            break;
        case 'm':
            if (status == AMP_OR_APOS_A)
                status = AMP_M;
            else
                print_buffer();
            break;
        case 'o':
            if (status == APOS_P)
                status = APOS_O;
            else if (status == QUOT_U)
                status = QUOT_O;
            else
                print_buffer();
            break;
        case 'p':
            if (status == AMP_OR_APOS_A)
                status = APOS_P;
            else if (status == AMP_M)
                status = AMP_P;
            else
                print_buffer();
            break;
続き その3
        case 'q':
            if (status == ENC_START)
                status = QUOT_Q;
            else
                print_buffer();
            break;
        case 's':
            if (status == APOS_O)
                status = APOS_S;
            else
                print_buffer();
            break;
        case 't':
            if (status == LT_L)
                status = LT_T;
            else if (status == GT_G)
                status = GT_T;
            else if (status == QUOT_O)
                status = QUOT_T;
            else
                print_buffer();
            break;
        case 'u':
            if (status == QUOT_Q)
                status = QUOT_U;
            else
                print_buffer();
            break;
        default:
            printf("%c", c);
        }
    }

    return EXIT_SUCCESS;
}

以上。

状態をオブジェクトのようなもので表現して、変化させた方が良かったかなぁ...
やってみました。
文字数の制限に引っかかったのでこっちに載せました。
http://mixi.jp/view_diary.pl?id=434737045&owner_id=896165
見直してみて、バグ発見。
print_buffer()の時にstatus = NONE;をするのを忘れてた。(--;
あと、default:の動作はprint_buffer()にしないとだめ。

そうしないと#include<stdio.h>すら
まともに表示されない(--;;

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

C言語 更新情報

C言語のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。