/*C# Timer.ElapsedEventHandler(tme_tick) 과 같은 효과(Linux)*/
/*C# Timer.ElapsedEventHandler(tme_tick) 과 같은 효과(Linux)*/

#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <stdio.h>
 
void time_tick()
{
    printf("timer\n");
}
 
int createTimer( timer_t *timerID, int sec, int msec )  
{  
    struct sigevent         te;  
    struct itimerspec       its;  
    struct sigaction        sa;  
    int                     sigNo = SIGRTMIN;  
   
    /* Set up signal handler. */  
    sa.sa_flags = SA_SIGINFO;  
    sa.sa_sigaction = time_tick;     // 타이머 호출시 호출할 함수 
    sigemptyset(&sa.sa_mask);  
  
    if (sigaction(sigNo, &sa, NULL) == -1)  
    {  
        printf("sigaction error\n");
        return -1;  
    }  
   
    /* Set and enable alarm */  
    te.sigev_notify = SIGEV_SIGNAL;  
    te.sigev_signo = sigNo;  
    te.sigev_value.sival_ptr = timerID;  
    timer_create(CLOCK_REALTIME, &te, timerID);  
   
    its.it_interval.tv_sec = sec;
    its.it_interval.tv_nsec = msec * 1000000;  
    its.it_value.tv_sec = sec;
    
    its.it_value.tv_nsec = msec * 1000000;
    timer_settime(*timerID, 0, &its, NULL);  
   
    return 0;  
}
 
int main()
{
    timer_t timerID;
    
    createTimer(&timerID,5, 0);
    
    while(1)
    {
        //,,
    }
}



/*Console.SetCursorPosition Method try & catch*/

class TrisClass
{
//definition empty ,,,,,
//variables empty ,,,,,
//controls empty ,,,,,
void draw()
{
string formattext="";
string succsign="{}';
string failsign="..";
int ii,kk,positionx=0,positiony=0;

now=DateTime.Now;
formattext="";
formattext=formattext+"Time:[" + now.ToString("yyyy-MM-dd HH:mm:ss") + "]";
try
{
Console.SetCursorPosition(positionx,positiony+0);
Console.Write(formattext);
}
catch(ArgumentOutOfRangeException e)
{
Console.Clear();
Console.WriteLine(e.Message);
}


for(ii=0; ii<MAPY-1; ii++)
{
formattext="";
for(kk=1; kk<MAPX-1; kk++)
{
if(tris[ii,kk] == 1) formattext=formattext+succsign;
else formattext=formattext+failsign;
}

try
{
Console.SetCursorPosition(positionx,positiony+2+ii);
Console.Write(formattext);
}
catch(ArgumentOutOfRangeException e)
{
Console.Clear();
Console.WriteLine(e.Message);
}
}

formattext="";
formattext=formattext+"Score:[" + score.ToString("0000") + "]";
try
{
Console.SetCursorPosition(positionx,positiony+0);
Console.Write(formattext);
}
catch(ArgumentOutOfRangeException e)
{
Console.Clear();
Console.WriteLine(e.Message);
}
}//end of method
}//end of class








/*ShowDialog호출시 SubForm에서 데이타 받기(set,get)*/
/*ShowDialog호출시 SubForm에서 데이타 받기(set,get)*/
/*ShowDialog호출시 SubForm에서 데이타 받기(set,get)*/

/*FILENAME:UAPCFGM0151.cs*/

public class UAPCFGM0151
{
public string __query_1 = string.Empty;
public string __query_2 = string.Empty;
public string __query_3 = string.Empty;

public string Query_1
{
get { return __query_1; }
set { __query_1 = value; }
}
public string Query_2
{
get { return __query_2; }
set { __query_2 = value; }
}
public string Query_3
{
get { return __query_3; }
set { __query_3 = value; }
}

            public void running()
{
Query_1 = string.Foramt(@"INSERT INTO IMT_MST_LOGFILE({0},'{1}','{2}','{3}')",
itemIDInsertOnlyTxt.Text, filePath.Text, filePath.Text, filePath.Text);

Query_2 = string.Foramt(@"INSERT INTO IMT_MST_LOGFILE({0},'{1}','{2}','{3}')",
itemIDInsertOnlyTxt.Text, filePath.Text, filePath.Text, filePath.Text);

Query_3 = string.Foramt(@"INSERT INTO IMT_MST_LOGFILE({0},'{1}','{2}','{3}')",
itemIDInsertOnlyTxt.Text, filePath.Text, filePath.Text, filePath.Text);
}
}

/*FILENAME:UAPCFGM0150.cs*/

public class UAPCFGM0150
{
public static void Main()
{
UAPCFGM0151 subForm = new UAPCFGM0151();

if(subForm.ShowDialog() == DialogResult.OK)
{
MessageBox.Show(subForm.Query_1.ToString());
MessageBox.Show(subForm.Query_2.ToString());
MessageBox.Show(subForm.Query_3.ToString());
}
}
}



/*C#에서 Null과 Empty String 차이*/
/*C#에서 <Null String>과 <Empty String> 차이*/

1. string에 null 이거나 ''" (Empty String)일때, 처리하지 않게 하려면, string.IsNullOrEmpty()를 사용하면 됩니다.

if (!string.IsNullOrEmpty(row["TIP_ADJUST"].ToString()))
{
     _tip_adjust_total += Convert.ToDecimal(row["TIP_ADJUST"]);
}

2. C#에서 Null과 Empty String 차이

2.1. Empty String 
string s = ""; //System.String 객체에  zero문자만을 가진것.
int len = s.Length;; // Number -> 0

2.2. Null String
string s = null; 
int len = s.Length;; // NullReferenceExcption 발생(throw).

Tip) if(s==null) s="";
Tip) if(s==null) s="";
Tip) if(s==null) s="";

3. C#의 null 체크하기
string str =null ;
if (str == null) MessageBox.Show("String is null");

4. C#에서 null 또는 string.Empty 체크하기
string str =null;
if (string.IsNullOrEmpty(str)) MessageBox.Show("String is empty or null");

5. Example

class Program
{
public static void Main()
{
StringExCls nm = new StringExCls();
nm.running1();
nm.running2();
}
}
class StringExCls
{
public void running1()
{
    string tmp=null;  //NULL

    if(string.IsNullOrEmpty(tmp))
    {
        if(tmp==null)
        {
            Console.WriteLine("NULL");
            //tmp.Length call -> NullReferenceException !!!!!!!!
            //tmp.Length call -> NullReferenceException !!!!!!!!
            //tmp.Length call -> NullReferenceException !!!!!!!!
        }
        else
        {
            Console.WriteLine("Empty");
            Console.WriteLine("Empty,Length:" + tmp.Length);
        }
    }
}
public void running2()
{
    string tmp="";   //Empty

    if(string.IsNullOrEmpty(tmp)) 
    {
        if(tmp==null)
        {
            Console.WriteLine("NULL");
        }
        else
        {
            Console.WriteLine("Empty");
            Console.WriteLine("Empty,Length:" + tmp.Length);
        }
    }
}
}

/*
 * 가비지 컬렉션 (Garbage Collection)
 */
가비지 컬렉터는 Mark & Compact 알고리즘을 이용하여 객체들의 관계를 추척한다. 
즉, 인스턴스화 시켯던 DataSet에 Null을 할당하면 DataSet은 사용하지 않은 객체로 간주되고 가바지 컬렉션시에 메모리 해제의 대상이 된다.

1. 
C 또는 C++ 언어로 프로그래밍을 하다보면 자주 사용하는 힙영역에 대한 메모리 해제때문에 머리 아픈 경우가 많았습니다.
하지만 C#에서는 가비지 컬렉터(Garbage Collector) 덕분에 아주 편하게 프로그래밍을 할 수 있게 됐습니다.
물론 C/C++ 프로그래밍에서 정확하고 안정적으로 코드를 짤 수 있다면 메모리를 효율적으로 사용할 때만 사용하고 
버리고 싶을 때는 제거할 수 있겠지만, 사람인 이상 실수를 할 수 밖에 없습니다. 
더군다나 프로그램이 커질수록 혼자만 코딩을 하는게 아니기 때문에 어쩔 수 없는 문제입니다. 
또, C/C++ 기반의 프로그램을 실행하는 C-runtime 은 힙에 객체를 할당하기 위해 비싼 비용을 치르는 문제
(메모리를 할당하기 위해 순차적으로 탐색하면서 객체를 담을만한 메모리 블록을 찾고, 메모리를 쪼개고, 메모리 블록의 리스트를 재조정하는; 탐색,분할,재조정의 오버헤드)를 가지고 있습니다.

2.
C#에서는 가비지컬렉터가 사용하지 않는 객체를 알아서 판단하여 메모리를 회수합니다. 
하지만, 가비지 컬렉터도 소프트웨어이기 때문에 CPU와 메모리를 사용합니다. 
따라서 가바지 컬럭테가 최소한으로 자원을 사용하게 하는 것도 프로그램의 성능을 높이는 방법입니다. 
그래서 가비지 컬렉션의 메커니즘을 이해하고, 이를 바탕으로 어떻게 코딩지침을 세울 것인가를 정리하고자 합니다.

3.
가비지 컬렉션 메커니즘
C#으로 작성한 프로그램을 실행하면 CLR은 프로그램을 위한 일정 크기의 메모리를 확보합니다. 
C-runtime 처럼 메모리를 쪼개는 일을 하지 않고 그냥 일정 메모리 공간을 확보해서 하나의 관리되는 힙(Managed Heap)을 마련합니다.
객체를 할당하게 되면 메모리에 순서대로 할당하게 됩니다. 
(CLR은 객체가 위치할 메모리를 할당하기 위해 공간을 쪼개만든 리스트를 탐색하는 시간도 소요하지 않고, 공간을 나눈 뒤에 리스트를 재조정하는 작업도 하지 않습니다)

4.
참조 형식의 객체가 할당될 때는 스택 영역에는 힙의 메모리 주소를, 힙 영역에 실제 값이 할당된다고 했습니다.
그럼 객체가 할당된 코드블록이 끝나면 스택 영역의 메모리가 회수되고, 힙 영역에 값이 쓰레기가 됩니다.
여기서 회수된 스택의 객체를 루트(Root) 라고 부릅니다.
.NET 응용 프로그램이 실행되면 JIT 컴파일러가 이 루트들을 목록으로 만들고 CLR은 이 루트 목록을 관리하며 상태를 갱신하게 됩니다.
방법은 다음과 같습니다.

가비지 컬렉터는 힙영역의 임계치에 다다르게 되면
4.1. 모든 객체가 쓰레기라고 가정합니다.( 루트 목록 내의 어떤 루트도 메모리를 가리키지 않는다고 가정)
4.2. 루트 목록을 순회하면서 참조하고 있는 힙 객체와의 관계 여부를 조사합니다. 즉 어떤 루트와도 관계가 없는 힙의 객체들은 쓰레기로 간주됩니다.
4.3. 쓰레기가 차지하고 있던 메모리가 회수되면, 인접 객체들을 이동시켜 차곡차곡 채워서 정리합니다.

5.
CLR의 메모리도 구역을 나누어 메모리에서 빨리 해제될 객체와 오래 있을 것 같은 객체를 따로 담아 관리합니다.
구체적으로 CLR은 메모리를 0세대, 1세대, 2세대 3가지로 분리하고, 0세대는 빨리 사라질 객체, 2세대는 오래 남아있을 것 같은 객체들을 위치시킵니다.

그 방법은 다음과 같습니다.
응용 프로그램을 실행하면 0세대부터 할당된 객체들이 차오르기 시작합니다.

5.1. 0세대 가비지 컬렉션 임계치에 도달하면 0세대에 대해 가비지 컬렉션을 수행합니다. 여기서 살아남은 객체는 1세대로 옮겨집니다. 
5.2. 1번과정을 계속 반복하다보면, 1세대 가비지 컬렉션이 임계치에 도달하게 되고, 1세대에 대해 가비지 컬렉션을 수행합니다. 
여기서 살아남은 객체는 다시 2세대로 옮겨집니다.
5.3. 2번과정도 지속되다보면 2세대 가비지 컬렉션이 임계치에 도달합니다.
2세대 가비지컬렉션이 임계치에 도달하면 0,1,2 세대 전체 가비지컬렉션 (Full Garbage Collection) 을 수행합니다. 

프로그램이 오래 살아남는 개체들을 마구 생성하면, 2세대 힙이 가득차게 될 것입니다.
2세대 힙이 가득차게 되면 CLR은 응용프로그램의 실행을 멈추고 전체 가비지 컬렉션을 수행하면서 메모리를 확보하려 하기 때문에 응용 프로그램이 차지하는 메모리가 많을 수록 프로그램이 정지하는 시간도 그만큼 늘어나게 됩니다.

 
6.
>>>코딩지침
가비지 컬렉션의 메커니즘을 바탕으로 효율적인 코드를 작성하기 위한 방법이 있습니다.

6.1 객체를 너무 많이 할당하지 마세요.
6.2 너무 큰 객체 할당을 피하세요.
6.3 너무 복잡한 참조 관계는 만들지 마세요.
6.4 루트를 너무 많이 만들지 마세요.
6.5 객체를 너무 많이 할당하지마세요.

객체 할당 코드를 작성할 때 꼭 필요한 객체인지 필요 이상으로 많은 객체를 생성하지 않는지 고려하라는 말입니다.
너무 큰 객체 할당을 피하세요.
CLR은 85KB 이상의 대형 객체를 할당하기 위한 대형 객체 힙 (Large Object Heap ; LOH) 을 따로 유지하고 있습니다.
대형 객체가 0세대에 할당하면 가비지 컬렉션을 보다 자주 수행하기 때문입니다.
대형 객체 힙은 객체의 크기를 계산한 뒤 여유공간이 있는지 힙을 탐색하여 할당합니다. 또한, 대형 객체 힙은 해제된 공간을 인접 객체가 채우는 것이 아니라 그대로 둡니다. 대형 객체를 복사하여 옮기는 비용이 너무 비싸기 때문입니다. 이로 인해 큰 공간 사이사이가 메모리를 낭비하게 됩니다. (C-runtime 방식의 문제점과 비슷합니다)

너무 복잡한 참조관계는 만들지 마세요.
참조 관계가 많은 객체는 가비지 컬렉션 후에 살아남아 있을 때가 문제입니다. 살아 남은 객체는 세대를 옮기기 위해 메모리 복사를 진행하는데, 참조 관계가 복잡할 경우 객체를 구성하고 있는 각 필드 객체간의 참조관계를 조사하여 메모리 주소를 전부 수정해야 되기 때문에 탐색과 수정의 오버헤드가 발생합니다. 또한 A객체가 2세대인데 A 객체안에 B객체를 이제막 생성하여 0세대로 되었다면, A의 인스턴스는 2세대에 있고 B 필드를 참조하는 메모리는 0세대에 위치하게 됩니다. 이때 0세대 가비지 컬렉션이 수행된다면 B필드가 수거될 수 있습니다. 하지만 CLR은 쓰기 장벽(Write barrier)이라는 장치를 통해서 B필드가 루트를 갖고 있는 것으로 간주하게 해서 수거 되지 못하게 합니다. 이 쓰기 장벽을 생성하는 데 오버헤드가 크다는 것이 문제가 됩니다.
루트를 너무 많이 만들지 마세요.
가비지 컬렉터는 루트 목록을 돌면서 쓰레기를 수거하기 때문에 적을 수록 성능에 유리합니다.


가비지 컬렉션에 대해 정리해보았습니다.

/*TimeSpan structure(구조체)*/

class Program
{
    public static void Main()
    {
        TrisCls nm=new TrisCls();
        nm.running();
    }
}
class TrisCls
{
    //properties
    Timer tm;
    DateTime now,startdate,enddate;
    TimeSpan dateDiff;
    int diff_day,diff_hour,diff_minute,diff_second;

    public void running()
    {
        tm=new Timer();
        tm.Elapsed += new ElapsedEventHandler(____time_tick);
        tm.Interval = 500;
        tm.Start();

        now = DateTime.Now;
        startdate = Convert.ToDateTime(now.ToString("yyyy-MM-dd HH:mm:ss"));

        while(true)
        {
            keyinfo = Console.ReadKey(true);

            if(keyinfo.Key==ConsoleKey.Escape) break;
        }

        tm.Stop();
        tm.Elapsed -= ____time_tick;
    }
    void ____time_tick(object sender, ElapsedEventArgs e)
    {
        now = DateTime.Now;
        enddate=Convert.ToDateTime(now.ToString("yyyy-MM-dd HH:mm:ss"));

        dateDiff = enddate - startdate;

        diff_day = dateDiff.Days;
        diff_hour = dateDiff.Hours;
        diff_minute = dateDiff.Minutes;
        diff_second = dateDiff.Seconds;

        log("Time");
    }
    void log(string msg)
    {
        Console.WriteLine("Event:[" msg + "]" + ">>>>"
                       + diff_day + "/" + diff_hour + "/" + diff_minute + "/" + diff_scond);
    }
}

웹 정의 자바는 동시적이고, 클래스 기반이며, 객체 지향적이며 가능한 한 구현 종속성을 최소화하도록 특별히 고안된 컴퓨터 프로그래밍 언어입니다. .NET Framework는 주로 Microsoft Windows에서 실행되는 Microsoft에서 개발 한 소프트웨어 프레임 워크입니다. 대규모 라이브러리가 포함되어 있으며 여러 프로그래밍 언어에서 언어 상호 운용성을 제공합니다.
발명가 오라클 및 Sun Microsystem 마이크로 소프트
지원 Java는 Java 단순 코드 및 프로그래밍 패턴 만 지원합니다. .NET은 여러 언어, Visual Basic 및 C #을 지원하는 런타임 프레임 워크입니다.
실행 Java는 플랫폼에 독립적입니다. 즉, Windows, Mac 및 Linux를 비롯한 여러 운영 체제에서 실행됩니다. .NET은 주로 Windows 용입니다.
가상 머신  JVM (Java Virtual Machine)은 바이트 코드를 기계어 코드로 변환합니다. Microsoft의 가상 머신은 바이트 코드를 기계 코드로 변환합니다.
중요 구성 요소 JVM, JRE, JDK, Java 애플릿, Java 스크립트 및 스윙으로 구성됩니다. CLR (Common Language Runtime), 가상 시스템 및 다양한 응용 프로그램 바이너리 라이브러리로 구성된 .NET 프레임 워크로 구성됩니다.
쓰레기 청소 시설 자바는 좋은 쓰레기 청소 시설을 제공합니다. 가비지 클리닝 기능은 Java에 비해 .NET에서 그리 효율적이지 않습니다.
추가 기능 Java에서 사용할 수있는 추가 기능은 없습니다. .Net에서는 표준 개발 IDE (Microsoft Visual Studio)를 사용할 수 있습니다.
버전 JDK 알파 및 베타

JDK 1.0

JDK 1.1

J2SE 1.2

J2SE 1.3
.NET Framework 1.0

.NET Framework 1.1

.NET Framework 2.0

.NET Framework 3.0

.NET Framework 3.5
파일 확장자 자바, .java, .jad, .jar, .jsp, .class .asax, .ascx, .ashx, .asmx, .aspx

/*
 * Console에서 DLL생성과 DLL을 이용해서 실행파일 만들기
 */

/*
#DLL Creation
prompt>csc.exe /target:library TrisPackage.cs
prompt>csc.exe /target:library TrisPackage.cs
prompt>csc.exe /target:library TrisPackage.cs
prompt>csc.exe /target:library TrisPackage.cs
prompt>csc.exe /target:library TrisPackage.cs

prompt>dir
TrisPackage.cs
TrisPackage.dll

#EXE Creation reference by DLL File
prompt>csc.exe /out:example.exe /referece:TrisPackage.dll example.cs
prompt>csc.exe /out:example.exe /referece:TrisPackage.dll example.cs
prompt>csc.exe /out:example.exe /referece:TrisPackage.dll example.cs
prompt>csc.exe /out:example.exe /referece:TrisPackage.dll example.cs
prompt>csc.exe /out:example.exe /referece:TrisPackage.dll example.cs
*/

/*FILENAME:example.cs*/
using TrisPackage.Tris;

class Program
{
    public static void Main(string[] args)
    {
        TrisCls nm = new TrisCls();
        nm.running();
    }
}



/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
FILENAME:TrisProblem.java
Compile:javac TrisProblem.java
Execution: java TrisProblem.class
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*/
package Tris.TrisPackage

/*--------------------------------------------------------------------*/
import java.io.Console;
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
class TrisProblem
{
public static void main(String[] args) 
{
//System.out.println("Hello World!");
TrisCls nm = new TrisCls();
nm.running();
}
}

/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
class TrisCls
{
//definition
final int MAPY=22;
final int MAPX=40;
final int MAXDESIGN=10;
final int ARR=3;
final int D_RRIGHT=1000;
final int D_LEFT=1002;
final int D_DOWN=1003;
final int TRUE=1;
final int FAIL=0;

//variables
int[][] tris = new int[MAPY][MAPX];
int[][] design = new int[ARR][ARR];
int xpos,ypos,score;
int hyun,next;

//int[][][] realdesign = new int[MAXDESIGN][ARR][ARR];
int[][][] realdesign =
{
{{1,1,1},{1,1,1},{1,1,1}},
{{1,1,1},{1,1,1},{1,1,1}},
{{1,1,1},{1,1,1},{1,1,1}},
{{1,1,1},{1,1,1},{1,1,1}},
{{1,1,1},{1,1,1},{1,1,1}},
{{1,1,1},{1,1,1},{1,1,1}},
{{1,1,1},{1,1,1},{1,1,1}},
{{1,1,1},{1,1,1},{1,1,1}},
{{1,1,1},{1,1,1},{1,1,1}},
{{1,1,1},{1,1,1},{1,1,1}}
};
//control

//method
public void running()
{
//
}
}
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/

/*정적 클래스 및 정적 클래스 멤버
정적 클래스 및 정적 클래스 멤버(C# 프로그래밍 가이드)*/

정적 클래스는 기본적으로 비정적 클래스와 동일하지만, 
정적 클래스는 인스턴스화할 수 없다는 한 가지 차이점이 있습니다. 
즉, new 연산자를 사용하여 클래스 형식의 변수를 만들 수 없습니다. 
인스턴스 변수가 없기 때문에 클래스 이름 자체를 사용하여 정적 클래스의 멤버에 액세스합니다. 
예를 들어 public static 메서드 MethodA를 포함하는 UtilityClass라는 정적 클래스가 있는 경우 
다음 예제와 같이 메서드를 호출합니다.

UtilityClass.MethodA();  

정적 클래스는 입력 매개 변수에 대해서만 작동하고 
내부 인스턴스 필드를 가져오거나 설정할 필요가 없는 메서드 집합에 대한 편리한 컨테이너로 사용할 수 있습니다. 
예를 들어 .NET 클래스 라이브러리의 정적 System.Math 클래스에는 
Math 클래스의 특정 인스턴스에 고유한 데이터를 저장하거나 검색할 필요 없이 수학 연산을 수행하는 메서드가 포함되어 있습니다. 
즉, 다음 예제와 같이 클래스 이름과 메서드 이름을 지정하여 클래스의 멤버를 적용합니다.

double dub = -3.14;  
Console.WriteLine(Math.Abs(dub));  
Console.WriteLine(Math.Floor(dub));  
Console.WriteLine(Math.Round(Math.Abs(dub)));  
  
// Output:  
// 3.14  
// -4  
// 3  

모든 클래스 형식과 마찬가지로, 
정적 클래스에 대한 형식 정보는 클래스를 참조하는 프로그램이 로드될 때 .NET 런타임에 의해 로드됩니다. 
프로그램에서 클래스가 로드되는 시기를 정확하게 지정할 수는 없습니다. 
그러나 클래스가 로드되도록 하고, 
프로그램에서 클래스를 처음으로 참조하기 전에 해당 필드가 초기화되고 정적 생성자가 호출되도록 합니다. 
정적 생성자는 한 번만 호출되며, 
프로그램이 있는 애플리케이션 도메인의 수명 동안 정적 클래스가 메모리에 유지됩니다.

>참고
자체 인스턴스 하나만 생성될 수 있도록 하는 비정적 클래스를 만들려면 C#에서 Singleton 구현을 참조하세요.

다음 목록은 정적 클래스의 주요 기능을 제공합니다.
1. 정적 멤버만 포함합니다.
2. 인스턴스화할 수 없습니다.
3. 봉인되어 있습니다.
4. 인스턴스 생성자를 포함할 수 없습니다.

따라서 정적 클래스를 만드는 것은 기본적으로 정적 멤버와 private 생성자만 포함된 클래스를 만드는 것과 동일합니다. 
private 생성자는 클래스가 인스턴스화되지 않도록 합니다. 
정적 클래스를 사용하면 컴파일러에서 인스턴스 멤버가 실수로 추가되지 않도록 확인할 수 있다는 장점이 있습니다. 
컴파일러는 이 클래스의 인스턴스를 만들 수 없도록 합니다.

정적 클래스는 봉인되므로 상속할 수 없습니다. 
Object를 제외하고 어떤 클래스에서도 상속할 수 없습니다. 
정적 클래스는 인스턴스 생성자를 포함할 수 없습니다. 
그러나 정적 생성자는 포함할 수 있습니다. 
또한 클래스에 특수한 초기화가 필요한 정적 멤버가 포함된 경우 비정적 클래스에서 정적 생성자도 정의해야 합니다. 
자세한 내용은 정적 생성자를 참조하세요.

this 키워드

this 키워드는 객체가 자기 자신을 가리키고 싶을때 사용하는 키워드입니다.
객체외부에서는 객체의 변수나 메소드에 접근할떄는 객체의 이름을 사용한다면, 
객체내부에서는, 자신의 변수나 메소드에 접근할때, this 키워드를 사용합니다.

class Student
{
    private string name;

    public void SetName(string name)
    {
        this.name = name;
    }
}

/*객체의 이해와 객체의 생성필요와 생성이 필요없는경우*/

객체(Object)

객체란 사물과 같은 유형적인것뿐만 아니라, 개념이나 논리와 같은 무형적인 것들을 객체라고
합니다. 프로그래밍에서의 객체는 클래스에 정의된 내용이 메모리에 생성된것을 뜻합니다.
클래스로부터 객체를 만드는과정을 인스턴스화라고 하고, 어떤 클래스로부터 만들어진 객체를
그 클래스의 인스턴스(Instance)라고 합니다.

>객체생성하기
객체를 생성할때는 new 연산자를 사용하면 됩니다. new연산자가 하는 역할은 객체를 생성하고
생성자를 호출하는데 사용됩니다.

---------------------------------------------------------------------------------------------------------
Timer 클래스(new를 통해서 생성)

정의
네임스페이스: System.Timers
어셈블리: System.ComponentModel.TypeConverter.dll
반복 이벤트를 생성하는 옵션으로 설정된 간격 후 이벤트를 생성합니다.

public class Timer : System.ComponentModel.Component, System.ComponentModel.ISupportInitialize
상속 Object -> MarshalByRefObject -> Component -> Timer
---------------------------------------------------------------------------------------------------------

DateTime 구조체(new를 통해서 생성할 필요가 없다)
정의
네임스페이스: System
어셈블리: mscorlib.dll, System.Runtime.dll
일반적으로 날짜와 시간으로 표시된 시간을 나타냅니다.
public struct DateTime : IComparable, IComparable<DateTime>, IConvertible, IEquatable<DateTime>, IFormattable, System.Runtime.Serialization.ISerializable
상속 Object -> ValueType -> DateTime
---------------------------------------------------------------------------------------------------------

ConsoleKeyInfo 구조체(new를 통해서 생성할 필요가 없다)

정의
네임스페이스: System
어셈블리: System.Console.dll
콘솔 키로 표현된 문자와 Shift, Alt 및 Ctrl 보조키의 상태를 포함하여 누른 콘솔 키를 설명합니다.
public struct ConsoleKeyInfo : IEquatable<ConsoleKeyInfo>
상속 Object -> ValueType -> ConsoleKeyInfo

using System;

class Example
{
   public static void Main()
   {
      ConsoleKeyInfo cki; //new 사용하지 않음, 객체생성하지 않아도 사용할수 있는 경우. 이른바 구조체(?)
      // Prevent example from ending if CTL+C is pressed.
      Console.TreatControlCAsInput = true;

      Console.WriteLine("Press any combination of CTL, ALT, and SHIFT, and a console key.");
      Console.WriteLine("Press the Escape (Esc) key to quit: \n");
      do
      {
         cki = Console.ReadKey();
         Console.Write(" --- You pressed ");
         if((cki.Modifiers & ConsoleModifiers.Alt) != 0) Console.Write("ALT+");
         if((cki.Modifiers & ConsoleModifiers.Shift) != 0) Console.Write("SHIFT+");
         if((cki.Modifiers & ConsoleModifiers.Control) != 0) Console.Write("CTL+");
         Console.WriteLine(cki.Key.ToString());
       } while (cki.Key != ConsoleKey.Escape);
    }
}
// This example displays output similar to the following:
//       Press any combination of CTL, ALT, and SHIFT, and a console key.
//       Press the Escape (Esc) key to quit:
//
//       a --- You pressed A
//       k --- You pressed ALT+K
//       ► --- You pressed CTL+P
//         --- You pressed RightArrow
//       R --- You pressed SHIFT+R
//                --- You pressed CTL+I
//       j --- You pressed ALT+J
//       O --- You pressed SHIFT+O
//       § --- You pressed CTL+U

---------------------------------------------------------------------------------------------------------

 

/*3 * 3 배열로 된 테트리스 모양 회전시키기
 *스페이스바를 누르면, 90도씩 회전하는 로직*/

class Program
{
    public static void Main()
    {
        TrisCls nm = new TrisCls();
        nm.running();
    }
}
class TrisCls
{
    //desinition & variables
    const int ARR=3;
    int[,] design = new int[,]
    {
        {0,0,1},
        {1,1,1}, 
        {0,0,1}
    }
    //control
    ConsoleKeyInfo keyinfo;

    public void running()
    {
        int rc;
        while(true)
        {
            keyinfo=Console.ReadKey(true);
            if(keyinfo.Key==ConsoleKey.Escape) break;
            if(keyinfo.Key==ConsoleKey.Spacebar) 
            {
                rc=design_rotation();
                rc=design_rotation();
            }

            draw();
        }
    }
    int design_rotation()
    {
        int tmp;

        tmp = design[0,0];
        design[0,0]=design[0,1];
        design[0,1]=design[0,2];
        design[0,2]=design[1,2];
        design[1,2]=design[2,2];
        design[2,2]=design[2,1];
        design[2,1]=design[2,0];
        design[2,0]=design[1,0];
        design[1,0]=tmp;

        return(1);
    }
    void draw()
    {
        string text="";
        int ii,kk;

        for(ii=0; ii<ARR; ii++)
        {
            for(kk=0; kk<ARR; kk++)
            {
                if(design[ii,kk]==1) text=text+"U";
                else text=text+"_";
            }
            text=text+"\n";
        }
        Console.Write(text);
    }
}



        

#솔류션 + 프로젝트 다수일경우 참조방법

하나의 솔류션에 여러개의 프로젝트 단위로 나누어서 프로그램을 구성하는경우에
DLL파일 참조시에, 프로젝트 단위별로 DLL참조를 해야한다.

프로젝트(1) -> 속성(R) -> 참조경로(1)

프로젝트(1) -> 속성(R) -> 참조경로(2) ex>C:\Program Files\ComponetOne\Studio for WinForms\bin\v4\

위의 이미지에서, 참조경로에 추가를 해주면 됩니다.

C1 배포 & Deploy

컴포넌트원(ComponentOne)를 배포하는 방법에 대한 설명입니다.

배포가 될 때 사용중인 아래의 DLL이 같이 배포된 프로그램의 같은 경로에 포함되어야 합니다.

  • C1.Win.2.dll
  • C1.Win.컨트롤 이름.2.dll/C1.C1 컨트롤 이름.2.dll
  • C1.Win.4.dll
  • C1.Win. 컨트롤 이름.4.dll/C1.C1 컨트롤 이름.4.dll
  • C1.Win. 컨트롤 이름.4.Design.dll/C1.C1 컨트롤 이름.4.Design.dll

DLL에 붙어 있는 숫자 2와 4는 기본적으로 .NET 프레임 워크와 호환성을 나타내며 해당 DLL이 다양한 타입의 호환성을 가지기 때문에 현재는 문제가 되지 않더라도 장래적인 호환성을 위하여 배포하실 때는 2가지 버전의 DLL을 모두 배포하여야 합니다.

예를 들어 C1.Win.FlexGrid.2.dll와 C1.Win.FlexGrid.4.dll을 모두 배포하여야 합니다.

C1.C1Excel.4.5.2 Assembly / C1.C1Excel Namespace

 

C1.C1Excel Namespace | ComponentOne Excel for .NET

 

www.grapecity.com




Class                    Description

  C1XLBook Represents an Excel workbook containing one or more worksheets.
Contains methods for loading and saving XLS files, and exposes a collection of XLSheet objects that represent the individual worksheets.
  ShapeCollection Represents a collection of XLShape objects on an XLSheet.
  Strings Static class containing UI strings used by the designer.
  XLBorderFormatting The border formatting.
  XLCell Represents individual cells in an XLSheet and provides properties for getting and setting the cell Value, Style, and Hyperlink.
  XLCellRange Represents a range of XLCell objects in an XLSheet.
  XLCellRangeCollection Represents a collection of XLCellRange objects on an XLSheet.
  XLColumn Represents a column in a worksheet. This class provides properties for setting the column's width, style, and visibility.

/*

31 characters

Microsoft Excel does not allow worksheet name longer than 31 characters.

*/

/*

Excel Worksheet Naming Rules and Tips
► A worksheet name cannot cannot exceed 31 characters. ► A worksheet name cannot be left blank. ► A worksheet cannot be named history in either lower or uppercase.

*/

 

using C1.C1Excel;

 

namespace Problem

{

    class Program

    {

        public static void Main(string[] args)

        {

            Problem_2021_10_15 nm = new Problem_2021_10_15();

            nm.running();

        }

    }

    class Problem_2021_10_15

    {

        public void running()

        {

            C1XLBook book = new C1XLBook();

            XLSheet sheet = book.Sheets[0];

            sheet.Name="1234567890123456789012345678901";
            //Microsoft Excel does not allow worksheet name longer than 31 characters.

            XLStyle style = new XLStyle();

            style.AlignHorz = XLAlignHorzEnum.Center;

            XLCell cell = sheet[1,0];

            cell.Value="1234567890123456789012345678901";
            //Microsoft Excel does not allow worksheet name longer than 31 characters.

        }

    }

}

/*
 * C# Excel 연동(엑셀 COM 레퍼런스 추가하기)
 */

엑셀 COM 레퍼런스 추가하기

1. 개체추가
일단 C# 에서 엑셀 연동을 하기 위하여는 참조 개체를 추가해야 합니다.
상단 메뉴의 "프로젝트" -> "참조" 로 이동하신 다음 아래와 같은 항목을 찾아서 체크해 줍니다.

앞쪽의 체크박스를 선택해주고 확인 버튼을 눌러주면 된다.

2. 선언
확인을 누르셨으면 이제 해당 레퍼런스를 사용하도록 선언을 해줍니다.

코드 페이지의 제일 윗 부분에 아래와 같이 작성을 해 주겠습니다.

using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using Application = Microsoft.Office.Interop.Excel.Application;

두번째 추가한 구문은 현재 열려있는 엑셀 어플리케이션을 확인하기 위한 용도로 사용합니다.

세번쨰 구문은 이후 사용할 Application 이라는 지시어가 현재 C# 컴파일러가 헷깔릴수 있는 용어이기 때문에 특별히 어떤 녀석인지를 지시하도록 작성하였습니다.

3. 코드작성
이제 사용할 준비는 되었고 코드를 작성해 보겠습니다.

아래와 같이 작성이 되면 됩니다. 본인의 비주얼 스튜디오에 복붙 하지 마시고 한번 타이핑 해보시기 바랍니다. 코딩의 재미중에 타이핑 하는 맛도 빼 놓을 수 없기 때문이며 직접 타이핑을 해보는게 좀더 빠르게 익숙해 지기 때문이기도 하죠. 물론 인텔리센스가 도와주기 때문에 사실 몇글자 씩만 적어도 아래에 적어야 될 코드들이 자동으로 나타나서 저처럼 영문 타이핑을 못하는 사람도 쉽게 코딩을 할 수 있습니다.

한번 코드를 보실까요? 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using Application = Microsoft.Office.Interop.Excel.Application;

namespace excelAutomate
{
    public partial class Form1 : Form
    {
        private Application xlsApp;


        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 폼 로딩시에 위에서 정의한 xls App 를 엑셀과 연동해 주겠습니다.
            xlsApp = (Application)Marshal.GetActiveObject("Excel.Application"); // 현재  열려있는 엑셀 어플리케이션이 지정됩니다.
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // 버튼을 누르면 텍스트 박스에 엑셀 어플리케이션이 열고 있는 엑셀 파일 명을 표시해 보겠습니다.
            textBox1.Text = xlsApp.ActiveWorkbook.Name;
        }
    }
}

 

 

문제 1

문제 풀이 : Lv1. 숫자 문자열과 영단어

  • 1478 → “one4seveneight”
  • 234567 → “23four5six7”
  • 10203 → “1zerotwozero3”

네오와 프로도가 위와 같이 숫자를 문자열로 바꾸는 게임을 하고 있습니다. 이때 일부 자릿수가 영단어로 바뀌었거나 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어질 때, s가 의미하는 원래 숫자를 return 하는 함수를 완성해 주세요.

제한사항

  • 1 ≤ s의 길이 ≤ 50
  • s가 “zero” 또는 “0”으로 시작하는 경우는 주어지지 않습니다.
  • return 값이 1 이상 2,000,000,000 이하의 정수가 되는 올바른 입력만 s로 주어집니다.

입출력 예

"one4seveneight" 1478
"23four5six7" 234567
"2three45sixseven" 234567
"123" 123

 

 

 

using System;
using System.IO;
using System.Timers;

namespace ProblemPackage
{
    class Program
    {
        public static void Main(string[] args)
        {
            Tris_2021_10_15 nm = new Tris_2021_10_15();

            if(args.Length == 1)
            {
                nm.running(args[0]);
            }
            else
            {
                nm.running("23four5six7");
                nm.running("one4seveneight");
            }
        }
    }
    class Tris_2021_10_15
    {
        string[] english = new string[]
        {
            "zero",
            "one",
            "two",
            "three",
            "four",
            "five",
            "six",
            "seven",
            "eight",
            "nine"
        };
        string[] numeric = new string[]
        {
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6",
            "7",
            "8",
            "9"
        };
        const int TRUE=1;
        const int FAIL=0;

        public void running(string text)
        {
            string[] result = new string[100];
            string tmp;
            int kk,ii,ff;

            Console.WriteLine("Problem String------------------------------------------------");
            Console.WriteLine("[" + text + "]");

            kk=0;
            ii=0;
            while(true)
            {
                if(search_string(text)==TRUE)
                {
                    result[kk]=get_string(text);

                    ff=text.Length-result[kk].Length;
                    tmp = text.Substring(result[kk].Length,ff);
                    text="";
                    text=tmp;
                    kk++;
                }
                else
                {
                    result[kk]=get_number(text);

                    ff=text.Length-1;
                    tmp = text.Substring(1,ff);
                    text="";
                    text=tmp;
                    kk++;
                }

                ii++;
                if(text=="") break;
            }

            tmp="";
            for(kk=0; kk<ii; kk++)
            {
                if(result[kk].Length > 1) 
                {
                    for(ff=0; ff<10; ff++)
                    {
                        if(result[kk].CompareTo(english[ff])==0)
                        {
                            tmp = tmp + numeric[ff];
                            break;
                        }
                    }
                }
                else tmp = tmp + result[kk];
            }

            Console.WriteLine("Result String------------------------------------------------");
            Console.WriteLine("[" + tmp + "]");
        }
        int search_string(string str)
        {
            int kk,ii,ff;

            for(kk=0; kk<str.Length; kk++)
            {
                ii = (str.Substring(kk,1)).CompareTo("a");
                ff = (str.Substring(kk,1)).CompareTo("z");

                if(ii==0) return TRUE;
                if(ff==0) return TRUE;

                if(ii == 1 && ff == -1)
                {
                    return TRUE;
                }

                ii = (str.Substring(kk,1)).CompareTo("0");
                ff = (str.Substring(kk,1)).CompareTo("9");

                if(ii==0) return FAIL;
                if(ff==0) return FAIL;

                if(ii == 1 && ff == -1)
                {
                    return FAIL;
                }
            }
            return -1;
        }
        string get_number(string str)
        {
            return(str.Substring(0,1));
        }
        string get_string(string str)
        {
            int ii,kk;
            int max,min;
            string min_final_str;
            string max_final_str;

            max=-999;
            min=999;

            min_final_str="";
            max_final_str="";
            for(kk=0; kk<10; kk++)
            {
                ii = str.IndexOf(english[kk]);

                if(ii < 0) continue;

                if(max < ii)
                {
                    max=ii;
                    max_final_str = str.Substring(ii,english[kk].Length);
                }
                if(min > ii)
                {
                    min=ii;
                    min_final_str = str.Substring(ii,english[kk].Length);
                }
            }
            return(min_final_str);
        }
    }//end of class
}//end of nameapace

/*console 3*3 tris game source
 *cmd>type *.cs | findstr formattext
*/

using System;
using System.IO;
using System.Timers;

namespace ____java_is_package
{
    class Program
    {
        public static void Main(string[] args)
        {
            ____tris_overloading_cls nm = new ____tris_overloading_cls();
            nm.running();
        }
    }

    class ____tris_overloading_cls
    {
        //properties
        const int TRUE=1;
        const int FAIL=0;
        const int D_RIGHT=1000;
        const int D_LEFT=1001;
        const int D_DOWN=1002;
        const int MAPY=22;
        const int MAPX=22;
        const int ARR=3;
        const int MAXDESIGN=10;

        int xpos,ypos,hyun_design,next_design;
        int[,] tris=new int[MAPY,MAPX];
        int[,] design=new int[ARR,ARR];
        int[,,] realdesign=new int[,,]
        {
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
            {{1,1,1},{1,1,1},{1,1,1}},
        };

        Timer tm;

        //method
        void draw_tris()
        {
            string formattext="";
            string spacetext="                                          ";
            int ii,kk;

            for(ii=0; ii<MAPY-1; ii++)
            {
                formattext=formattext+spacetext;
                for(kk=1; kk<MAPX-1; kk++)
                {
                    if(tris[ii,kk]==1) formattext=formattext+"U";
                    else formattext=formattext+"_";
                 }
                 formattext=formattext+"\n";
             }
             Console.SetCursorPosition(0,0);
             Console.Write(formattext);
        }

        int common_check(int direction)
        {
            int[,] tris_tmp=new int[MAPY,MAPX];
            int ii,kk,ff;

            for(ALL)for(ALL)tris_tmp[ii,kk]=tris[ii,kk];
            for(ARR)for(ARR)if(design[ii,kk]==1) tris_tmp[ypos+ii,xpos+kk]=0;

            if(direction==D_RIGHT) xpos++;
            if(xpos+2>MAX-1) xpos--; //Array's MAX-1 Access Possible

            if(direction==D_LEFT) xpos--;
            if(xpos+0<0) xpos++ //Array's 0 Access Possible

            if(direction==D_DOWN) ypos++;

            for(ARR)for(ARR)if(design[ii,kk]==1) tris_tmp[ypos+ii,xpos+kk]=1;

            ff=0;
            for(ARR)for(ARR)if(tris_tmp[ypos+ii,xpos+kk]>1) ff++;

            if(ff > 0) 
            {if(direction==D_RIGHT) xpos--;
            if(direction==D_LEFT) xpos++;
            if(direction==D_DOWN) ypos--; return(FAIL)}
            else
            {
                for(ALL)for(ALL)tris[ii,kk]=tris_tmp[ii,kk];}
            }
            return(TRUE);
        }     
        void init()
        {
            int ii,kk;

            tm=new Timer();
            tm.Elapsed += new ElapsedEventHandler(____time_tick);
            tm.Interval=500;
            tm.Start();

            for(ALL)for(ALL)tris[ii,kk]=0;
            for(ii=0; ii<MAPY; ii++) tris[ii,0]=1; tris[ii,MAPX-1]=1;
            for(kk=0; kk<MAPX; kk++) tris[MAPY-1,kk]=1;

            xpos=MAPX/2; ypos=0; score=0;
            Random rr=new Random(); hyun_design=rr.Next() % MAXDESIGN; next_design=rr.Next() % MAXDESIGN;

            for(ARR)for(ARR) design[ii,kk]=realdesign[hyun_design,ii,kk];
            for(ARR)for(ARR) tris[ypos+ii,xpos+kk]=design[ii,kk];

            Console.Clear(); draw_tris();
        }
        int enter_check()
        {
            int ii,kk,rc;

            while(true)
            {
                rc=common_check(D_DOWN);
                if(rc==FAIL) break;

                draw_tris();
            }
            while(true)
            {
                if(check_horizon()==FAIL) break;
            }
            xpos=MAPX/2; ypos=0;
            hyun_design=next_design;
            Random rr=new Random(); next_design=rr.Next() % MAXDESIGN;
            for(ARR)for(ARR) design=realdesign[hyun_design];
            for(ARR)for(ARR) tris[ypos+ii,xpos+kk]=design[ii,kk];
            draw_tris();
            return(TRUE);
        }
        void ____time_check(object sender, ElapsedEventArgs e)
        {
            int ii,kk,rc;

            draw_tris();
            rc=common_check(D_DOWN);
            if(rc==FAIL)
            {
                if(ypos==0) stop();
                else
                {
                    while(true)
                    {
                        //no detect!!, while loop break!!
                        //no detect!!, while loop break!!
                        if(check_horizon()==FAIL) break;
                    }
                }
                xpos=MAPX/2; ypos=0;
                hyun_design=next_design;
                Random rr=new Random(); next_design=rr.Next() % MAXDESIGN;
                for(ARR)for(ARR) design[ii,kk]=realdesign[hyun_design,ii,kk];
                for(ARR)for(ARR) tris[ypos+ii,xpos+kk]=design[ii,kk];
            }
        }
        public void running()
        {
            int rc; ConsoleKeyInfo keyinfo;
            init();
            while(true)
            {
                keyinfo=Console.ReadKey(true);
                if(keyinfo.Key==ConsoleKey.RightArrow) rc=common_check(D_RIGHT);
                if(keyinfo.Key==ConsoleKey.LEFTArrow) rc=common_check(D_LEFT);
                if(keyinfo.Key==ConsoleKey.Escape) break;
                if(keyinfo.Key==ConsoleKey.Enter) rc=enter_check();
                draw_tris();
            }
            stop();
        }
        void draw_tris()
        {
            int ii,kk;
            string formattext="";

            for(ii=0; ii<MAPY-1; ii++)
            {
                for(kk=1; kk<MAPX-1; kk++)
                {
                    if(tris[ii,kk]==1) formattext=formattext+"U";
                    else formattext=formattext+"_";
                }
                formattext=formattext+"\n";
            }
            Console.SetCursorPosition(0,0);
            Console.Write(formattext);
        }
        void delete_column(int x, int y)
        {
            int ii;

            for(ii=y; ii>=1; ii--)
            {
                tris[ii.x]=tris[ii-1,x];
            }
        }
        int check_horizon()
        {
            int ii,kk,idx,horizon;

            horizon=MAPX-3;
            for(ii=0; ii<MAPY-1; ii++)
            {
                idx=0;
                for(kk=1; kk<MAPX-2; kk++)
                {
                    if(tris[ii,kk]==tris[ii,kk+1]) idx++;
                    else break;
                }
                if(idx==horizon)
                {
                    for(kk=1; kk<MAPX-1; kk++) delete_column(ii,kk);
                    score++;
                    return(TRUE);
                }
            }
            return(FAIL);
        }
    }//end of class
}

 

+ Recent posts