文字列を連結する strcat の可変長引数版(C言語)と その template 化 (C++)
目的
- (ポインタを使う一例として)、strcat より機能が高い、たとえば可変長引数で無数連結できる関数 combStrを strcat を用いずに C言語で作ります。
- (Templete を使う例として)作った combstr の wchar 版も作成し、char, wchar をテンプレートによりまとめ、ワイド文字列にも対応したものにします
C++であれば STL の vector クラスを使うのがふつうだと思いますが、ここではあえてポインタでそれをやってみるということです。
template <typename T>
unsigned int mylen(T* str){
unsigned int i = 0; while (str[i] != 0x00)
{
i = i + 1;
}
if (typeid(T) == typeid(wchar_t)){ return 2 * i; }
else{ return i; }
}
template unsigned int mylen(char*s);
template unsigned int mylen(wchar_t*s);
template <typename T>
T** CreChrArray(DWORD num){
return (T **)calloc(sizeof(T*) * (num + 1), sizeof(T*));
}
template char** CreChrArray(DWORD num);
template wchar_t** CreChrArray(DWORD num);
template <typename T>
T* CreChr(DWORD num){
return (T*)calloc(sizeof(T)*num, sizeof(T));
}
template char* CreChr(DWORD num);
template wchar_t* CreChr(DWORD num);
template <typename T>
unsigned int getByteChrArray(T** s){
unsigned int i = 0, b = 0;
while (s[i] != 0) {
b = b + mylen<T>(s[i]);
i = i + 1;
}
return b;
}
template unsigned int getByteChrArray(char**s);
template unsigned int getByteChrArray(wchar_t**s);
template <typename T>
T* combStr(T *s, ...){
unsigned char c = 1;
if (typeid(T) == typeid(wchar_t)){
c = 2;
}
int i = 0;
T **a = CreChrArray<T>(i);
va_list ap;
va_start(ap, s);
do {
i = i + 1;
a = (T **)realloc(a, (i + 1) * sizeof(T *));
a[i - 1] = s;
s = va_arg(ap, T*);
} while (s);
va_end(ap);
a[i] = 0x00; //旧 a[i]="\0";
int bi = getByteChrArray<T>(a);
int p = 0;
T* str = CreChr<T>(bi);
for (int j = 0; j < i; j++){
memcpy(str + p, a[j], mylen<T>(a[j]));
if (j < i) { p = p + mylen<T>(a[j]) / c; }
else{ break; }
}
str[p] = 0x00;
free(a);
return str;
}
template char* combStr(char *s, ...);
template wchar_t* combStr(wchar_t *s, ...);