GSI

본 내용은 클라이언트 xsl 적용 방법 입니다.

[categories.xml]

<?xml version='1.0' ?>
<?xml-stylesheet type='text/xsl' href='categories.xsl'?>
<categorylist xmlns:sql='urn:schemas-microsoft-com:xml-sql'>
 <sql:query>
  SELECT categoryid, categoryname
  FROM categories
  FOR XML AUTO, ELEMENTS
 </sql:query>
</categorylist>

[categories.xsl]
<?xml version='1.0' ?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
  <xsl:template match='/'>
    <BODY>
      <TABLE>
        <TR>
          <TD><B>Click a Product Category</B></TD>
        </TR>
        <xsl:for-each select='categorylist/categories'>
          <TR>
            <TD>
              <A>
                <xsl:attribute name='HREF'>
                  Products.xml?categoryid=<xsl:value-of select='categoryid'/>
                  &amp;contenttype=text/html
                </xsl:attribute>
                <xsl:value-of select='categoryname'/>
              </A>
            </TD>
          </TR>
        </xsl:for-each>
      </TABLE>
    </BODY>
  </xsl:template>
</xsl:stylesheet>
Posted by gsi
:

XML 템플릿 사용

XML에서 템플릿(template)은 데이터를 처리하기 위해 질의문을 미리 생성해 놓은 문서를 말한다. 사용자가 직접 서버에 URL 질의를 입력해서 데이터를 검색하는 것보다 XML 템플릿을 이요하면 좀더 안정적이고, 제어 가능한 환경을 만들 수 있다. 템플릿은 데이터베이스에서 데이터를 검색하기 위한 질의를 하나 이상 포함하고 있고, 그 결과는 호출한 브라우저나 클라이언트 애플리케이션에서 보낸다. 템플릿은 XML-SQL 네임스페이스를 기반으로 하는 XML문서다.

HTTP와 템플릿을 사용하기 위해서 가상 이름에 템플릿 파일을 저장하고 템플릿에 접근하기 위해 URL을 통해 템플릿 파일에 접근할 수 있다. 예를 들면 products.xml이란 파일명으로 저장한 템플릿 파일이 있다면 다음과 같은 URL을 통해 접근할 수 있다.

템플릿을 사용하려면 가상 이름에 템플릿 질의 허용을 체크해 놓아야 한다. IIS에 SQL XML 구성 지원 MMC 스냅인 툴에서 설정 탭의 템플릿 질의 허용을 체크하는 것으로 해당하는 가상 디렉토리에 템플릿 질의를 허용할 수 있다.

템플릿 생성과 사용
기본적으로 XML 템플릿의 구성은 XML 문서와 동일한 구조다. 다만 SQL문을 포함하고 있다는 점이 다르다. SQL 문을 사용하기 위해서 최상위 요소에 'sql' 네임스페이스를 지정하고 <query> 요소를 사용한다. 다음은 노스윈드(northwind) 데이터베이스로부터 제품목록을 보여 주는 템플릿을 생성한 예다.

<?xml version='1.0'?>
<categorylist xmlns:sql='urn:schemas-microsoft-com:xml-sql'>
      <sql:query>
            SELECT categoryid, categoryname
            FROM categories
            FOR XML AUTO, ELEMENTS
      </sql:query>
</categorylist>

템플릿 가상 이름(templates)을 지정한 곳(c:\sqlroots\northwinddata\)에 이 제폼 목록 템플릿을 categories.xml로 저장한다. 이 코드에서 템플릿은 ADO를 통한 질의 템플릿을 사용하는 것과 같은 형식을 가진다. 템플릿에 접근할 때 <query> 태그는 XML 데이터를 처리하며, 수행한 질의 결과는 호출한 곳으로 반환한다. 다음은 XML 템플릿을 IIS 웹 서버를 통해 실행하게 된다.

이 코드를 인터넷 웹 브라우저에서 실행해 보길 바란다.
원하는 결과가 나왔다면 다행이지만..
HTTP:500 내부 서버 오류 라는 말이 나오게 되면 xml 파일의 이상이다.

템플릿 확장
템플릿을 확장하는 방법으로 파라미터 추가가 있다. 파라미터는 사용자가 하나 이상의 다앙햔 결과를 볼 수 있게 한다. 예를 들면, 템플릿을 파라미터를 받을 수 있게 생성하고, 사용자가 CategoryID 파라미터를 넘겨 주면 제품 목록 중 특정 제품의 상세 정보를 나타나게 작성할 수 있다. 파라미터는 템플릿 헤더에 위치하고, <header> 태그를 사용해서 정의한다. 각 파라미터는 <param> 태그를 사용해 정의할 수 있다. 다름은 파라미터를 사용해서 카테고리 번호를 넘겨주고, 해당 카테고리의 제품 목록을 출력하는 XML 템플릿이다.

<?xml version='1.0'?>
<productlist xmlns:sql='urn:schemas-microsoft-com:xml-sql'>
      <sql:header>
            <sql:param name='categoryid'>1</sql:param>
      </sql:header>
      <sql:query>
            SELECT productid, productname, unitprice
            FROM products WHERE categoryid = @categoryid
            FOR XML AUTO, ELEMENTS
      </sql:query>
</productlist>

products.xml 템플릿 문서에서는 categoryid 기본값으로 1을 지정한다 .파라미터를 인식하려면 <param> 태그를 name 속성으로 사용해야 한다. 이 이름을 @ 기호와 함께 사용해서 SQL 질의에서 사용할 수 있다. 파라미터화한 템플릿으로 데이터에 접근하기 위해 URL 질의 스트링에 파라미터를 지정한다. 다음은 카테고리 번호 2를 파라미터로 전달하고, 템플릿을 실행하는 코드이다.

categoryid를 2로 입력된 하면을 볼 수 있다.

Posted by gsi
:

저번장까지 IIS를 설치하고 가상 디렉토리까지 마무리 했습니다.
이제 HTTP 를 사용해서 어떻게 사용하는 지에 대해서 간단하게 짚고 넘어 가겠습니다.

URL 질의 사용
가상 디렉토리가 제대로 설정되어 있는지 확인하는 간단한 방법은 URL 질의를 가능하게 한 후, XML 가능 브라우저를 사용해서 질의문을 실행해 보는 것입니다. URL에서 데이터를 추출할 경우 질의와 다른 설정이 적절한지 확인하기 위해 파라미터를 이용할 수 있다. 이 파라미터는 URL 질의 문자열에 표준 형식을 사용해서 보낼 수 있다. URL과 파라미터를 분리하려면 ? 기호를 사용하고, 여러개의 파라미터를 보낼 때는 각 파라미터를 & 기호를 이용해서 분리한다. 다음 URL 포맷은 2개의 파라미터를 이요해서 URL로 데이터에 접근할 때 사용한 예입니다.

URL 질의를 이용해서 FOR XML 질의를 포함하는 SQL 파라미터를 지정할 수 XML 문서를 추출할 수 있다. FOR XML 질의의 결과가 잘 구성한 XML 문서를 반환하기 보다 XML 데이터를 반환하기 때문에 최상위 요소를 URL에 반드시 지정해야 한다. 그래서 최상위 요소를 정확히 지정하거나 최상위 요소 파라미터를 지정해 처리할 수 있다.

다음 예제는 Northwind 데이터베이스의 Products 테이블로부터 데이터를 검색하는 것으로 사용하는 URL 질의다. 최상위 요소는 SQL 파라미터의 일부로 포함한다. 최상위 요소는 <catalog>로 임의의 요소를 정의하였다.

http://localhost/northwinddata?sql=SELECT+'<catalog>';SELECT+*+
FROM+products+FOR+XML+AUTO;SELECT+'</catalog>
또는
http://localhost/northwinddata?sql=SELECT+*+FROM+products+FOR+XML+AUTO&
root
=catalog

위의 내용을 인터넷 브라우저에서 확인 가능하다. 한번씩 해보길 바란다.

URL 질의를 하나하나 SQL문으로 작성하는 것은 상당히 번거로운 작업이다. 이러한 번거로움은 T-SQL의 EXECUTE 구문이나 ODBC를 호출해 저장 프로시저를 수행하면 해결할 수 있다. 효율적으로 URL 질의를 사용할 수 있을 뿐만 아니라 보안 측면에서도 훨씬 유리하다. 실제로 UTL질의 문을 한번 살펴 보자.

사용자 삽입 이미지
URL 질의에서 저장 프로시저를 호출할 수 있게, EXECUTE 구문과 저장 프로시저 이름, 파라미터를 브라우저 주소란에 입력한다.

결과는 직접 확인 바랍니다.



 

Posted by gsi
:

테스트 환경 : SQL 2000 입니다.

IIS 가상 디렉토리를 통한 데이터베이스 처리
SQL 서버 2000의 HTTP 처리를 위한 툴은 MMC에 스냅인 된 IIS에 SQL XML 구성 툴을 사용한다. SQL XML 지원 구성을 실행하려면 [시작]>[프로그램]>[Microsoft Sql server]>[IIS에 SQL XML 지원 구성]을 차례로 선택하여 실행한다.

사용자 삽입 이미지

IIS에 SQL XML 지원 구성을 실행하면 관리창을 볼 수 있다. 관리창을 이용하면 IIS의 가상 디렉토리로 이루어진 SQL 서버 2000의 XML 처리를 생성하고 관리할 수 있다. 관리 창을 수행한 후, 서버를 확장하면 로컬 컴퓨터에 구성한 웹 사이트는 왼쪽창에 나타난다. 왼쪽 창의 IIS 가상 디렉토리 관리를 선택해 서버를 관리할 수 있고, 원격 시스템 동작 메뉴를 이용해 등록할 수도 있다.

새로운 가상 디렉토리를 설정하려면 먼저 처리할 웹 사이트를 선택해야 한다. 기본 웹 사이트나 [동작] 메뉴를 선택한 후, [새로 만들기]>[가상 디렉토리]를 선택한다. 새로운 가상 디렉토리를 구성하는 대화 상자가 열린다.
사용자 삽입 이미지

가상 디렉토리 이름과 경로 지정
가상 디렉토리는 URL을 처리 하는 부분이다. 이름은 인트라넷 환경 형식인 'http://서버경로/가상디렉토리' 형태로 만든다. 가상 디렉토리 부분에는 IIS 서버 URL 중 도메인 부분을 지정한다.

자신의 시스템을 로컬에서 사용할 경우 http://localhost/northwinddata 형태로 사용할 수 있다. [로컬 경로]에서는 가상 디렉토리 지정된 물리적인 위치의 전체 경로를 지정할 수 있다.
사용자 삽입 이미지

가상 디렉토리 보안 설정
SQL 서버 2000의 인증 방법은 크게 두 가지로 나눌 수 있다. 첫번째는 윈도우 서버의 운영체제와 SQL 서버간의 통합한 인증 절차다. 운영체제 차원에서 인증 과정을 통과하면 자동적으로 SQL 서버의 인증도 통과하는 방식이다. 두번째는 운영체제와 SQL 서버의 분리한 인증방법으로, SQL 서버에서 인증 과정을 별도로 관리하는 것을 말한다. 어떤 인증 방법을 사용해도 상관없이, 설정한 인증 방법에 따라[보안] 설정을 하면 된다.
사용자 삽입 이미지

데이터 원본 지정
새 가상 디렉토리의 등록 정보 대화 상자의 [데이터 원본] 탭에서 SQLISAPI 애플리케이션에 데이터를 제공할 [SQL Server]와 [데이터베이스]를 지정한다. 데이터를 저장할 서버를 지정해야 하고, 데이터가 있는 데이터베이스 이름도 지정한다.
사용자 삽입 이미지

데이터 접근 지정
가상 디렉토리를 통한 데이터접근할 수 있게 설정하기 위해서 새 가상 디렉토리 등록 정보의 [설정]탭을 이용한다.

설정은 네 가지 중 선택할 수 있다. 모든 질의 방식을 지원받으려면 네 가지를 모두 체크하면 된다.

  • URL 질의 허용
  • 템플릿 질의 허용
  • XPath 허용
  • POST 허용

사용자 삽입 이미지

가상 이름(Virtual Name) 생성
가상 디렉토리 등록 정보 대화 상자의 [가상 이름] 탭에서 디렉토리를 위한 가상 이름을 설정할 수 있다. 가상 이름은 템플릿 스키마 또는 데이터베이스 객체를 지정하기 위해 URL에서 사용한다. 가상 이름은 템플릿, 스키마, 데이터베이스 객체형으로 가상 이름의 [새로 만들기]를 선택해 원하는 가상이름, 유형, 경로를 생성할 수 있다.
사용자 삽입 이미지
지정한 폴더에 XML 템플릿과 스키마를 포함하게 가상 이름을 사용할 수 있다. 예를 들면 Northwind data 가상 디렉토리 애플리케이션에서 products.xml 이라고 정의한 템플릿을 포함하는 폴더에 가상 이름 templates를 지정할 수 있다. 이 템플릿은 http://localhost/northwinddata/templates/products.xml과 같은 URL을 통해 접근할 수 있다.

여기까지 해서 설정이 모두 완료가 되었습니다. IIS(인터넷 정보 서비스)를 열어 보면 가상 디렉토리가 설정되어져 있는 것을 볼 수 있습니다.

이상..

Posted by gsi
:

SQL 서버 2000에서 제공하는 새로운 기능 중 HTTP를 이용해서 XML 데이터에 접근하는 방법을 알아본다. HTTP를 이용해서 인트라넷이나 인터넷 기반 애플리케이션을 구축할 수 있다. 이 방법은 Micorsoft IIS의 가상 디렉토리를 구축하는 방법으로 XML 데이터를 처리하거나 다른 애플리케이션에 쉽게 적용할 수 있다. HTTP로 데이터를 처리하는 기능으로 ASP 애플리케이션보다 적은 코드를 이용하면서도 쉽고 빠르게 데이터 중심적인 웹 사이트를 구축할 수 있다.

XSL 스타일시트를 XML 데이터에 적용해서 HTML 문서로 변형한 후, 브라우저 기반 클라이언트로 전송하거나 WML과 같은 다른 문서 형태로 변환해서 WAP 형식으로 휴대폰, PDA 등에 사용이 가능해 진다.

SQL 서버의 HTTP 처리 구조
SQL 서버는 SQLISAPI(SQL 서버에서 제공하는 ISAPI 애플리케이션)FMF DLDYDGOTJ ㅗㅅ세FMF CJFLGKSEK. IIS에 가상 디렉토리 루트를 생성한 후, HTTP URL을 이용하면 SQL 서버의 데이터베이스에 접근할 수 있다. SQLISAPI 애플리케이션은 SQL 서버 2000의 OLE-DB 공급자를 이용해서 클라이언트로 XML이나 HTML 데이터를 보낸다.

SQL 서버를 IIS 웹 서버와 동일한 시스템에 구축할 수 있다. SQL 서버에는 데이터를 테이블에 저장할 수 있고, 클라이언트로부터 IIS 웹 서버에 의해 질의문을 전송받고, 전송받은 질의문을 실행해서 질의한 결과의 데이터를 XML 문서의 형태로 IIS 웹 서버를 통해 클라이언트에게 전송한다. 클라이언트 애플리케이션은 다음과 같이 네 가지의 방법 중 하나로 데이터를 요청할 수 있다.

  • FOR XML 질의문을 질의 스트링으로 URL에 보내는 방법
  • XML 질의 템플릿을 ISAPI 애플리케이션에 포스팅 하는 방법
  • XML 질의 템플릿을 웹 서버의 가상 루트에 지정하는 방법
  • XML 스키마를 웹 서버의 가상 루트에 정의하는 방법





 

Posted by gsi
:

Connection의 이해

Connection은 데이터 저장소와 .NET 응용 프로그램 사이의 물리적 커뮤니케이션을 다른다. Connection 객체는 데이터 공급자의 한 부분이기 때문에. 각각의 데이터 공급자는 자신만의 Connection 객체를 구현한다. .NET 프레임 워크가 제공하는 두 개의 데이터 공급자는 System.Data.OleDB 네임스페이스에서 OleDbconnection을 구현하고, System.Data.SqlClient 네임스페이스에서 SqlConnection을 구현한다.

OleDbConnection은 보통 OLE DB를 사용하는데, Microsoft SQL Server를 포함하여 다른 OLE DB 공급자에서도 사용할 수 있다. SqlConnection 은 OLE DB 공급자를 거치지 않고 직접 SQL Server로 접속하기 때문에, SQL Server일 경우에 효과적이다.


Connection을 직접 생성할 수도 있지만. 여기서는 테스트를 쉽게 하기 위해서
DataAdapter를 사용했다.


OleDbDataAdapter 또는 SqlDataAdapter를 사용해서 공급자를 선택하고 서버명, 로그인 정보를 입력하고 원하는 데이터 베이스를 선택 했다.

그리고 쿼리 생성기를 사용해서 해당 테이블의 컬럼 정보를 선택해서 생성하였다.

이렇게 하면 디자인 뷰의 화면 하단에 oleDbDataAdapter1, oleDbConnection1 또는 sqlDataAdapter1, sqlConnection1 이 생기게 된다.

Connection을 이해 하기 위해서 두개의 ConnectionString를 모두 추가 하였고 이것을 사용해서 테스트를 진행 했다.

두개의 커넥션을 모두 받을수 있는 System.Data.IDbConnection 변수를 하나 생성하였다.
private System.Data.IDbConnection myconnection;

그리고 Ole 또는 Sql 을 선택해서 myconnection에 설정하게 된다.
myconnection = this.oleDbConnection1;

myconnection 은 아래와 같은 3개의 정보를 담고 있다.
1. myconnection.ConnectionString.ToString();
2. myconnection.Database.ToString();
3. myconnection.ConnectionTimeout.ToString();



커넥션을 열고 닫고 하는 과정은 아래와 같다.
this.myconnection.Open();  //커넥션을 오픈한다.
MessageBox.Show(this.myconnection.State.ToString()); //커넥션 상태를 알아본다.
this.myconnection.Close();  //커넥션을 닫는다.


[관련내용]
ConnectionString 속성
ConnectionString은 어느 Connection 객체이든지 간에 가장 중요한 속성이며, 사실상 나머지 속성은 읽기 전용이다. 이들 나머지 속성들은 ConnectionString이 제공한 값에 의해 생성된 Connection에 의해 설정된다.

모든 ConnectionString은 동일한 포멧을 가진다. 그것은 키워드와 값이 한 세트로 구성되고 세미콜론(;)으로 구분되며, 전체가 작은 따옴표나 큰 따옴표로 쌓여 있다.

"keyword=value;keyword=value"

키워드 이름은 대소문자 구별을 하지 않는다. 그러나 데이터 소스에 의존하는 값은 그렇지 않을 수 있다. 작은 따옴표 혹은 큰 따옴표의 사용은 문자열의 기본 규칙을 따른다. 예를 들면, 데이터베이스의 이름이 Becca's Data이면, ConnectionString은 큰 따옴표를 써야 한다. "Database=Becca's Data", 'Database=Becca's Data' 는 에러를 일으킬 것이다.

동일한 키워드를 여러번 사용한다면 마지막 인스턴스가 사용될 것이다. 예를 들어, ConnectionString에 databast=Becca's Data ; database=Northwind"를 준다면, 초기 데이터베이스는 NorthWind가 될 것이다. 다중 인스턴스를 사용하는 것이 구문 에러를 발생하지 않는 가장 이상적인 방법이다.

ConnectionString 형식은 어렵지 않지만, 내용은 데이터 공급자마다 항상 고유하기 때문에 내용을 정의 하는 것이 어려울 수 있다. 그러나 [데이터 연결 속성] 대화 상자를 이용해서 디자인 타임 연결을 생성하고, 그 값을 복사함으로써 쉽게 작업을 할 수 있다.

ConnectionString은 연결이 닫힐 때만 설정할 수 있다. 설정될 때 Connection 객체는 문자열 문법을 검사하고 나머지 속성(앞에서 읽기 전용이고 했던 것을 기억할 것이다)들을 설정할 것이다. ConnectionString은 연결이 열려 있을 때에 완전히 확인할 수 있다. 만약 연결이 확인되지 않거나 제공하지 않는 속성을 발견하면 오류가 발생할 것이다(객체가 사용될 때 의존하고 있는 OleDbException과 SqlDbException 둘 중 하나에서 발생한다.).


이상...
이론 내용은 Microsoft ADO.NET Step by Step 내용 2장에서 발췌 하였음...






Posted by gsi
:

함수가 많을 경우 함수 포인터를 사용해서 배열로 사용하는 방법이 편할때가 있다.

그래서 STL의 vector을 사용해서 함수 포인터 정보를 배열로 저장하고
해당 함수들을 콜해서 처리 하는 방법을 사용할까 한다.


함수 포인터로 사용한 원형을 typedef로 선언한다.

typedef ngevent (*PF)(EVENT_INFO* arg);

이렇게 선언한 후에 일반 포인터로 사용할 경우는 아래와 같이 하면 된다.

PF pf; //pf에 함수 포인터 연결

vector을 사용할 경우에는 아래와 같이 사용한다.

//선언
vector<PF>  m_ClickEventHandler;

//연결할 함수를 작성한다.
ngevent test(EVENT_INFO* arg)
{
 return 1;
}

ngevent test2(EVENT_INFO* arg)
{
 return 1;
}

//vector 함수에 추가
m_ClickEventHandler.push_back(test);
m_ClickEventHandler.push_back(test2);

//함수를 vector의 배열로 for문을 통해서 호출한다.
for(int i = 0; i < (int)m_ClickEventHandler.size(); i++)
{
      EVENT_INFO info;
      info._click2d.x = 10.f * (float)i;
      m_ClickEventHandler[i](&info);
}


//////////////////////////////////////////////////

Posted by gsi
:

함수 포인터 타입 - (펌)

STL 2007. 9. 18. 14:48 |

주소 : http://www.winapi.co.kr/clec/cpp2/15-2-2.htm

함수 포인터 타입도 일종의 고유한 타입이다. 따라서 원형이 다른 함수 포인터끼리는 곧바로 대입할 수 없으며 함수의 인수로도 넘길 수 없다. 정수형 포인터 변수(int *)에 실수형 포인터 변수(double *)의 값을 대입할 수 없듯이 말이다. 다음 코드를 보자.

 

int (*pf1)(char *);

void (*pf2)(double);

pf1=pf2;                  // 타입이 다르므로 에러

 

pf1은 문자형 포인터를 인수로 취하고 정수형을 리턴하는 함수를 가리키는 함수 포인터이며 pf2는 실수를 인수로 취하고 리턴값이 없는 함수를 가리키는 함수 포인터이다. 두 변수가 가리킬 수 있는 함수의 원형이 다르기 때문에 pf2가 가리키는 번지를 pf1에 곧바로 대입할 수 없다. 만약 이것이 가능하다면 pf1로 함수를 호출할 때 컴파일러는 char *형의 인수를 찾지만 pf1이 가리키는 함수는 double형의 인수를 받아들이므로 불일치가 발생하며 함수가 제대로 호출되지 않을 것이다.

함수 포인터가 가리킬 수 있는 원형과 같지 않은 함수의 번지를 대입하는 것도 똑같은 이유로 에러로 처리된다. 다음 코드에서 pf3은 문자형 포인터와 실수를 인수로 취하고 리턴값이 없는 함수를 가리키도록 선언했는데 func 함수는 pf3의 원형과 다르므로 pf3에 func 함수의 번지를 대입할 수 없다.

 

int func(int a);

 

void (*pf3)(char *, double);

pf3=func;                         // 에러

 

그러나 타입이 다른 함수 포인터끼리라도 강제로 대입할 수는 있는데 이것이 일단은 가능해야 한다. void 포인터에 저장된 함수의 번지를 대입받는다거나 자료 구조 설계시에 미리 알 수 없는 함수에 대한 포인터를 다루고자 할 때이다. 이럴 때 사용하는 것이 바로 캐스트 연산자이며 여러 가지 이유로 강제 캐스팅의 필요성은 누구나 인정하고 있다. int *pi와 double *pd가 있을 때 pi=pd 대입은 금지되지만 pi=(int *)pd는 가능한 것처럼 함수 포인터도 타입에 맞게 캐스팅하면 강제로 대입할 수 있다.

데이터 포인터에서와 마찬가지로 함수 포인터에도 캐스트 연산자를 쓸 수 있는데 문제는 함수 포인터의 캐스트 연산자가 모양이 생소해서 조금 어렵다는 것이다. 함수 포인터는 타입 자체가 길기 때문에 캐스트 연산자의 모양도 상당히 복잡해 보인다. 다음 코드는 pf2를 pf1에 강제로 대입하기 위해 캐스트 연산자를 사용한 것이다.

 

int (*pf1)(char *);

void (*pf2)(double);

pf1=(int (*)(char *))pf2;

 

이 식에서 (int (*)(char *))가 캐스트 연산자이다. 함수 포인터형의 캐스트 연산자를 만드는 방법은 함수 포인터 선언식에서 변수명을 빼고 전체를 괄호로 한 번 더 싸주면 된다. 일종의 공식이므로 외워 두거나 아니면 필요할 때마다 이 공식을 찾아보기 바란다.

pf1=(int (*)(char *))pf2 대입문은 pf2가 가리키는 번지를 문자형 포인터를 인수로 취하고 정수를 리턴하는 함수 포인터 타입으로 잠시 바꾼 후 pf1에 대입한다. pf3에 func 함수의 번지를 강제로 대입할 때도 마찬가지로 캐스트 연산자를 사용할 수 있다. 물론 이렇게 강제로 대입했을 때의 부작용에 대해서는 스스로 책임져야 한다.

 

pf3=(void (*)(char *,double))func;

 

캐스트 연산자가 길어 보여서 그렇지 원리를 알고 나면 별로 어렵지 않다. 다음은 조금 이론적인 얘기가 되겠지만 함수 포인터의 배열이나 포인터를 선언하는 형식에 대해 알아보자. T형에 대해 T형 배열과 T형 포인터를 항상 선언할 수 있으므로 함수 포인터에 대해서도 배열과 포인터를 선언할 수 있다. func 타입의 함수를 가리킬 수 있는 함수 포인터를 요소로 가지는 크기 5의 arpf 배열은 다음과 같이 선언한다.

 

int (*arpf[5])(int);

 

함수 포인터 배열을 선언할 때는 변수명 다음에 첨자 크기를 밝혀 주면 된다. 잘못 생각하면 int (*arpf)(int)[5];가 맞을 것 같기도 한데 첨자 크기는 반드시 변수명 다음에 바로 써야 한다. 이 선언에 의해 int (*)(int)형의 함수의 번지를 가리킬 수 있는 함수 포인터 arpf[0] ~ arpf[4]까지 4개의 변수가 생성되며 각 변수는 int func(int)와 같은 원형의 함수를 가리키는 번지를 가질 수 있다. 동일한 타입의 변수들을 배열에 모아 두면 루프를 돌면서 함수들을 순서대로 호출한다거나 하는 처리도 가능해진다.

다음은 함수 포인터의 포인터를 선언해 보자. func 타입의 함수를 가리키는 함수 포인터를 가리키는 포인터 ppf는 다음과 같이 선언하는데 * 구두점만 하나 더 적으면 된다.

 

int (**ppf)(int);

 

이렇게 선언된 ppf는 int (*)(int) 타입으로 선언된 함수 포인터 변수나 함수 포인터 배열을 가리킬 수 있는 이차 함수 포인터 변수이다. ppf=&pf 또는 ppf=arpf 식으로 함수 포인터 변수의 번지를 대입받을 수 있으며 ppf로부터 함수를 호출할 때는 (**ppf)(2) 형식을 사용한다. 함수 포인터 배열 arpf와 이중 함수 포인터 ppf가 메모리에 구현된 모양은 다음과 같다.

함수 포인터의 타입은 함수가 취하는 인수들의 타입과 리턴값까지 정확하게 밝혀야 하기 때문에 타입의 형식이 너무 길어서 쓰기에 번거롭다. 또한 함수 포인터로부터 파생된 타입을 만드는 것도 헷갈리고 생소한 면이 있다. 그래서 함수 포인터 타입을 자주 사용하거나 자신이 없다면 직접 타입을 기술하는 것보다 typedef로 함수 포인터 타입을 따로 정의한 후 사용하는 것이 편리하다. int func(int)형의 함수를 가리키는 타입은 다음과 같이 정의한다.

 

typedef int (*PFTYPE)(int);

PFTYPE pf;

 

함수 포인터를 선언하는 문장에서 변수명을 원하는 타입 이름으로 바꾸고 앞에 typedef만 붙이면 된다. 이후 컴파일러는 PFTYPE이라는 명칭을 int (*)(int) 타입으로 인식하므로 PFTYPE으로 함수 포인터 변수를 쉽게 선언할 수 있으며 캐스트 연산자로도 사용할 수 있다. 또한 함수 포인터로부터 배열이나 포인터같은 파생 변수를 선언하는 것도 훨씬 더 간편하다.

 

PFTYPE arpf[5];

PFTYPE *ppf;

 

마치 int형으로부터 배열이나 포인터를 선언하듯이 PFTYPE을 사용할 수 있으므로 직관적이고 읽기에도 좋다.

Posted by gsi
:

회사 컴퓨터에 sql 2000을 깔았다.
DB를 배우다 보니 2005 이상의 좋은 환경에서의 공부는 몬가 부족하다.
세부적인 내용을 알지 못하고 DB를 편하게만질수 있는것과, XML과의 통합으로 인해서
몬가 편해진듯 보이면서도 확장하기 위한 기본 기술이 너무 부족한듯 하다.

Visual Studio 2003을 기준으로 해서 ADO.NET를 기본을 조금더 배우고
작업에 들어가야 할거 같다.
Posted by gsi
:

STL 샘플 코드...강추!!!

STL 2007. 9. 18. 10:30 |

Posted by gsi
:

사용자 삽입 이미지

본 프로그램은 GsiSee의 조금 다른 버젼으로 계획 중이다.

기능은 하단에 해당 이미지 리스트가 있으며 가운데 선택된 이미지가 크게 보이게 되며, 좌우 버튼을 통해서 이미지 선택이 가능하다.

구현할 내용
1. 해당 폴더의 내용을 가져와서 리스트로 만드는 부분 완성하기
2. 버튼으로 좌우 이동하지 않고 마우스를 위치 시키거나 스크롤을 사용해서 처리 가능하게 한다.
3. 이미지 이동시 에니메이션 처리를 해서 자연스럽게 이동되도록 한다.
4. 이동될때 선택된 이미지가 항상 가운데 있어야 하기 때문에 이미지 위치를 계산해서 처리 해야 할거 같다.
5. 이미지가 선택되면 자연스럽게 위에 화면에 나타나도록 한다.
6. 하단의 이미지 슬롯을 Viewport3D의 형태로 구현해서 입체적으로 보이도록 구현한다.

이상 구현 내용이며, 조금씩 업데이트 하도록 하겠습니다.

[파일 데모 설명]
1. 해당 이미지는 6개의 샘플 이미지를 사용한 겁니다. 압축 파일에는 존재 하지 않습니다.
   - 1, 2, 3, 4, 5, 6 jpg 파일을 임의로 만들어서 추가 해야 합니다.

<해당 데모>

Posted by gsi
:

가끔 어이 없는 실수를 할때가 ^^..

stl::string 를 사용해서 문자열을 받는 곳에서 메모리 릭이 발생!!
아.. 어디지?.. 이게 왜 릭이 생기지?..

상속 구조를 취하게 되었을때 소멸자를 virtual로 해주어야 하는 것을 깜박 했다.

앞으로는 조심조심. ^^..
Posted by gsi
:

link : http://msdn.microsoft.com/library/kor/default.asp?url=/library/KOR/cpguide/html/cpconnavigatingrelationshipbetweentwotables.asp

DataRelation의 주요한 기능 중 하나는 DataSet 내의 한 DataTable에서 다른 DataTable로 이동을 허용한다는 것입니다. 따라서, 연관된 DataTableDataRow가 하나 주어지면 연관된 다른 DataTable에 있는 모든 연관된 DataRow 개체를 검색할 수 있습니다. 예를 들어, 고객 테이블과 주문 테이블 사이에 DataRelation을 만든 다음 DataRow.GetChildRows를 사용하여 특정 고객 행에 대한 모든 주문 행을 검색할 수 있습니다.

다음 코드 예제에서는 DataSetCustomers 테이블과 Orders 테이블 사이에 DataRelation을 만들고 각 고객에 대한 모든 주문을 반환합니다.

[C#]
DataRelation custOrderRel = custDS.Relations.Add("CustOrders",
                     custDS.Tables["Customers"].Columns["CustomerID"],
                     custDS.Tables["Orders"].Columns["CustomerID"]);
foreach (DataRow custRow in custDS.Tables["Customers"].Rows)
{
  Console.WriteLine(custRow["CustomerID"]);
  foreach (DataRow orderRow in custRow.GetChildRows(custOrderRel))
    Console.WriteLine(orderRow["OrderID"]);
}

다음 예제에서는 이전 예제를 기반으로 네 개의 테이블을 모두 연관시키고 이들 관계를 탐색합니다. 이전 예제에서와 마찬가지로 CustomerIDCustomers 테이블을 Orders 테이블에 연관시킵니다. Customers 테이블의 각 고객에 대해 Orders 테이블의 모든 자식 행이 결정되어 특정 고객의 주문 개수와 이들의 OrderID 값이 반환됩니다.

확장된 예제에서는 OrderDetailsProducts 테이블의 값도 반환됩니다. Orders 테이블은 각 고객 주문에 대해 주문된 제품과 수량을 결정하기 위해 OrderID를 사용하여 OrderDetails 테이블에 연관됩니다. OrderDetails 테이블에는 주문된 제품의 ProductID만 있으므로 OrderDetailsProductName을 반환하기 위해 ProductID를 사용하여 Products에 연관됩니다. 이 관계에서 Products 테이블은 부모 테이블이고 Order Details 테이블은 자식 테이블입니다. 그 결과, OrderDetails 테이블을 반복하여 검색할 때는 GetParentRow가 호출되어 연관된 ProductName 값이 검색됩니다.

CustomersOrders 테이블에 대해 DataRelation을 만들면 createConstraints 플래그(기본값은 true)의 값이 지정되지 않습니다. 이런 경우에는 Orders 테이블의 모든 행이 부모 테이블인 Customers에 존재하는 CustomerID 값을 가지고 있다고 가정합니다. Customers 테이블에 없는 CustomerIDOrders 테이블에 있으면 ForeignKeyConstraint에 의해 예외가 throw됩니다.

부모 열에 포함되어 있지 않은 값이 자식 열에 있는 경우 DataRelation을 추가할 때 createConstraints 플래그를 false로 설정합니다. 예제에서는 Orders 테이블과 OrderDetails 테이블 사이의 DataRelation에 대해 createConstraints 플래그가 false로 설정됩니다. 이렇게 되면 응용 프로그램에서는 런타임에 예외를 발생시키지 않고 OrderDetails 테이블의 모든 레코드와 Orders 테이블 레코드의 일부분만 반환할 수 있습니다. 확장된 예제는 다음과 같은 형식의 출력을 생성합니다.

      Customer ID: NORTS
        Order ID: 10517
              Order Date: 4/24/1997 12:00:00 AM
                 Product: Filo Mix
                Quantity: 6
                 Product: Raclette Courdavault
                Quantity: 4
                 Product: Outback Lager
                Quantity: 6
        Order ID: 11057
              Order Date: 4/29/1998 12:00:00 AM
                 Product: Outback Lager
                Quantity: 3

다음 코드 예제는 확장된 예제로서 OrderDetailsProducts 테이블의 값과 반환되고 있는 Orders 테이블 레코드의 일부분만 반환합니다.

[C#]
DataRelation custOrderRel = custDS.Relations.Add("CustOrders",
                     custDS.Tables["Customers"].Columns["CustomerID"],
                     custDS.Tables["Orders"].Columns["CustomerID"]);

DataRelation orderDetailRel = custDS.Relations.Add("OrderDetail",
                     custDS.Tables["Orders"].Columns["OrderID"],
                     custDS.Tables["OrderDetails"].Columns["OrderID"], false);

DataRelation orderProductRel = custDS.Relations.Add("OrderProducts",
                     custDS.Tables["Products"].Columns["ProductID"],
                     custDS.Tables["OrderDetails"].Columns["ProductID"]);

foreach (DataRow custRow in custDS.Tables["Customers"].Rows)
{
  Console.WriteLine("Customer ID: " + custRow["CustomerID"]);

  foreach (DataRow orderRow in custRow.GetChildRows(custOrderRel))
  {
    Console.WriteLine("  Order ID: " + orderRow["OrderID"]);
    Console.WriteLine("\tOrder Date: " + orderRow["OrderDate"]);

    foreach (DataRow detailRow in orderRow.GetChildRows(orderDetailRel))
    {
        Console.WriteLine("\t   Product: " + detailRow.GetParentRow(orderProductRel)["ProductName"]);
        Console.WriteLine("\t  Quantity: " + detailRow["Quantity"]);
    }
  }
}
Posted by gsi
:

이것을 보면서 조금더 공부해도 좋을듯 하다.
.net framework의 내용중에서 ado.net 에 관련된 내용이다.
한글로되어 있기 때문에 더 추천 !!

http://msdn.microsoft.com/library/kor/default.asp?url=/library/KOR/cpguide/html/cpconaccessingdatawithadonet.asp
Posted by gsi
:

DataSet 객체 만들기

DB&XML 2007. 9. 17. 00:44 |

대부분의 책을 보면 DataSet 등과 같은 DB를 연결하기 위한 부분들이 코드로 직접 작성하는 부분이 많았던거 같다. 내가 지금 하고 있는 VS 2008 Beta 2 에서는 대부분 많은 부분 자동화가 되어 있는듯 하다. 아무래도 2005 이상 부터는 그런거 같은데..
간단하게 DB를 가져와서 Window Form에 연결하는 과정에 대해서 적어 보도록 한다.

기본적으로 SQL이 설치 되어 있고, Northwind DB가 있다고 가정하겠습니다.


Data Sources 창에서 추가하고 시작할때.


사용자 삽입 이미지

메뉴에서 Data를 선택하고 Show Data Sources 를 선택합니다.
선택하면 Data Sources 라는 창이 하나 보이게 됩니다.

사용자 삽입 이미지
Add New Data Source...   를 누르면 창이 하나 보이게 됩니다. 여기서 Database를 선택합니다.
사용자 삽입 이미지
New Connection... 을 누르면 창이 하나 뜨게 됩니다. 여기서 우리가 SQL DB를 사용하기 때문에 Change 를 누르고 Microsoft SQL Server (SqlClient) 를 선택하게 됩니다.
이렇게 하면 Server name가 나오게 됩니다. (단, 로컬에서 사용할때라면 컴퓨터 이름이 나오게 됩니다.)

Server name를 선택하고 Log on to the server 항목에서 Use SQL Server Authentication을 체크 하고 User name와 Password를 입력합니다.

Connect to a database 에서 Select or enter a database name를 Northwind로 선택하게 됩니다.
모두 성공적으로 처리가 되었는지를 알아 보기 위해서 Test Connection을 선택하면 메시지 박스가 뜨게 됩니다.

제대로 되었다면 아래와 같은 내용을 보실수 있을겁니다.
사용자 삽입 이미지

next를 눌러서 다음 화면으로 넘어 갑니다.
기본 이름을 사용하시거나 다른 이름을 지정하고 next를 다시 누릅니다.
해당 테이블을 선택할 수 있는 화면이 나오는데요.
여기서 해당 테이블을 선택하고 사용할 컬럼을 따로 선택할 수도 있습니다.
(여기까지는 별도 이미지 없음 ^^)

여기까지 되었다면. Data Srouces 라는 창에 NorthWindDataSet 라는 부분이 보이게 되며
Solution Explorer 의 화면에 NorthwindDataSet.xsd와 몇개의 파일이 하위 트리로 생성되게 됩니다.
사용자 삽입 이미지
위의 화면에서 NorthwindDataSet.xsd 를 클릭 하게 되면 중앙의 화면과 같이 나오게 됩니다.

중앙 화면의 Server Explorer 라는 부분을 클릭 하게 되면 Server Explorer이라는 창이 하나 보이게 되는데요 이전에 추가 했던 ***.Northwind.dbo 라는 부분이 보이게 됩니다.
여기서 해당 테이블을 중앙 화면으로 드래그 해서 추가해 주시면 됩니다.

사실 여기서 많은 방법이 있지만..
테이블을 추가 하고 나면 그 해당 테이블의 모든 정보가 화면에 드래그 되서 다 들어가게 됩니다. 이 부분에 대해서 부분적인 컬럼정보만 필요하다면 Data Sources 창에서 편집이 가능하며 다른 테이블을 가져와서 세부 연결해주는 것도 가능하게 됩니다.
(아.. 많은 부분 이미지 처리를 못하는게 좀 아쉽습니다. 용량 문제로 인해서.. -.-)

아래 화면은 필요한 부분만 편집해서 나온 최종 모습입니다.
사용자 삽입 이미지

이제 윈도우 폼을 배치 하고 해당 내용을 링크 시키는 부분만 남아 있습니다.

사실 여기서 윈도우 폼도 Data Sources 에 있는 내용을 그대로 드래그 해서 배치가 가능해 집니다. 참 편하게 변했죠 ^^.. 하지만 윈도우 폼이 기존에 있다고 가정하고 해보겠습니다.

이때 방법은 두가지로 나눠 집니다.
윈도우 폼에 드래그 해서 링크 시키는 방법과 Properties 창에서 직접 선택해서 넣는 방법으로 나눠 집니다.
사용자 삽입 이미지
위에서 보는 것과 같이 Title 부분에 TitleOfCourtesy라는 부분은 연결시키고 있습니다.
원래 있는 컨트롤에 가져 드래그 해서 가져 가게 되면 위와 같이 커서 모양이 생기게 됩니다.

아래는 직접 메뉴에서 선택한 부분입니다.
사용자 삽입 이미지
해당 컨트롤을 선택하고 DataBindings를 펼친후 Text 부분에서 해당 테이블의 컬럼을 선택해 주고 있습니다. 최초 선택시에는 Other Data Sources 라는 항목만 보이게 되지만 두번째 부터는 위와 같이 employeesBindingSource 라는 항목이 보이게 됩니다.

이 부분 말고도 DataSet 라는 것을 새로 추가 하면서 바로 바인딩이 가능해 지는 방법도 존재를 합니다. 물론 중간 과정들은 중복해서 나오게 되어 있습니다.
Access 파일을 사용할때도 같은 방법으로 바인딩이 가능해 집니다.


장황하게 설명 했지만 2005이상에서는 위와 같이 DB를 윈도우 폼에 연결하는 과정은 조금씩 편해 지는거 같습니다. 그 결과 세부적으로 제어 하는 코드가 어떻게 돌아 가는지 점점더 분석하기 어려워 지는건 아닌가 모르겠습니다.

지금 배우는 입장에서 조금씩 해보고 있는 중이라서 틀린 부분이 존재를 할지도 모르겠습니다. 위와 같이 구성해서 테스트해보면 바로 바인딩 되서 데이터 값이 보여 지는 것을 확인할 수 있습니다.

DB 부분을 새롭게 공부 하고 있거나 공부 내용들을 서로 공유 하고 싶으신 분은 댓글 부탁 드리구요. 잘못된 부분이 있거나 하다면 댓글로 수정 부탁 드립니다.

이상 ^^






Posted by gsi
: