// 텍스트에서 중복 공백이나 중복 개행 제거, 주석을 포함시키지 않고 순수 내용만 간결하게 남긴다.
// 길이가 줄어드므로 소스와 버프에 동일 주소를 지정해도 된다.
TCHAR * __stdcall ConsciseText(TCHAR *buf, const TCHAR *src)
{
TCHAR *p, *q;
p = (TCHAR *)src; // 소스 포인터
q = buf; // 버프 포인터
for (; ; )
{
if (!*p) // 문자열 맨 끝 널문자인 경우
{
if (q != buf) // ★ 논리상 버퍼 기록 여부를 먼저 판단해야 q[-1] 조건이 유효하다. 더 아래에서도 마찬가지로 조건문에서 가장 앞에 두어야 한다.
{
if (q[-1] == ' ') // 문자열-공백-널문자순인 경우 공백은 무의미하므로 1칸 앞으로 당긴다.
--q;
/* 마지막 개행을 제거하고자 할 때 주석 해제. 보통 편의상 마지막 개행은 남겨둔다.
if (q[-1] == '\n')
--q;
if (q[-1] == '\r') // 윈도우 시스템의 개행은 \r\n 2문자
--q;
*/
}
break;
}
if (*p == ' ' || *p == VK_TAB) // 공백인 경우
{
if (q == buf || q[-1] == ' ' || q[-1] == VK_TAB || q[-1] == '\n') // 버퍼 미기록 상태(처음부터 공백) 또는 이전이 공백, 개행이면 기록하지 않는다.
{
++p;
continue; // 더 아래로 진행하지 않고 건너뛴다.
}
// 탭을 스페이스로 바꾸는 경우. 탭을 그대로 유지하려면 아래 3줄을 주석처리한다.
*q++ = ' '; // 공백을 스페이스 하나로 일치
++p;
continue;
}
else if (*p == '\r' || *p == '\n') // 개행인 경우
{
if (q == buf || q[-1] == '\n') // 버퍼 미기록 상태(처음부터 개행) 또는 이전이 개행이면 기록하지 않는다.
{
if (*p == '\r') // 참고로 윈도우의 개행은 \r\n이고 유닉스 등은 \n이다.
p += 2;
else
++p;
continue;
}
if (q != buf && q[-1] == ' ') // 문자열-공백-개행순인 경우 공백은 무의미하므로 1칸 앞으로 당긴다.
--q;
}
else if (*p == '/') // 주석 표시 고려
{
if (p[1] == '/') // 주석이 //인 경우 개행 전까지 무시
{
for (p += 2; *p && !(*p == '\r' || *p == '\n'); ++p);
continue;
}
else if (p[1] == '*') // 주석이 /*인 경우 */까지 무시
{
for (p += 2; *p; ++p)
{
if (*p == '*' && p[1] == '/')
{
p += 2;
break;
}
}
continue;
}
}
*q++ = *p++;
}
*q = '\0';
return buf;
}