Last Update: Dec.12,2002

C Source Library

「LSI C-86 Ver.3.30c 試食版」、「Borland C++ 5.5」でコンパイル出来ます。

■ エスケープ文字を使って文字列変換

/*
 *  c_str.c : エスケープ文字を使って文字列変換
 *
 *      Copyright (c) 2002 AOK. 
 *
 *      2002.12.11 - 初版
 *
 *  かなり使い道があると思うのは僕だけかな…
 *
 */

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

/* 
 *  入力文字列をCスタイルの文字列に変換。
 *  dst を NULL にして必要なバッファサイズ(NULL文字を含まない)
 *  を求め、dst の領域確保を行うこと。
 */
int c_escape(char *src, char *dst)
{
    unsigned char c;
    int mode = 0, cnt = 0;
    while (*src != '\0')
    {
        c = (unsigned char)*src++;
        switch (mode)
        {
        case 0:
            switch (c)
            {
            case '\t': if (dst != NULL) { *dst++ = '\\'; *dst++ = 't'; } cnt+=2; break;
            case '\n': if (dst != NULL) { *dst++ = '\\'; *dst++ = 'n'; } cnt+=2; break;
            case '\r': if (dst != NULL) { *dst++ = '\\'; *dst++ = 'r'; } cnt+=2; break;
            case '\\': if (dst != NULL) { *dst++ = '\\'; *dst++ = '\\';} cnt+=2; break;
            case '\"': if (dst != NULL) { *dst++ = '\\'; *dst++ = '\"';} cnt+=2; break;
            default:
                if ((c>=0x81 && c<=0x9F) || (c>=0xE0 && c<=0xFC)) mode = 1;
                if (dst != NULL) *dst++ = c;
                cnt++;
                break;
            }
            break;
        case 1:
            if (dst != NULL) *dst++ = c;
            cnt++;
            mode = 0;
            break;
        default:
            break;
        }
    }
    if (dst != NULL) *dst = '\0';
    return cnt;
}

/* 
 *  Cスタイルの文字列を元の文字列に戻す。
 *  dst を NULL にして必要なバッファサイズ(NULL文字を含まない)
 *  を求め、dst の領域確保を行うこと。
 */
int c_unescape(char *src, char *dst)
{
    unsigned char c;
    int mode = 0, cnt = 0;
    while (*src != '\0')
    {
        c = (unsigned char)*src++;
        switch (mode)
        {
        case 0:
            if (c == '\\') { mode = 2; break; }
            if ((c>=0x81 && c<=0x9F) || (c>=0xE0 && c<=0xFC)) mode = 1;
            if (dst != NULL) *dst++ = c;
            cnt++;
            break;
        case 1:
            if (dst != NULL) *dst++ = c;
            cnt++;
            mode = 0;
            break;
        case 2:
            if (dst != NULL)
            {
                switch (c)
                {
                case 't':  *dst++ = '\t'; break;
                case 'n':  *dst++ = '\n'; break;
                case 'r':  *dst++ = '\r'; break;
                case '\\': *dst++ = '\\'; break;
                case '\"': *dst++ = '\"'; break;
                default:   *dst++ = c;    break;
                }
            }
            cnt++;
            mode = 0;
            break;
        default:
            break;
        }
    }
    if (dst != NULL) *dst = '\0';
    return cnt;
} 

/* テスト */
int main()
{
    int n;
    char p1[32767], *p2, *p3;
    fgets(p1, 32767, stdin);
    /* エスケープする */
    n = c_escape(p1, NULL); 
    printf("escape:   <%d>\n", n);
    p2 = (char *)malloc(n+1);
    c_escape(p1, p2);
    /* アンエスケープする */    
    n = c_unescape(p2, NULL);
    printf("unescape: <%d>\n", n);
    p3 = (char *)malloc(n+1);
    c_unescape(p2, p3);
    /* 表示 */
    printf("%s\n", p1);
    printf("%s\n", p2);
    printf("%s\n", p3);
    free(p2);
    free(p3);
    return 0;
}