C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

컴포넌트/라이브러리
Delphi/C++Builder Programming Components&Libraries
[429] 플렛폼 독립적인 심플 String, TStringList 클래스와 함수.
김태선 [jsdkts] 11181 읽음    2006-01-01 15:56
새해 기념으로 올립니다.
플렛폼 독립적인 심플 String , TStringList 클래스와 함수입니다.
모든 C++ 컴파일러에서 쓸수 있습니다.

#ifndef __BCSysClass
#define __BCSysClass

//---------------------------------------------------------------------------
// 시스템 유틸리티 클래스
// --------------------------------------------------------------------------
// 제작목적:
//        이미 익숙한 String 과 TStringList 등의 빌더 클래스와 함수를 이용하여 프로그램하고 싶은데,
//        지원되지 않은 환경에서 사용하기 위해 만듦.
//        또한, 기존 소스를 수정하는 노력을 취소로하여 옮기기 위해.
//        윈도우 환경에서 만든 기능을 순수도스용 프로그램으로 바꿀려니.. 거의 쓸수 있는 클래스/함수가 없어 허걱 했음. 그래서 만듦.
//
// 구현 클래스/함수:
//        AnsiString, String
//        TStringList
//      ExtractFileName
//        ExtractFilePath
//        FileExists
//
// Written by 김태성(jsdkts@korea.com), Open Source.
//
// 날짜       설명 (update history)
// --------------------------------------------------------------------------
// 2006-01-01 첫버전 제작. 메모리 누수없음. 더 필요한 기능은 추가해서 쓰세요. ^^;
//---------------------------------------------------------------------------
namespace BCSysClass
{

typedef char    byte;
#define ZeroMemory(a,b)        memset(a, 0, b)

// 순수 도스에서 사용하기 위한 String 클래스
//         원래 C++Builder에 있는 AnsiString을 순수 도스나 VC++에서 이용하기 위해 몇가지 기능만 구현함.
//        일부 동작이 표준 AnsiString과는 약간 틀리나 대략 비슷하게 사용할수 있음.

class    String
{
    enum { BUFFER_SIZE = 4097 };    // 4k 문자열 임시 버퍼.

private:
    char    *Data;

public:
    String()
    {
        Data = NULL;
    }
    String(char *str)
    {
        if (*str == 0 || str == NULL)
            Data = NULL;
        else
        {
            Data = new char[strlen(str)+1];
            strcpy(Data, str);
        }
    }
    String(String& str)
    {
        if (str.Length() == 0)
            Data = NULL;
        else
        {
            Data = new char[str.Length()+1];
            strcpy(Data, str.c_str());
        }
    }
    String(char ch, int len)    // 원래 AnsiString에는 없으나, 문자열공간 선확보 목적으로 신설.
    {
        if (len > 0)
        {
            Data = new char[len+1];
            memset(Data, ch, len+1);
        }
        else
            Data = NULL;
    }
    ~String()
    {
        if (Data)
        {
            delete[] Data; Data = NULL;
        }
    }
    int  Length()
    {
        if (Data == NULL) return 0;
        return strlen(Data);
    }
    char  *c_str()
    {
        return Data;
    }
    String&  operator=(char *str)
    {
        if (Data)
        {
            delete[] Data; Data = NULL;
        }
        if (strlen(str) > 0)
        {
            Data = new char[strlen(str) + 1];
            strcpy(Data, str);
        }
        return *this;
    }
    String&  operator=(String str)
    {
        if (Data)
        {
            delete[] Data; Data = NULL;
        }
        if (str.Length() > 0)
        {
            Data = new char[str.Length() + 1];
            strcpy(Data, str.c_str());
        }
        return *this;
    }
    String&  SubString(int pos, int len)
    {
        if (pos == 0) return *this;      // 위치 인덱스는 1부터
        String  *ps = new String(0, len);
        strncpy(ps->c_str(), Data + pos - 1, len);    // 끝에 자동초기화된 0가 있으므로.
        return *ps;
    }
    // String().sprintf("%d %s", a, b); 식으로도 사용가능하게 하기 위해.
    String&  sprintf(const char* format, ...)
    {
        char     buffer[BUFFER_SIZE];
        va_list  args;
        va_start(args, format);
        int  len = vsprintf(buffer, format, args);
        va_end(args);
        if (len == EOF)   
            len = 0;        // throw "vsprintf의 변환 에러"; 
        String  *ps = new String(0, len);
        strcpy(ps->c_str(), buffer);
        return  *ps;
    }
    int  printf(const char* format, ...)
    {
        char     buffer[BUFFER_SIZE];
        va_list  args;
        va_start(args, format);
        int  len = vsprintf(buffer, format, args);
        va_end(args);
        if (len == EOF)       
            return 0;
        if (Data)
        {
            delete Data; Data = NULL;
        }
        if (len > 0)
        {
            Data = new char[len + 1];
            strcpy(Data, buffer);
        }
        return len;
    }
};

typedef String        AnsiString;

// 순수 도스에서 사용하기 위해 TStringList를 간편하게 새롭게 만들었다.
//        원래 TObject를 상속한 VCL스타일 클래스이나 이것은 아무것도 상속하지 않았다.
//        간편하게 사용할 목적이므로 에러 체크를 안한다.

class    TStringList
{
    // MAX_LINE * 4 만큼 스트링 포인트 테이블로 소요.
    // 원래 한줄당 인스턴스용 메모리를 할당받아야 하나, 간편하게 구현하기 위해.
    enum { MAX_LINE = 10000 };

private:
    int        Max;

public:
    int        Count;
    String    *Strings;

public:
    TStringList(int max = MAX_LINE)
    {
        ZeroMemory(this, sizeof(*this));
        Max = max;
        Strings = new String[max];    // 생성자에서 자동 0로 모두 초기화된다.
    }
    ~TStringList()
    {
        delete[] Strings;
    }

    int  Add(String str)
    {
        if (Count + 1 >= Max)
            throw "TStringList 인덱스값 초과";    // over
        Strings[Count] = str;
        return  Count++;
    }
    void  Delete(int index)
    {
        if (index >= Count)
            return;
        if (Strings[index].Length() > 0)
            delete (Strings + index);
        memcpy(Strings + index, Strings + index + 1, sizeof(String) * (Max - index - 1));
        ZeroMemory(Strings + Max-1, sizeof(String));
        Count--;
    }
    String& operator[](int index)
    {
        return Strings[index];
    }
};


String    ExtractFilePath(String filename)
{
    int   len = filename.Length();
    char  *p = filename.c_str();
    for(int c = 0; c < len; c++)
    {
        char  ch = p[len-c-1];
        if (ch == '\\' || ch == ':')
        {
            return filename.SubString(1, len - c);
        }
    }
    return "";
}

String    ExtractFileName(String filename)
{
    int   len = filename.Length();
    char  *p = filename.c_str();
    for(int c = 0; c < len; c++)
    {
        char  ch = p[len-c-1];
        if (ch == '\\' || ch == ':')
        {
            String  name = (p + len - c);
            return  name;
        }
    }
    return filename;
}

bool    FileExists(String filename)
{
    FILE  *fp = fopen(filename.c_str(), "rb");
    bool  b = fp;
    if (fp)
        fclose(fp);
    return b;
}


}; // name space BCSysClass


#endif



사용할 때는
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <dir.h>

대략 이정도는  해주시고..

//---------------------------------------------------------------------------
// 유닛
//---------------------------------------------------------------------------
using namespace BCSysClass;

로 네임스페이스 참조를 해줘야 합니다.

일단, 제가 만든 도스 프로그램을 이 헤더만 포함해서 아무런 컨버팅없이 돌려보니, 잘 되는군요.
메모리 누수가 발생하는지 체크해봤는데 누수없이 잘 돌아갑니다.

너무 간단하게 만들었기 때문에, 구현하지 않은 기능이 많습니다.  필요한 기능을 추가하는 것은 별로 어려운 일이 아니라 생각됩니다.
혹시 모를 버그도 있을수 있으니 그건 리플을 달아주시면 좋겠습니다.
소스를 공개하므로 알아서 개선해 쓰셔도 좋을것 같군요.

참고로 원래 빌더에서 지원하는 String 클래스나 TStringList 등의 클래스는 콘솔프로그램에서도 사용할 수 있습니다.
하지만, 콘솔일뿐 win32 응용프로그램의 일부이며, 순수한 도스용 프로그램 제작을 지원하지 않습니다.
김태선 [jsdkts]   2006-01-03 01:47 X
TC++ 3.0 for DOS 에서 사용하려면,
파일명을 SysClass.h 로 고치고
namespace 는 제거하고
typedef int    bool;
enum { false, true };
를 해줘야 합니다. 오래된 C++ 규정이라서 제한이 좀 있습니다.

소스중에 bool b = fp 는
bool b = fp ? true: false;
로 조금 고쳐야 합니다.


+ -

관련 글 리스트
429 플렛폼 독립적인 심플 String, TStringList 클래스와 함수. 김태선 11181 2006/01/01
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.