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

但是,由于charand的大小不同wchar_t,我不能只传递数组;我必须使用转换并将mbstowcs临时传递wchar_t *CommandTree_putnw. 这是次优的,因为它将CommandTree_putn看到最多的使用,并且这将存储字符串的内存使用 ( sizeof (char)to sizeof (char) + sizeof (wchar_t)) 增加五倍,如果其中很多将使用较长的命令进行实例化,这可能会堆叠。

我想知道我可以做一些事情,比如创建一个包含逻辑的第三个函数,并传递 a size_t,这取决于它将传递给它的字符串转换为 a 的值,或者void *但假设 C 是静态类型的,我必须将逻辑转换为各自的类型,这会破坏我想要的“单个逻辑实例”的想法。const char *const wchar_t *s

所以最终,问题是,我是否可以只提供一次程序逻辑const char *const wchar_t *分别传递包装器,而不在函数中创建一个临时wchar_t *来处理const char *

4

1 回答 1

3

我不知道你的硬性要求,但wchar_t正是因为这个问题,往往很难处理;与使用char.

我使用过的所有代码库最终都迁移到了 UTF-8,这消除了以不同类型存储字符串的必要性。UTF-8 与标准strcpy/strlen类型的字符串操作函数一起使用,并且完全精通 Unicode。唯一的挑战是您需要将其转换为 UTF-16 才能调用 Windows Unicode API。(OS X 可以直接使用 UTF-8。)你没有提到平台,所以我不知道这对你来说是否是个问题。在我们的例子中,我们只是编写了采用 UTF-8 字符串的 Win32 包装器。

你能用C++吗?如果是这样,并且实际类型wchar_t很重要(而不是 Unicode 支持),您可以将函数模板化,然后使用std::wstringstd::string根据字符串宽度实例化它们。您也可以将它们编写为基于char并且wchar_t如果您很勇敢,但是您需要编写特殊的包装器函数来处理诸如strcpyvs之类的基本操作wcscpy,因此到目前为止它最终会成为更多的工作。

在普通的 C 语言中,我认为根本没有灵丹妙药。有一些令人讨厌的答案,但我不能直面推荐。

于 2014-12-16T20:51:20.183 回答