2014-12-16 12 views
1

나는 명령을 저장하기 위해 C로 데이터 구조를 작성하고있다. 여기에 내가에 만족 해요 무엇을 아래로 깎았 원인이 완벽하게 잘 작동명시 적 문자열 복사없이 char 문자열과 wchar_t 문자열 사이에서 함수 논리를 다시 사용 하시겠습니까?

#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 바이트보다 작은 데이터 유형을 만들 수 있다는 것을 알았을 때이 코드를 추가하기로 결정 했으므로 코드를 복제하지 않으므로 의 논리를 다시 사용하십시오.

그러나 charwchar_t의 크기 차이로 인해 필자는 배열을 전달할 수 없습니다. 을 CommandTree_putnw으로 전달해야합니다. CommandTree_putn이 가장 많이 사용되며 저장된 문자열의 메모리 사용량 (sizeof (char) ~ sizeof (char) + sizeof (wchar_t))이 5 배로 길어 졌다고 가정 할 때이 옵션은 차선입니다. 이러한 문자열이 오래 걸리는 명령으로 인스턴스화 될 경우 스택 할 수 있습니다.

은 내가 논리를 포함 할 세 번째 함수를 만드는 등의 일을 할 수 있고, 그것이 void *에 하나 const char * 또는로 전달 된 문자열을 던졌다있는 값에 따라 size_t을 전달받을를 궁금 해서요 const wchar_t *하지만 C가 정적으로 입력되면, 나는 논리를 "논리의 단일 인스턴스"로 옮길 생각을 망칠 수있는 각각의 유형으로 캐스팅 된 로직을 s으로 복제해야합니다.

그래서 궁극적으로 문제는, 내가 한 번만 프로그램 로직을 제공 할 수 const char *를 처리하는 기능에 임시 wchar_t *을 만들지 않고, 각각 래퍼 const char *const wchar_t *을 통과?

+0

독서를 쉽게하기 위해 거대한 단락을 별도의 문장으로 자르십시오! –

답변

3

어려운 요구 사항을 모르지만 wchar_t은이 문제로 인해 정확하게 작업하기가 쉽지 않습니다. char을 사용하는 기존 코드와 메쉬하기가 너무 어렵습니다.

내가 작업 한 모든 코드베이스는 결국 다른 유형의 문자열을 저장할 필요성을 제거하는 UTF-8로 마이그레이션되었습니다. UTF-8은 표준 strcpy/strlen 유형의 문자열 조작 함수와 함께 작동하며 완전히 유니 코드에 익숙합니다. 유일한 과제는 Windows 유니 코드 API를 호출하기 위해이를 UTF-16으로 변환해야한다는 것입니다. (OS X은 UTF-8을 직접 사용할 수 있습니다.) 플랫폼에 대해 언급하지 않았으므로이 문제가 귀하에게 문제가되는지는 잘 모릅니다. 여기에서는 UTF-8 문자열을 사용하는 Win32 래퍼를 작성했습니다.

C++을 사용할 수 있습니까? 그렇다면 실제 유형 wchar_t이 중요합니다 (유니 코드 지원이 아닌). 함수를 템플릿 화 한 다음 문자열 너비에 따라 std::wstring 또는 std::string으로 인스턴스화 할 수 있습니다. 용감한 사람이라면 charwchar_t을 기반으로 작성할 수 있지만 strcpywcscpy과 같은 기본 작업을 처리하는 특수 래퍼 기능을 작성해야하므로 전반적으로 훨씬 더 많은 작업이 끝납니다.

C에서 나는 총알이 전혀 없다고 생각합니다. 운 좋은 대답이 있지만, 나는 똑바로 얼굴로 추천 할 수 없다.

+0

순수한 UTF-8 아이디어가 마음에 들지만 C가 wchar_t를 사용하여 UTF-8을 저장하는 표준 방법이 아닙니다. 이 경우 기존 코드를 어떻게 리팩터링합니까? 플랫폼에 따라 POSIX 호환 OS 세트가 주요 대상입니다. Windows 포팅은 추가 고려 사항 일 것입니다. –

+1

UTF-8은 항상 8 비트'char'에 저장되고'wchar_t'에 저장되지 않습니다. POSIX를 타겟으로한다면 실제로'wchar_t'가 필요 없습니다. POSIX API는이를 사용하지 않습니다. – StilesCrisis

+0

아, 알겠습니다. 그래서 widechar 메서드를 모두자를 수 있습니까? –