1

コマンドを格納するために C でデータ構造を作成しています。これは、私が満足していないものに切り詰められたソースです。

#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>

#include "dbg.h"
#include "commandtree.h"

struct BranchList
{
    CommandTree *tree;
    BranchList *next;
};

struct CommandTree
{
    wchar_t id;       // wchar support actually has no memory cost due to the 
    bool term;        // padding that would otherwise exist, and may in fact be
    BranchList *list; // marginally faster to access due to its alignable size.
};

static inline BranchList *BranchList_create(void)
{
    return calloc(1, sizeof(BranchList));
}

inline CommandTree *CommandTree_create(void)
{
    return calloc(1, sizeof(CommandTree));
}

int CommandTree_putnw(CommandTree *t, const wchar_t *s, size_t n)
{
    for(BranchList **p = &t->list;;)
    {
        if(!*p)
        {

            *p = BranchList_create();
            if(errno == ENOMEM) return 1;
            (*p)->tree = CommandTree_create();
            if(errno == ENOMEM) return 1;
            (*p)->tree->id = *s;
        }   
        else if(*s != (*p)->tree->id)
        {   
            p = &(*p)->next;
            continue;
        }
        if(n == 1)
        {
            (*p)->tree->term = 1;
            return 0;
        }
        p = &(*p)->tree->list;
        s++;
        n--;

    }
}
int CommandTree_putn(CommandTree *t, const char *s, size_t n)
{
    wchar_t *passto = malloc(n * sizeof(wchar_t));
    mbstowcs(passto, s, n);
    int ret = CommandTree_putnw(t, passto, n);
     free(passto);
    return ret;
}

これは完全にうまく機能しますが、ツリーがwchar_t. CommandTreeのパディングにより7 バイト未満のデータ型が同じくらい多くのメモリを消費することに気付いたので、これを追加することにしましたが、コードを複製しないようCommandTree_putnに、 wchar_t-supporting のロジックを再利用しましたCommandTree_putnw

charただし、とのサイズの違いにより、wchar_t単に配列を渡すことはできません。を使用して変換しmbstowcs、一時wchar_t *を に渡す必要がありCommandTree_putnwます。これは最適ではありません。これはCommandTree_putn、 が最も多く使用され、格納された文字列のメモリ使用量が 5 倍 ( sizeof (char)sizeof (char) + sizeof (wchar_t)) になることを考えると、これらの多くが長いコマンドでインスタンス化される場合にスタックする可能性があります。

ロジックを含む 3 番目の関数を作成し、渡された文字列を aにsize_tキャストする値に応じて、またはC が静的に型付けされていることを考えると、 、それぞれのタイプへのキャストを使用してロジックをほぼ複製する必要があり、これにより、「ロジックの単一インスタンス」のアイデアが台無しになります。void *const char *const wchar_t *s

したがって、最終的に問題は、プログラム ロジックを 1 回だけ提供し、ラッパーconst char *const wchar_t *それぞれ渡すことができるかwchar_t *ということです。const char *

4

1 に答える 1

3

あなたの厳しい要件はわかりませんがwchar_t、この問題のために正確に作業するのが難しい傾向があります。を使用する既存のコードと噛み合うのは難しすぎますchar

私が扱ってきたすべてのコードベースは、最終的に UTF-8 に移行されました。これにより、文字列を別の型で保存する必要がなくなりました。UTF-8 は標準strcpy/strlenタイプの文字列操作関数で動作し、Unicode に完全に精通しています。唯一の課題は、Windows Unicode API を呼び出すために UTF-16 に変換する必要があることです。(OS X は UTF-8 を直接使用できます。) プラットフォームについて言及していないので、これが問題になるかどうかはわかりません。私たちの場合、UTF-8 文字列を取る Win32 ラッパーを書きました。

C++は使えますか?wchar_tその場合、 (Unicode のサポートではなく)実際の型が重要な場合は、関数をテンプレート化し、文字列の幅を使用して、std::wstringまたはstd::string文字列の幅に応じてインスタンス化できます。勇気があればcharandに基づいてそれらを作成することもできますが、 vsなどの基本的な操作を処理する特別なラッパー関数を作成する必要があるため、全体的にはるかに多くの作業が必要になります。wchar_tstrcpywcscpy

普通の C では、特効薬はまったくないと思います。厄介な答えがありますが、私が真顔でお勧めできるものはありません.

于 2014-12-16T20:51:20.183 に答える