Showing posts with label Languages. Show all posts
Showing posts with label Languages. Show all posts

August 18, 2010

C# Create CSV File using StreamWriter

안녕하세요 이동규(LiveDK)입니다.

 

ListView에 있는 데이터를 파일로 저장하려하는중 엑셀파일을 이용하여 쓰기를 시도하였으나 이는 대상 컴퓨터에 동일한 버전의 Excel 이 설치 되어 있지 않으면 읽고 쓰기에 어려움이 있어 CSV 를 이용하여 파일 작성을 해보았습니다.

 

파일 작성을 위해 StreamWriter 를 이용해보았습니다. 상당히 간단하기 때문에 별다른 설명 없이 코드만 첨부 하겠습니다.

 

StreamWriter sw = new StreamWriter("aa.csv", false, Encoding.Unicode);

foreach (ListViewItem lvi in listView_score.Items)

{

      sw.WriteLine(lvi.Text + "\t" + lvi.SubItems[1].Text);

}

sw.Close();

(코드.1)

 

(출력.1)

 

 

+ 추가1, 각각의 칸이동은(좌우) 탭을 넣어주면됩니다(\t)

+ 추가2, 각줄의 이동은 WriteLine 을 이용하였기 때문에 자동이지요 :) (\r) 하시면 됩니다.

March 5, 2010

C# 인쇄를 해보자

안녕하세요 DKLEE(이동규) 입니다.

 

이번 포스팅에서는 C# 에서의 인쇄기능을 예제를 통해 알아보겠습니다. 인쇄 미리보기를 통해 작업한 내용을 확인해보고 인쇄까지 작동하는 방법을 아래 코드를 통해 확인해 볼 수 있습니다.

 

[code csharp] using System; using System.Drawing; using System.Windows.Forms; using System.Drawing.Printing; namespace ImagePrinting_ex01 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { PrintDocument docToPrint = new PrintDocument(); PageSettings ps = new PageSettings(); ps.Margins = new Margins(10, 10, 10, 10); docToPrint.DefaultPageSettings = ps; PrintPreviewDialog pd = new PrintPreviewDialog(); pd.ClientSize = new Size(500, 500); pd.UseAntiAlias = true; docToPrint.PrintPage += new PrintPageEventHandler(docToPrint_PrintPage); pd.Document = docToPrint; pd.Show(); } void docToPrint_PrintPage(object sender, PrintPageEventArgs e) { Font pf = new Font("궁서", 20, FontStyle.Regular); Image img = Image.FromFile(@"..\..\test.png"); e.Graphics.DrawImage(img, 0, 0, 500, 500); string str = "My name is Dongkyu Lee"; e.Graphics.DrawString(str, pf, Brushes.Black, 10, 500); } } } [/code]

 

아래 그림은 실행되고 있는 모습입니다. 추가한 이미지와 글씨가 바르게 나옴을 확인해 볼 수 있습니다. 인쇄 미리 보기가 실행되며 그안에서 인쇄버튼 / 확대 / 보기방법 을 실행할 수 있습니다.

 

 

 

C# Write Files using FileStream and StreamWriter

안녕하세요 DKLEE(이동규) 입니다.

 

아래의 간단한 예제를 통해 C#에서 파일 작성을 알아보겠습니다.

이전 포스팅에서는 BinaryWriter를 사용 하였지만 이번에는 StreamWriter 를 이용해보겠습니다.

 

[code csharp] using System.IO; namespace FileWrite_ex01 { class Program { private const string file_name = @"c:\test.txt"; //원하는 경로 및 파일명 static void Main(string[] args) { if (File.Exists(file_name)) { return; } FileStream fs = new FileStream(file_name, FileMode.CreateNew); StreamWriter sw = new StreamWriter(fs); sw.Write("DKLEE"); //작성내용 sw.Close(); fs.Close(); } } } [/code]

November 17, 2009

C# Serial Port 통신 - GPS 수신 (버전업)

안녕하세요 DKLEE 입니다.

 

지난 프로그램 과정....

C# Serial Port 통신 - GPS 수신 (1/2)
C# Serial Port 통신 - GPS 수신 (2/2)

C# Serial Port 통신 - GPS 수신 완성

 Serial 통신을 통하여 GPS 모듈로부터 나온는 RAW DATA를 가지고 OPEN API 를 이용해 현재 위치를 지도에 띄우는 작업을 저번부터 해왔었습니다.

 저번 프로그램은 지도와 WinForms 상호간에 데이터가 일방적이였던 반면 이번 프로그램에서는 이를 개선하여 상호간 데이터를 자유롭게 얻거나 설정 할 수 있게 되었습니다. 전체적으로는 달라진게 없어보이지만 앞으로 발전해 나갈 방향을 생각했을땐 상당히 도움이 될것이라 생각됩니다.

 

 우선 저번과 달라진 점은GMap.NET 이라는 Open Source .NET Control 을 사용한점입니다. 이 컨트롤은 WinForms 디자인(도구모음)에서 간단하게 추가하여 사용할 수 있습니다. OPEN MAPS 또한 Google / Bing / Yahoo 등의 일반지도 그리고 위성지도까지 설정, 사용이 가능합니다. 또한 위도,경도 데이터를 바로 집어 넣을 수 있으며, 현재 선택한 위치(위도, 경도)를 간편하게 얻어 올 수 있어서 다양한 용도로 사용이 가능하게 됩니다.

 이전 프로그램의 문제점이 여기에 있습니다. 데이터를 집어넣어 지도에 현재 위치를 나타내기는 쉽지만 얻어오는 과정이 상당히 까다로웠습니다. 이유는 이전 Open API 지도들은 전부 익스플로러의 웹상에서 컨트롤이 가능했기때문에 WinForms 와 연동하기 어려웠기 때문입니다. 하지만 GMap.NET 을 통해 손쉽게 Open API Maps 를 사용할 수 있었습니다.

 

 GMap.NET 의 DLL 을 추가하게 되면 아래와 같이 도구모음에 뜨게되며 속성을 통해 여러 작업을 할 수 있습니다.

 

아래는 위 컨트롤을 간단하게 사용해본 예제 소스입니다.^^

 

 마커는 지도에 현재 위치나 목적지등 압정처럼 생긴 작은 표시를 지도에 표시해주는 기능을 합니다. 오버레이 객체에 삽입 하여 최종적으론 지도 컨트롤에 삽입함으로서 실제로 화면에 표시해 주는 기능을 하게됩니다. 아래는 최종 실행 결과 입니다.

 

 

p.s 굉장히 저의 주관적으로 작성된 프로그램 내용이므로 궁금한 점은 대환영 입니다. 댓글이나 방명록을 통해 물어봐 주시면 감사하겠습니다.

 

September 29, 2009

C# using BitConverter

 안녕하세요 :) 오랜만에 포스팅입니다. 요즘은 일교차가 커지고 날씨도 점점 추워지고 있습니다. 다들 감기조심하세요^^

 

 요즘 MFC 프로젝트를 C# Windows Forms 로 컨버팅 작업을 하고 있습니다. 작업중 memcpy 에서 막혀 조금 고생하다 한방법을 찾아 이렇게 소개합니다.ㅋ

BitConverter
Converts base data types to an array of bytes, and an array of bytes to base data types.

 

 우선 MFC 의 어떤 부분이 저를 괴롭혔는지 아래 코드를 살펴보겠습니다.

unsigned int x = 0; // 0 ~ 4294967295
unsigned char intTochar[4] = {0,};

memcpy(intTochar, &x, 4);

for(int i = 0 ; i < 4 ; i++)
{
     printf("%d\n",intTochar[i]);
}

하고자 하는 사항은 부호없는 정수형(unsigned int) 의 값을 부호없는 문자형(unsigned char) 배열에 담는것입니다. 정수형은 4Byte 이고 문자형은 1Byte 이기때문에 크기가 4인 배열에 담으려고 하는것입니다. C 에서는 memcpy 를 통해 수행이 가능합니다. 아래는 출력 결과 입니다. 부호없는 정수형은 0~4294967295 의 데이터 범위를 가집니다. 0일때와 4294967295 의 출력결과 입니다. 한바이트 씩 출력해보았습니다.

 

 

(변수 x 가 0 일때와 4294967295 출력 결과)

 

 

 다음은 C# 을 통해 위와 같이 구동되는 방법을 알려드리겠습니다. (아래와 같습니다 -_-a 흐흐)

uint x = 4294967295; // 0 ~ 4294967295
byte[] intTochar = new byte[4];

intTochar = BitConverter.GetBytes(x);	

 

참으로 간단합니다.^^ 가끔보면 C# 은 참 매력있는거 같습니다.

BitConverter 에 대하여 더많이 알고 싶다면 (역시 MSDN 이죠?!)

http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

 

 

 

 

 

August 24, 2009

C# and Excel (reading)

이전 포스트 였던 C#을 이용한 엑셀(쓰기) C# and Excel (writing) 에서 이 번 포스팅 에서는 엑셀(읽기)를 해보겠습니다.

이전 포스트와 같은 환경 Microsoft Visual Studio 2008 + Microsoft Office Excel 2007 이며 처음 참조추가 하는 부분은 같습니다. 혹시 이 글을 처음 보신다면 이전 글을 먼저 확인해 보세요^^.

 

역시 이번 포스팅도 상당히 간단하게 끝납니다. 역시 사용법을 몰랐을 뿐이죠…

string conStr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\sample.xlsx;Extended Properties=""Excel 12.0;HDR=YES;""";
OleDbConnection excelConnection = new OleDbConnection(conStr);
excelConnection.Open();

string strSQL = "SELECT * FROM [Sheet1$]";
OleDbCommand dbCommand = new OleDbCommand(strSQL, excelConnection);
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(dbCommand);

DataTable dTable = new DataTable();
dataAdapter.Fill(dTable);

dataGridView_excel_data.DataSource = dTable;

// dispose used objects
dTable.Dispose();
dataAdapter.Dispose();
dbCommand.Dispose();

excelConnection.Close();
excelConnection.Dispose();


1번째 줄에서는

Provider=Microsoft.ACE.OLEDB.12.0; 오피스 버전에 영향을 받습니다.
Data Source=c:\sample.xlsx; 파일경로 입니다.
Extended Properties="Excel 12.0;HDR=YES"; 엑셀을 가르키며, HDR 은 엑셀 데이터의 첫번째 row 를 columnname 으로 지정할지 하지 않을지 결정하게됩니다. YES 는 지정입니다.

2~11번째는 OleDb 커넥,명령 등입니다.

12번째 줄은 폼에서 생성한 DataGridView에 DataSource로 dTable 을 지정하는 부분입니다. 이부분을 지나게 되면 폼에서 DataGridView에 내용이 채워지게 됩니다.

14~20번째는 OleDb 커넥 종료와 Objects 들을 Dispose 하게 됩니다.

 

1번째 줄의 HDR=YES or NO 를 통해 어떻게 바뀌는지 확인해 보겠습니다.

우선 Excel File 윈 원본 데이터를 먼저 보겠습니다.

 

HDR=YES 로 설정한 경우는 아래와 같이 DataGridView 에 컬럼 제목으로 들어가게 됩니다.

 

반면 HDR=NO 로 설정하게 되면 컬럼명은 기본 셋팅값으로 바뀌고 원하던 바로 되지 않고 제목까지 데이터 쪽으로 내려가 버립니다.

 

이제부터는 원하는 부분을 읽어보도록 하겠습니다. (DataGridView 내용에서)

 

//DataGridView 에서 Rows 를 얻어옵니다.
DataGridViewRowCollection rowCollection = dataGridView_excel_data.Rows;
string getStr = rowCollection[1].Cells[3].Value.ToString();

 

row는 열을 가리키며 가로줄 입니다. 1줄에서 데이터그리드로 부터 Rows 를 얻어와 컬렉션에 집어 넣습니다. 이렇게 되면 rowCollection 을 통해 내용을 얻어 올 수 있습니다. 그리하여 다음줄에 인덱스연산을 통해 원하는 부분의 Value 를 얻어 올 수 있습니다.

 

어때요 참 쉽죠?ㅋ

 

또 한번의 간단한 포스팅이 끝났네요^^ㅎ 다음 포스팅에서는 인쇄 작업을 해보겠습니다.

 

 

 

 

 

August 18, 2009

C# and Excel (writing)

안녕하세요 LiveDK 입니다.

이번에 포스트 에서는 닷넷을 통해 엑셀화일을 만들어 보겠습니다.

우선 이번 프로젝트를 만들기위해서 제가 사용하는 프로그램은 다음과 같습니다.

Microsoft Visual Studio 2008 + Microsoft Office Excel 2007

 

처음으로, 윈폼을 하나 생성합니다. 참조추가 를 눌러 COM 탭을 눌러 Microsoft Excel 12.0 Object Library 를 선택하고 확인을 누릅니다.(여기서 저는 Office Excel 2007을 사용하기 때문에 12.0 버전이 나오게 되었습니다.)

 

 

다음으로 코드로 넘어와서 using 을 추가해주어야 합니다. (using 쪽에 아래 코드처럼 대입연산을 통해 하는 과정은 이번에 처음 배웠네요^^)

using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;

이제 디자인으로 넘어와 버튼을 하나 추가하고 더블클릭을 통해 버튼 이벤트를 하나만듭니다. 버튼이 눌렀을경우 다음 코드를 실행하게 해보겠습니다.

Excel.Application xls;
Excel._Workbook wbook;
Excel._Worksheet wSheet;
try
{
   xls = new Excel.Application();

   wbook = (Excel._Workbook)(xls.Workbooks.Add(Missing.Value));
   wSheet = (Excel._Worksheet)wbook.ActiveSheet;

   wSheet.Cells[1, 1] = "Name";
   wSheet.Cells[1, 2] = "Location";

   string[,] saNames = new string[2, 2];

   saNames[0, 0] = "DKLEE";
   saNames[0, 1] = "Asan";
   saNames[1, 0] = "JHKWON";
   saNames[1, 1] = "Seoul";
                                
   wSheet.get_Range("A2", "B3").Value2 = saNames;
                                               
   xls.Visible = true;
   xls.UserControl = true;
}
catch (System.Exception ex)
{
   MessageBox.Show(ex.ToString());
}

 

내용은 다음과 같습니다. 엑셀 Application 을 하나 생성하고 Workbook , Worksheet 을 만들고 그곳에 데이터를 넣는 코드 입니다.  뭐든지 그렇듯이(?) 알기전까진 어렵지만 알고나면 참간단하다고 느끼내요^^

사실 기능이 너무 많이 있지만 간단하게 데이터를 넣는 부분만 해보았습니다.

너무간단히 포스팅이 끝나서 죄송한 마음이네요.

 

참고한 항목으로는 MSDN 입니다. 이곳을 가시면 더 자세한 내용을 확인해 볼 수 있습니다. 계산 그리고 그래프까지 가능하네요^^

C# 한글,영어 문자열 길이 알아보기

훈스닷넷(hoons.kr) 에서 Q&A 게시판을 보다가 한글과 영문길이 체크라는 글을보고 괜찮은 팁이라 생각해서 다시정리하게 되었습니다.

 

질문의 내용은...(원문)

윈폼에서 텍스트박스의 입력된 문자열의 길이를 체크하여 메시지를 띄워주는것입니다.

만약 DB에서 컬럼이 VarChar(10) 일경우 영문은 10자, 한글은 5자 밖에 입력이 되어야하는데...

 

따라서 문자열의 길이를 체크하여 메시지를 띄워주면 문제는 해결되지요

하지만 텍스트박스에 입력된 문자열이 영문인지 한글인지 특수문자인지 알 수 없기때문에

바이트단위로 문자열을 세야 합니다.

 

//영문 10자
string str_e = "abcdefghij";
//한글 5자
string str_k = "가나다라마";

int e, k;
e = str_e.Length;
k = str_k.Length;
//글자의 길이 출력
Console.WriteLine("E:{0} K:{1}", e, k);

e = Encoding.Default.GetByteCount(str_e);
k = Encoding.Default.GetByteCount(str_k);
//바이트단위 길이 출력
Console.WriteLine("E:{0} K:{1}", e, k);

 

 

 

결과는 위와 같습니다. 단순히 Length 를 쓴다면 우리 눈으로 보는 글자수를 출력해 주게됩니다. 하지만 적용해야될 환경의 단위와 다를때는  Encoding.Default.GetByteCount 요놈을 사용하여 글자수를 맞춰줘야 하겠습니다.

 

 

May 29, 2009

C# Serial Port 통신 - GPS 수신 완성

이전 포스트에서 다루었던  C# Serial Port 통신 - GPS 수신 을 완성하였습니다.

C# Serial Port 통신 - GPS 수신 (1/2)

C# Serial Port 통신 - GPS 수신 (2/2)

 

지도는 Google Maps Api 을 이용하였습니다.

 

Serial 통신을 이용하여 받은 내용중

$GPGGA,114455.532,3735.0079,N,12701.6446,E,1,03,7.9,48.8,M,19.6,M,0.0,0000*48

이 데이터를 Parsing 하여 "현재시간, 위도, 경도, 사용위성수" 를 표시하였습니다.

이중에서 위도 경도는 Google Maps API 를 이용하여 지도로 뿌려주었습니다.

참고) 위도 경도 값을 바로 넣어주면 안되고 변환 시켜야 합니다.

C# Serial Port 통신 - GPS 수신 (2/2) 에서 마지막 포인트를 읽어보세요^^

 

시스템은 위와 같습니다.

GPS 모듈을 통해 들어온 데이터를 PC로 전송하기 위하여 MAX232 모듈을 사용하였습니다.

GPS의 TX 를 MAX232 모듈의 RX  그리고 모듈의 TX 를 RS232의 RX 로 연결하였습니다.

 

May 9, 2009

C# using FileStream (Write,Read)


MSDN 에서 보면 "파일에 대해 Stream을 제공하여 동기 및 비동기 읽기/쓰기 작업을 모두 지원합니다."한다고 나와 있습니다.

 

우선 FileStream을 사용하기 위해서는 아래와 같이 추가해주셔야합니다.

using System.IO;

 

기본적으로 아래와 같이 객체를 하나 만듭니다.

FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew);

FILE_NAME : 파일 이름을 적어줍니다 (읽을땐 읽을파일, 쓸땐 쓰고자하는 파일명)

FileMode : 열거형 운영 체제에서 파일을 여는 방법을 지정합니다

<MSDN 발췌>

 

간단한 예제


 

C# Serial Port 통신 - GPS 수신 (2/2)

C# Serial Port 통신 - GPS 수신 (1/2) 에 이어 이번에는 NMEA 프로토콜에 대해서 알아보겠습니다.

 

GPS 를 연결하여 시리얼 통신을 하면 아래와 같은 데이터가 나오게 됩니다.

$GPGGA,134807.000,3732.6627,N,12701.3549,E,1,04,2.6,39.7,M,19.7,M,,0000*69
$GPGSA,A,3,20,28,17,11,,,,,,,,,6.5,2.6,6.0*3D
$GPGSV,2,1,08,17,60,325,22,28,57,210,34,20,52,066,19,04,32,260,*76
$GPGSV,2,2,08,11,30,066,19,23,10,120,18,01,08,062,,02,00,252,*7A
$GPRMC,134807.000,A,3732.6627,N,12701.3549,E,1.58,329.68,110808,,,A*63

이중에서 우리가 봐야 할 부분은

$GPGGA,114455.532,3735.0079,N,12701.6446,E,1,03,7.9,48.8,M,19.6,M,0.0,0000*48

입니다. 하나씩 분석해 보겠습니다. 데이터들은  ,  로 구분 되어 있습니다.

 

114455.532 <- 시간으로 그리니치 표준시 입니다. (11시 44분 55.532초) 따라서 한국의 시간을 구하기위해서는 +9 를 해야겠지요

 

3735.0079 , N<- 이것은 위도로서 37도 35.0079분을 뜻하며 , N 은 북위라는 의미입니다.

 

12701.6446 , E<- 경도를 가르키며 127도 1.6446분을 뜻하며, E 는 동격을 말합니다.

 

1 <- fix종류 입니다.

0 이면 invalid한 데이터(못쓰는 데이터) 라는 의미
1 이면 gps 위성신호만으로 계산
2 라면 dgps도 사용하여 계산 등등이다.

 

03 <- 계산에 사용된 위성의 갯수입니다. 최소한 3개 이상이 되어야 합니다.

 

7.9 <- 위성과 노이즈에 관련자료

 

48.8 M <- 해수면 기준 고도 입니다.

 

19.6 M <- ??

 

0.0,0000 <- dgps를 사용했을경우 마지막으로 update한 시간과 dgps 기지국 ID

 

*48 <- check sum 입니다.

 

http://gpsinformation.org/dale/nmea.htm#GGA

여기를 참조하시면 모든 내용을 보실 수 있습니다(영문)

 

여기서 포인트!!

3735.0079 , N

12701.6446 , E

위와 같이 위도와 경도를 뽑아오게 됩니다. Google Maps API 나 다음 Open Api 를 사용하여 실제 지도에 뿌려주기 외해서는 위의 값을 바로 넣어주면 안됩니다.

37도 35.0079분을 뜻하기 때문에 실제로 값을 넣어 줄때는

37 + (35.0079/60) = 37.583465 이렇게 넣어주셔야 합니다. (경도도 마찬가지 입니다.)

[C++] using Vector

요즘 C# 그리고 Silverlight 에 빠지다 보니 예전에 공부했던 내용들이 가물 가물 하더라구요 그리하여 이번에 차근 차근 보기로 했습니다. 초등학교때 썼던 일기장을 보듯?ㅋ

뜬금없이 Vector 가 나왔습니다. 요것은 Standard Library 에 있는 자료 구조중 하나이며 여러 종류들중 제가 가증 좋아하는 것입니다.

 

우선 vector 를 사용하기 위해서는 아래와 같이 해주셔야 합니다.

이제 본격적으로 사용 예를 보겠습니다.

CD 관리 프로그램으로 설명을 드리겠습니다.

우선은 App , CD 두개의 Class 가 존재합니다.

다음은 Class App 내용입니다.

여기서 vector <CD*> *base; 를 선언하였습니다. < > 여기 사이에 자료형을 넣습니다(여기선 클래스) 이네요 . 그리고 포인터 변수를 선언하였습니다.

실행과 동시에 App 생성자로 들어오게 되며, 이곳에서는 vector 를 초기화 합니다. 그리고 Run(); 을 실행하여 매뉴를 선택할 수 있게 하였고 이곳에서는 삽입,삭제,찾기 등을 할 수 있는 기능을 하게 됩니다.

이제 vector의 중요한 기능들을 보겠습니다.

<삽입>

<전체 출력>

for 문을 순회 하게 되는데 maximum 은 base->size() 로 하였습니다. size()는 vector의 총 크기를 int 형으로 반환해줍니다. 그리고 base->begin()은 vector의 처음을 가르키는데 증가하면서 역참조하여 CD 를 반환해줍니다. 이렇게하여 출력이 간으하게 됩니다. 이런 순회구문을 이용하여 찾기도 가능합니다. strcmp 등을 이용하여 문장을 비교하여 출력해주면 됩니다.

<삭제>

 

전체 출력 결과에서 삭제할 번호를 선택하여 index 에 저장하고 삭제를 하는 과정입니다. index-1 해준 이유는 vector의 시작이 0 부터 시작하기 때문입니다. erase() 를통해 단순히 목록에서 삭제해주기전에 선택한 CD 실제로 메모리 해제를 하기위해 delete 를 사용하였습니다.

 

간단하게 vector에 대해서 알아 보았습니다. 옛기억 새록 새록 나네요^^

April 24, 2009

C# Serial Port 통신 - GPS 수신 (1/2)

요즘 공부하고 있는 GPS 에 대해서...

 

GPS 와 컴퓨터와 통신을 하기 위해서는 RS232 라는 시리얼  포트를 사용하여 통신을 해야합니다. 그를 위해 보통(내가 현재 속해있는 실험실)은 MFC 를 이용하여 연습을 하던데 나는 이번에 C# 을 이용하여 도전하기로 했습니다.

 

우선 이를 위해 알아야할 가장 중요한것은 바로

 

using System.IO.Ports;

SerialPort sp = new SerialPort();

 

시리얼 통신을 하기 위해서는 몇가지 설정을 해주어야 합니다.

통신할 대상에 맞추어(대상 매뉴얼 참조) 셋팅을 해주면 되는데 이번에 사용할 GPS 의 셋팅은 다음과 같습니다.

 

sp.PortName = label_selected_port.Text;
sp.BaudRate = 9600;
sp.Parity = Parity.None;
sp.DataBits = 8;
sp.StopBits = StopBits.One;

 

다음으로 데이터를 읽기위한 이벤트를 추가해주어야 합니다.

sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
//데이터 읽기
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
      this.Invoke(new EventHandler(ReadGPSData));
}

 

여기서 sp.ReadExisting() 요것이 나오게 되는데 이것은 데이터가 있을데 데이터를(String)을 반환해준다. 이렇게 들어온 데이터를 Parsing 하여 원하는 데이터로 가공하면 시리얼 통신의 목적을 달성 할 수 있습니다.

 

private void ReadGPSData(object s,EventArgs e)
{
    string buff;
    buff = sp.ReadExisting();
    if (buff != null)
    {
        richTextBox_data.Text += buff;

        //데이터 처리하기
        ProcessGPSData(buff);
    }
}

 

바로 이벤트안에 코딩하게 되면 프로그램이 "먹통"이 될 수 있으니 잘 처리해야 합니다. Invoke 를 사용 하면 잘 되는군요^^

 

다음으로 GPS에서 나오는 데이터를 보겠습니다.

$GPGGA,134807.000,3732.6627,N,12701.3549,E,1,04,2.6,39.7,M,19.7,M,,0000*69
$GPGSA,A,3,20,28,17,11,,,,,,,,,6.5,2.6,6.0*3D
$GPGSV,2,1,08,17,60,325,22,28,57,210,34,20,52,066,19,04,32,260,*76
$GPGSV,2,2,08,11,30,066,19,23,10,120,18,01,08,062,,02,00,252,*7A
$GPRMC,134807.000,A,3732.6627,N,12701.3549,E,1.58,329.68,110808,,,A*63

GPS를 통해 나오는 값을 보면 위의 데이터가 화면에 주르르르르륵 나오게 됩니다. 여기서우리가 필요한 정보를 얻기 위해서는 파싱을 해야합니다. 우선 위와 같은 데이터는 NMEA라는 하나의 프로토콜? 이라고 할 수 있습니다.

 

여기서 $GPGGA 가 그리니치 표준시, 경도, 위도 의 정보가 담겨 있다고 하네요

 

다음 포스트에는 요것을 Parsing 해볼까요?

C# Serial Port 통신 - GPS 수신 (2/2)

 

 

December 31, 2008

virtual 소멸자

 

상속하고 있는 클래스의 객체소멸시 문제점

  1. #include <iostream>
    using std::endl;
    using std::cout;
  2. class AAA {
        char* str1;
    public:
        AAA(char* _str1) {
            str1=new char[strlen(_str1)+1];
            strcpy(str1, _str1);
        }
        ~AAA() {        //virtual ~AAA()
            cout<<"~AAA() call!"<<endl;
            delete []str1;
        }
        virtual void showString() {
            cout<<str1<<' ';
        }
    };
  3. class BBB : public AAA {
        char* str2;
    public:
        BBB(char* _str1, char* _str2) : AAA(_str1) {
            str2=new char[strlen(_str2)+1];
            strcpy(str2, _str2);
        }
        ~BBB() {
            cout<<"~BBB() call!"<<endl;
            delete []str2;
        }
        virtual void showString() {
            AAA::showString();
            cout<<str2<<endl;
        }
    };
  4. int main(void) {
        AAA* a=new BBB("Good", "evening");
        BBB* b=new BBB("Good", "morning");
  5.     a->showString();
        b->showString();
  6.     cout<<"----객체 소멸 직전 ----"<<endl;
        delete a;
        delete b;
  7.     return 0;
    }

소멸자의 호출에 문제가 있다. 출력내용을보면 BBB클래스의 소멸자가 한번 덜 호출되었음을 볼 수 있다.
위의 예제에서는 AAA타입 포인터 a로 BBB객체를 가리키고 있다. 그리고 53번째 줄에서는 포인터 a를 통한 BBB객체의 소멸을 시도하고 있다. 여기서 바로 문제가 생긴 것이다. 왜냐하면 포인터 a가 가리키는 객체는 BBB객체이지만 AAA타입의 포인터로 가리키고 있기 때문에, 컴파일러는 BBB객체를 AAA객체로 인식한다. 따라서 AAA클래스의 소멸자만 호출이 되는 것이다.

AAA클래스의 소멸자도, BBB클래스의 소멸자도 동적으로 할당한 메모리 공간을 소멸시켜 주는 역할을 하게끔 정의되어 있기 때문에 객체소멸시에는 반드시 둘 다 호출되어야 한다. 하나라도 호출되지 않으면 메모리 유출(누수)이 발생하게 된다.

Virtual 소멸자

AAA클래스의 소멸자를 다음과 같이 변경한다.

  1. virtual ~AAA() {        //virtual ~AAA()
        cout<<"~AAA() call!"<<endl;
        delete []str1;
    }

일단 AAA클래스의 소멸자를 호출하려 든다. 그러나 소멸자가 Virtual인 관계로 Derived클래스의 소멸자를 호출하게 된다. 비록 함수의 이름은 다르지만, 둘 다 소멸자인 관계로 virtual함수를 오버라이딩했을 때의 현상이 그대로 적용되는 것이다. 그 다음 BBB클래스의 소멸자는 AAA클래스를 상속하고 있기 때문에 다시 AAA클래스의 소멸자가 호출된다. 결국 Derived클래스, Base클래스의 소멸자가 모두 호출이 된다.

 

이 글은 스프링노트에서 작성되었습니다.

December 21, 2008

Check File Exsists in C#

using System.IO;

 

File.Exists(string filepath);

 

return 형은 bool 값이다.