※「セキュリティ保護のため...」というメッセージが出る方・日本語が入力できない方へ
文字列分解結合
int InCha(const char* str, int cnt, char a);
int LineStrMix(char* str);
int LineStrSep(char* str, const char* lfcode);
char* my_strtok(char* str, const char* del);
char* my_strtok1(char* str, const char* del);
long my_strtok1L(char* str, const char* del);
long my_strtokL(char* str, const char* del);
double my_strtokD(char* str, const char* del);
char* my_buftok(char* str, int len);
long my_buftokL(char* str, int len);
試作品
#ifdef UTL_MAIN
char* my_strtok_ptr;
char my_strtok_del;
int swDebug = 1;
#else
extern char* my_strtok_ptr;
extern char my_strtok_del;
extern int swDebug;
#endif
■文字が指定グループに入っているかどうかをチェックするルーチン。
この手の処理は通常strstrでチェックするのだが、このルーチンは
my_strtok用の特別仕様であり、それ以外の用途はあまりないかも。
/********************************************************************
* 文字の位置 (0-origin, not found = -1)
*******************************************************************/
int InCha(const char* str, int cnt, char a)
{
int k;
k = 0;
while(cnt--)
{
if (str[k]==a)
return(k);
k++;
}
return(-1);
}
■strtokを少し変形したものである。
(1)strtokは最後まで文字列を読んでしまうと、その次の呼び出しで
エラーが起きてしまう。これを避ける。
(2)strtokが内部的に使用している変数をグローバルに置いて、strtok
をネストして使うことを可能にした。
(3)my_strtokL などは結果を数字で取り出すものである。使用している
PickSuzi系についてはこちらを参照。
/********************************************************************
* 文字列分解(strtok準拠,スコシチガウ)
*******************************************************************/
char* my_strtok(char* str, const char* del)
{
int k;
char* q;
if (!str)
str = my_strtok_ptr;
while(InCha(del,strlen(del),*str)>=0)
str++;
if (*str==0)
{
my_strtok_del = 0;
my_strtok_ptr = str;
return(0);
}
for (q=str; *q; q++)
{
k = InCha(del, strlen(del), *q);
if (k>=0)
{
my_strtok_del = del[k];
my_strtok_ptr = q+1;
*q = 0;
return(str);
}
}
my_strtok_del = 0;
my_strtok_ptr = q;
return(str);
}
long my_strtokL(char* str, const char* del)
{
char* p;
p = my_strtok(str, del);
return( PickSuziS(p) );
}
double my_strtokD(char* str, const char* del)
{
char* p;
p = my_strtok(str, del);
return( PickSuziSD(p) );
}
■strtokのバリエーションで区切り文字を1個ずつ使用するもの。
例えば空白が2個続いている時、それを1個の空白とはみなさない。
/********************************************************************
* 文字列分解(strtok準拠,スコシチガウ) 連続区切り文字を1個ずつ使う
*******************************************************************/
char* my_strtok1(char* str, const char* del)
{
int k;
char* q;
if (!str)
str = my_strtok_ptr;
if (*str==0)
{
my_strtok_del = 0;
my_strtok_ptr = str;
return(0);
}
for (q=str; *q; q++)
{
k = InCha(del, strlen(del), *q);
if (k>=0)
{
my_strtok_del = del[k];
my_strtok_ptr = q+1;
*q = 0;
return(str);
}
}
my_strtok_del = 0;
my_strtok_ptr = q;
return(str);
}
long my_strtok1L(char* str, const char* del)
{
return PickSuziS(my_strtok1(str,del));
}
■buftok
似たような文脈で使用するルーチンだが処理内容はまるっきり違う。
これは固定長のレコードで使用するもので、指定桁のデータを取り
出すものである。このルーチンはstrtok同様区切り文字部分を破壊
するので注意。破壊が困る場合はMidStr系を使用のこと。
char* my_buftok(char* str, int len)
{
if (!str)
str = my_strtok_ptr;
str[len]=0;
my_strtok_ptr = str+(len+1);
return str;
}
long my_buftokL(char* str, int len)
{
return PickSuziS(my_buftok(str,len));
}
■複数行からなるデータを1個の文字列にまとめたり分解したりするもの
/********************************************************************
改行を含む文字列をまとめる (return=行数)
*******************************************************************/
int LineStrMix(char* str)
{
int i,j,k,m,r,len,c1,lcnt;
char* buf;
len = strlen(str);
buf = (char*)malloc(len*2+1);
for (i=j=k=m=r=lcnt=0; i<len; i++)
{
c1 = str[i]; if (c1<0) c1+=256;
if (c1==13) //CR
{
j=k;
buf[j++]='\\';
buf[j++]='n';
if (str[i+1]==10)
i++;
k=j;
lcnt++;
m=0;
continue;
}
if (c1==10) //LF
{
j=k;
buf[j++]='\\';
buf[j++]='n';
k=j;
lcnt++;
m=0;
continue;
}
if (c1==32) //ANK-SPACE
{
buf[j++]=str[i];
continue;
}
if (c1==129 && str[i+1]==64) //KANZI-SPACE
{
buf[j++]=str[i++];
buf[j++]=str[i];
continue;
}
if ((129<=c1 && c1<=159) || (224<=c1))
{
buf[j++]=str[i++];
buf[j++]=str[i];
k=r=j;
m=1;
continue;
}
else
{
buf[j++]=str[i];
k=r=j;
m=1;
continue;
}
}
buf[r]=0;
if (m) //最後の改行の後にも文字があった
lcnt++;
strcpy(str, buf);
free(buf);
return lcnt;
}
/********************************************************************
LineStrMixで作った文字列を解釈する (return=行数) ここでは空白の圧縮はしない
*******************************************************************/
int LineStrSep(char* str, const char* lfcode)
{
int i,j,m,len,c1,lcnt;
char* buf;
len = strlen(str);
buf = (char*)malloc(len*2+1);
for (i=j=m=lcnt=0; i<len; i++)
{
c1 = str[i]; if (c1<0) c1+=256;
if (c1==92 && str[i+1]==110) //\n
{
strcpy(buf+j, lfcode);
j+=strlen(lfcode);
lcnt++;
i++;
m=0;
continue;
}
if ((129<=c1 && c1<=159) || (224<=c1))
{
buf[j++]=str[i++];
buf[j++]=str[i];
m=1;
continue;
}
else
{
buf[j++]=str[i];
m=1;
continue;
}
}
buf[j]=0;
if (m) //最後の改行の後にも文字があった
lcnt++;
strcpy(str, buf);
free(buf);
return lcnt;
}
以下は試作品である。何かの必要にかられて一時的に作ったものであり、まだ
汎用ルーチンとしては仕上がっていない。参考までに。
■csv操作関係
char* my_csvpack(const char* str);
char* my_csvtok(char* str);
long my_csvtokL(char* str);
/********************************************************************
* CSV文字列操作
*******************************************************************/
char* my_csvpack(const char* str)
{
static char buf[256];
int i,j,cnt,len;
cnt=0;
len = strlen(str);
for (i=0; i<len; i++)
{
if (str[i]==34)
cnt++;
}
// char* buf = new char[len+cnt+4];
buf[0]=34;
for(i=0,j=1; i<len; i++)
{
if (str[i]==34)
{
buf[j++]=34;
buf[j++]=34;
}
else
buf[j++]=str[i];
}
buf[j++]=34;
buf[j]=0;
// CString wstr = CString(buf);
// delete [] buf;
return buf;
}
char* my_csvtok(char* str)
{
static char work[256];
int k;
char* q;
char qst;
char c1,c2;
if (!str)
str = my_strtok_ptr;
k=0;
/* Skip spaces */
while(*str==' ')
str++;
if (*str==0)
{
my_strtok_del = 0;
my_strtok_ptr = str;
return(0);
}
/* if quote ? */
if (*str==34 || *str==39)
qst=*str++;
else
qst=0;
q = str;
/* loop */
loop1:
c1=str[0];
c2=str[1];
if (qst)
{
if (c1==qst && c2==44) // quote + comma
{
my_strtok_ptr = str+2;
goto owari;
}
if (c1==qst && c2==0) // quote + null
{
my_strtok_ptr = str+1;
goto owari;
}
}
else
{
if (c1==44) // comma
{
my_strtok_ptr = str+1;
goto owari;
}
if (c1==0) // null
{
my_strtok_ptr = str;
goto owari;
}
}
work[k++]=c1;
str++;
// if ((c1>=0x080 && c1<=0x09f) || (c1>=0x0e0))
// dest[k++]=*sour++;
if (c1==qst && c2==qst)
str++;
goto loop1;
owari:
work[k]=0;
// if (k>0 && work[k-1]==qst)
// work[k-1]=0;
// if (c1)
// my_strtok_ptr = str++;
// else
// my_strtok_ptr = str;
/* cut spaces */
// while(k>0 && dest[k-1]==' ')
// k--;
// dest[k]=0;
return(work);
}
long my_csvtokL(char* str)
{
return PickSuziS( my_csvtok(str) );
}
■strtokStr
char* my_strtokStr(char* str, const char* del) //仮バージョン
{
int k;
char* q;
if (!str)
str = my_strtok_ptr;
while(InCha(del,strlen(del),*str)>=0)
str++;
if (*str==0)
{
my_strtok_del = 0;
my_strtok_ptr = str;
return(0);
}
if (*str==0x22)
{
str++;
for(q=str; *q!=0x22 && *q!=0;)
q++;
*q++=0;
my_strtok_ptr = q+1;
my_strtok_del = *q;
return(str);
}
for (q=str; *q; q++)
{
k = InCha(del, strlen(del), *q);
if (k>=0)
{
my_strtok_del = del[k];
my_strtok_ptr = q+1;
*q = 0;
return(str);
}
}
my_strtok_del = 0;
my_strtok_ptr = q;
return(str);
}
■septok
char* my_septok(char* str, char* del)
{
int k;
char* q;
if (!str)
str = my_strtok_ptr;
if (*str==0)
{
my_strtok_del = 0;
my_strtok_ptr = str;
return(0);
}
for (q=str; *q; q++)
{
k = InCha(del, strlen(del), *q);
if (k>=0)
{
my_strtok_del = del[k];
my_strtok_ptr = q+1;
*q = 0;
return(str);
}
}
my_strtok_del = 0;
my_strtok_ptr = q;
return(str);
}
long my_septokL(char* str, char* del)
{
return PickSuziS(my_septok(str, del));
}