[Ruby]WEBrick 서블릿 사용하기

언어로그/Ruby/Rails 2010. 12. 12. 04:37


ruby_servlet_container.rb
#!/usr/bin/ruby

require 'webrick'
include WEBrick

s = HTTPServer.new(:Port => 4000)
class HelloServlet < HTTPServlet::AbstractServlet
	def do_GET(req, res)
		res['Content-Type'] = "text/html";
		res.body = %{
				Hello. You're calling form a #{req['UserAgent']}
				I see parameters: #{req.query.keys.join(', ')}
		}
	end
end

s.mount("/hello", HelloServlet)

trap("INT"){ s.shutdown }

s.start


'언어로그 > Ruby/Rails' 카테고리의 다른 글

자바 개발자를 위한 루비적 관점  (0) 2011.03.04
[Ruby]WEBrick 서블릿 사용하기  (0) 2010.12.12
[Ruby]WEBrick 서버구동  (0) 2010.12.12

[Ruby]WEBrick 서버구동

언어로그/Ruby/Rails 2010. 12. 12. 04:30


ruby_webserver.rb
#!/usr/bin/ruby
require 'webrick'

include WEBrick

s = HTTPServer.new(
  :Port => 3000,
  :DocumentRoot => File.join(Dir.pwd, "/html")
)
trap("INT") { s.shutdown }

s.start

'언어로그 > Ruby/Rails' 카테고리의 다른 글

자바 개발자를 위한 루비적 관점  (0) 2011.03.04
[Ruby]WEBrick 서블릿 사용하기  (0) 2010.12.12
[Ruby]WEBrick 서버구동  (0) 2010.12.12

[Mac]launch daemon vs launch agent

운영체제로그/MacOS 2010. 12. 11. 16:37


운영체제 부팅과 함께 프로그램을 실행시키는 2가지 형태의 방법이 있다. 
launch daemon 으로 실행하는 방법과, launch agent 로 실해하는 방법이 그것인데, 
각각 윈도우에서 서비스 , 시작프로그램으로 실행하는 것과 같다. 

[Launch daemon]
사용자 로그인없이도 실행이 가능하지만,  GUI 상에서 정보를 보여줄 수는 없다. 
웹서버와 데이터베이스 서버 구동을 위해 적합한 방법이라 할수 있겠다.  프로그램들은 plist 설정파일에 
실행할 명령 및 옵션과 함께 기술된다.   /System/Library/LaunchDaemons 폴더에는 애플에서 제공되는 
daemon들을 위한 설정파일이 위치하고, /Library/LaunchDaemons 폴더에는 사용자 및 그외의
 daemon들을 위한 설정파일들이 저장된다. 

[Launch agent]
agent는 사용자를 대신하여 실행되는 프로그램이기 때문에 반드시 사용자가 로그인되어 있어야 한다. 
GUI를 통해 정보를 보여줄 수 있기 때문에,  SNS 애플리케이션과 같이 자주 사용하는 애플리케이션 등록에
적한한 방법이다. 역시 plist 포맷으로 기술되며, 모든 사용자가 공통으로 사용할 프로그램은  /System/Library/LaunchAgents 와 /Library/LaunchAgents 폴더에 설정파일이 저장된다. 사용자별 설정파일은 ~/Library/LaunchAgents 폴더에 저장된다. 

'운영체제로그 > MacOS' 카테고리의 다른 글

[Mac]launch daemon vs launch agent  (0) 2010.12.11
[Mac]시작프로그램/Script 등록하기  (0) 2010.12.11

[Mac]시작프로그램/Script 등록하기

운영체제로그/MacOS 2010. 12. 11. 15:43


Mac에서 시작 프로그램를 다음과 같이 등록할 수 있다.

시스템 환경설정(System Preferences) > 계정설정(Account) > "로그인 항목" 에

부팅완료 후 자동실행을 할 애플리케이션을 추가하거나 삭제할 수 있다.

MySQL을 설치하고, MySQL 서버를 시작과 동시에 구동하려 했는데... 위 항목에서는

스크립트를 추가할 수가 없었다.

launchd를 사용하여 데몬으로 시작시키는 방법을 알아보았다~

1 PropertyEditor 를 실행시켜서 아래와 같이 입력한다.


2. com.mysql.mysqld.plist 라는 이름으로 저장한다.

3. 이 파일을 /Library/LaunchDaemons 폴더로 복사한다.

4. 파일의 소유자와 그룹, 권한을 다음과 같이 변경한다.

$cd /Library/LauchDaemons$sudo chown root com.mysql.mysqld$sudo chgrp wheel com.mysql.mysqld$sudo chmod 644 com.mysql.mysqld

5. sudo launchctl load com.mysql.mysqld.plist 명령을 수행하여, launchd 에 작업을 등록한다.

* plist 파일에 지정합 키-값은 launchd 에 의해 미리 정해진 옵션으로 Program을 daemon으로 수행하기 위한 옵션으로 작용한다.

plist 파일을 변경하고, 다시 적용하기 위해서는 먼저 launchctl unload com.mysql.mysqld.plist 명령으로 언로드를 수행하고 다시 적용시켜야한다

디폴트로 mysqld 는 /etc/my.cnf 파일에 정해진 설정을 읽어서 구동되는데, 이 파일에 옵션을 줄 수도 있지만, plist 파일을 사용하면

모든 설정을 한곳으로 모을수 있는 장점이 있다. mysqld 에 줄수 있는 옵션들은 /etc/my.cnf 파일을 열어 확인을 하고,

plist 파일의 ProgramArguments 키의 array 값의 인자로 지정을 하면된다.

plist 파일의 추가할 수 있는 키옵션들은 man launchd.plist 명령을 통해 확인하자.

'운영체제로그 > MacOS' 카테고리의 다른 글

[Mac]launch daemon vs launch agent  (0) 2010.12.11
[Mac]시작프로그램/Script 등록하기  (0) 2010.12.11

프로그래머의 길 멘토에게 묻다.

북로그 2010. 12. 10. 23:56


1장 들어가는 글

  • 소프트웨어 장인정신이란 무엇인가?
  • 견습과정이란 무엇인가?
  • 견습과정 패턴이란 무엇인가?
  • 패턴들은 어디시 비롯 되었는가?
  • 여기서 이제 어디로 가는가?


2장 잔을 비우다

  • 첫 번째 언어
  • 흰 띠를 매라
  • 열정을 드러내라
  • 구체적인 기술
  • 무지를 드러내라
  • 무지에 맞서라
  • 깊은 쪽
  • 한발 물러서라


3장 긴 여정을 걷다

  • 긴 여정
  • 예술보다 기예
  • 지속적인 동기부여
  • 열정을 키워라
  • 자신만의 지도를 그려라
  • 직위를 지표로 이용하라
  • 전장에 머물러라
  • 또 다른 길


4장 정확한 자기 평가

  • 가장 뒤떨어진 이가 되라
  • 멘토를 찾아라
  • 마음 맞는 사람들
  • 팔꿈치를 맞대고
  • 바닥을 쓸어라


5장 끊임없는 학습

  • 능력의 폭을 넓혀라
  • 새로운 정보를 얻고자 자기 능력의 폭을 넓히는 단계는 견습생에게 아주 중요하며, 다양한 차원에 걸쳐서 새로운 지식과 경험을 찾아가는 활동을 수반한다. 몇가지 사례로
  • 구글리더 같은 구독기로 소프트웨어 개발 블로그를 구독하라. 팀 오라일리가 ' 알파 긱'이라 불렀던 블로거들을 구독해보라
  • 트위터에서 소프트웨어 분야쪽으로 유명한 사람들을 팔로우하고, 관심있는 분야에 주의를 기울여라
  • 최근에 만들어진 신기술 로컬 유저그룹에 참여하고, 주최자에게 자신을 소개하고 도움을 주어라
  • 기술적인 컨퍼런스에 참석하고, 웹사이트의 슬라이드, 오디오, 동영상 등을 참고하라
  • 온라인 대학강좌, 아이튠즈, 유투브 , Google Talk 등 무료로 접할 수 있는 동영상을 보아라

연습, 연습, 또 연습
  • 코드카타는 연습하고 연습하고 또 연습하는 방법 중 하나일 뿐이며, 핵심은 스트레스 없고 쾌활한 분위기에서
  • 소프트웨어를 개발할 수 있는 시간을 스스로 개척해 가는 것이다. 그리고 연습시간에 짧은 피드백 루프를 같이 짜 넣는 것이 좋다. 수련시간에 사용할 흥미로운 과제들은 Programming Pearls, More Programming Pearls, Etudes for Programmers 같은 오래된 책을 통하여 확보하는 것도 좋은 방법 중 하나이다.

부숴도 좋은 장난감
  • 실패는 종종 무언가를 배울 수 있는 가장 좋은 방법이 된다. 오직 과감한 일을 하고, 실패하고, 그 실패로부터 학습하고, 또 다시 시도하는 것, 우리는 그렇게 해야만 어려운 문제에 맞닥뜨렸을 때 성공해 내는 사람으로 성장 할 수 있다.
  • 공 세개로 저글링할 줄 아는 사람이 다섯 개짜리 저글링을 전혀 시도하지 않으면, 그는 결코 한단계 더 올라서지 못할것이다.
  • 이 패턴을 사용하는 고전전인 예로 자신만의 위키을 만들었던 사람들을 들 수 있다. 위키는 놀라우리만치 간단한 모양이 될 수 있으며, 추후에 HTTP, REST, 파싱, 웹설계, 캐싱, 전문(full-text검색), 데이터베이스, 동시성을 배울 수 있다.
  • 또 다른 예로, 테트리스, 틱택토, 블로깅 소프트웨어, IRC 프로그램 등이 있다. 이것들은 본시 장난감이기 때문에 재미있어야 한다는 것을 잊지말고, 재구현하면서 그 도구가 지금의 설계에 이를 수밖에 없었던 이유를 깊이 생각해보자

소스를 활용하라
  • 다른 사람들의 코드를 찾아서 읽어라. 당신이 매일 사용하는 도구나 애플리케이션부터 시작해보라

  • 그 사람들의 코드를 읽고서, 그들처럼 프로그래밍 하는 법을 배우고, 개발자들이 코드를 그런식으로 모듈화한 이면에 무슨 이유라도 있는지 찾아보고, 당신이라면 어떻게 했을지 비교해 보라. 어떤 까닭에 그런 선택을 했는지 이해하기 위해서, 코드의 리팩터링을 시도해보고, 그 기능을 당신이 장난감으로 구현해서 통합해 봤을 때 교육적
    가치가 있을지 생각해보라. 시간이 지나면서 사람들이 작성한 코드로부터 그 의도를 꿰뚫어 보는 능력을 키울 수 있을 것이다.

  • 패턴, 관용어법, 우수한 사례들에 대해 배우는 가장 좋은 방법은 오픈소스 코드를 읽는 것이다.
  • 이 방법은 소프트웨어 개발 분야에 훌륭한 교사가 부족하다는 점을 보완해주면서, 프로젝트에 속한 개발자들이 학습하고 새로운 요구사항에 대응해 가는 과정을 추적해 나갈 수 있다. 알고리즘이 복잡한 오픈소스 프로젝트를 골라, 그 소스를 둘러보면서 생소한 알고리즘이나 자료구조, 설계사상을 기록한 후, 그 프로젝트 구조를 기술하고 새로 알게된 아이디어를 블로그에 포스트해보자

일하면서 성찰하라
  • 사색하는 소프트웨어 개발자가 되어라. 그러려면 일상에서 당신이 어떻게 일하고 있는지 스스로 성찰해야 한다.
  • 우리의 목표는, 매일 쌓은 경험을 낱낱이 분해한 다음 새롭고 흥미로운 방법으로 재조립하여 그런 일상의 경험으로부터 최대한의 교육적 가치를 얻어 내는 것이다. 당신이 일하는 습관을 조사하고 적응시키고, 개선하는데 들인 모든 노력에 대한 의미있는 증거는, 오직 기술 수준의 향상뿐이다.

배운 것을 기록하라
  • 당신이 걸아가는 여정의 기록을 일지나, 개인위키, 블로그 등으로 남겨라. 배운 교훈을 시간 순으로 기록하게 되면 걸어온 여정을 뚜렷이 볼수 있으므로, 멘토링하는 사람들에게 영감을 줄 수 있다. 당신이 썼던 글을 정기적으로 다시읽고, 리뷰함으로써, 당신은 미래를 만들어 내기위해 과거와 현재를 재배치 할 수 있다.

배운 것을 공유하라
  • 배운 것을 정기적으로 공유하는 습관을 견습과정 초기에 들여놓아라. 이것은 블로그를 운영하는 형태든, 컨스런스에서 발표하거나 학습중인 기술에 대한 튜토리얼을 쓰는 형태도 될 수 있다.
  • 혼자 힘으로 배우는 것과 그렇게 익힌 새 지식을 공유하는 것 둘다를 가치 있게 여기는 개인들이 모인 커뮤니티의 일원이 된다는 것은 견습과정이 가진 가장 강력한 측면이다.
  • 게다가 누군가를 가르친다는 것은 가르침 받는 사람보다도 가르치는 사람에게 더 강력한 학습 도구가 된다.
피드백 루프를 만들어라
  • 당신의 수행능력을 평가하는데 어느정도 객관성 있는 외부 데이터를 정기적으로 수집할 방안을 마련하라. 피드백을 얻는 얻는 방식에는 여러가지가 있는데, 테스트 주도개발이나, 대화식 인터프리터가 있는 동적타입 검사형 언어를 써서 당신이 짠 프로그램이 일찍 실패하도록 하는 기법이 있다.
  • 성공적인 견습생들이라면, 어떤 행동을 더 할지 덜 할지 결정하기 위한 데이터를 신속하고도 자주 얻는 상황을 조성하는 법을 배운다. 전투의 절반은 될 수 있는 한 빨리 나에게 애기해 줄 누군가를 찾는 일이다.

실패하는 법을 배워라
  • 사실 무언가를 한번도 실패해 본적이 없는 사람이라면, 그는 자기 능력의 한계치까지 밀어붙이기를 피해 왔거나 자기 실수를 대수롭지 않게 여기도록 배운 사람이다. 당신이 어떤 식으로 실패하곤 하는지 확인하고, 고칠 부분을 바로 잡아라.
  • 이 패턴의 목표는 당신을 실패로 이끌어 가는 방식, 조건, 습관, 행동 양식이 무엇인지 스스로 인식하는데 있다. - 당신에게는 잘 못하는 일, 좀 더 잘하려면 너무 많은 시간과 노력을 투자해야 하는 일들도 있다는 사실을 받아들여라.


6장 학습 과정의 구성


독서목록
  • 읽기로 한 책들을 추적해 갈 독서목록을 유지하고, 다 읽은 책은 언제 읽었는지와 함께 기억해 두라
  • 과거의 독서습관을 성찰하고, 지식의 홍수 속에서 우선순위를 매기며 걸러내는 방법이 된다.
  • 다음으로 읽어야 할 책은 곧 당신을 이 여정에서 더 멀리 내딛도록 해주는 책이다. 다음에 무엇을 학습해야할지 결정하는 사람은 바로 당신이어야 하며, 적절한 책을 적절한 시점에 읽는 것 역시 중요하다

꾸준히 읽어라
  • 긴 여정 중에는 상당한 양의 책을 읽을 기회가 있다. 몰두할 때, 학계라는 광대한 지식의 창구를 탐구하는 것이 필요하다
  • 정기적으로 발간되는 연구 논문집을 읽으며 당신의 정신세계가 확장되고, 전산학의 최첨단 이슈에 계속 접할 수 있으며, 도전적인 새 아이디어 원천이 되기도 한다. 다음에 무슨 책을 읽을지, 지금 결정하라

고전을 공부하라
  • 당신의 직업이나 관심분야에서 위대한 저작들, 즉 지금까지 있었던 가장 훌륭한 책과 기사, 연설문 등을 찾아서 그것을 진지하게 공부하기 시작하라- 조슈아 케리에브스키 -
  • 제일 훌륭한 것들만 읽어라. 하지만 너무 거기에만 몰두한 나머지 일상에서 장인정신을 발전시킬 실용적인 지식과 정보를 등한시 하는 우둔을 범하지 마라

더 깊이 파고들어라
  • 도구나 기술분야, 각종 기법 같은 것을 깊이 파고드는 법을 배워라. 여기서 깊이라 함은 세부적인 설계보다는 그런 설계에 이르게 한 요인을 이해하는 것을 의미한다.
  • 당신이 사용하는 기술분야에 대한 명세서, RFC, 표준문서 같은 것을 읽어라. 어떤 개념을 정말로 이해하려면 그 개념이 최초로 언급된 당신의 전후 맥락을 재구성해 볼 필요가 있다. 그 아이디어를 누가 처음 생각해 냈는지 조사해 보고, 그들이 풀려고 했던 문제가 무엇이었는지 이해하라
  • 당신이 학습중인 주제의 이면에 혹시 어떤 전산학적 개념이 깔려 있을지, 그리고 그 개념과 당신이 사용중인 구현본 사이에는 어떤 절충이 이루어졌는지 알아보라

익숙한 도구들
  • 익숙한 도구들을 선별해서 거기에 집중하라.
  • 때로는 일을 하기에 가장 알맞은 도구와 당신에게 가장 익숙한 도구가 다를 수도 있다.
  • 당신의 경력이 성공적이려면, 익숙한 도구들을 쉽게 얻고 쉽게 버리는 법을 배워야 한다.
  • 당신에게 익숙한 도구들의 목록을 적고, 그 도구를 학습할 계획을 세우고 오늘부터 실천하라.
  • 정보를 조직하고 수집하는 강력한 도구를 휘두를 수 있는 개발자로 성장해 가기 위해서, 당신은 계속되는 자기 교육의 과정에 능동적으로 참여할 필요가 있다.


'북로그' 카테고리의 다른 글

북로그  (0) 2011.02.14
프로그래머의 길 멘토에게 묻다.  (0) 2010.12.10
사랑하지 않으면 떠나라!  (0) 2010.12.10

비트필드

언어로그/C/C++ 2010. 12. 10. 20:07

구조체 포인터

struct  _STUDENT {
    char name[20];
int kor, eng, math, science, tot, grade;
    double avg;
} STUDENT;


STUDENT student[3];
STUDENT *ps = &student;

student[i].name  ==  (*(ps + i)).name == (ps + i)->name
  • 구조체 포인터를 사용하여 멤버에 접근하기 위해서, (->) 연산자를 사용한다.
  • student 구조체의 name 멤버에 접근하기 위해, 위와 같이 다양한 방법을 사용할 수 있다.


패딩(Padding) 바이트

  • 컴퓨터가 다루는 데이터의 단위를 워드라고 한다. 흔히 32비트 컴퓨터, 64비트 컴퓨터 하는데, 이때의 비트가 바로 워드이다.
  • 멤버들이 서로 다른 크기를 갖는 구조체의 경우, 32비트의 컴퓨터의 경우 1워드인 4바이트씩 데이터를 읽게 된다.
  • 하지만 4바이트 보다 적거나 큰 데이터를 읽기 위해선 1번 또는 2번을 읽어 경계에 있는 비트들을 합쳐줘야 하는 번거로운 연산을 추가적으로 해야한다.
  • 이런 번거로움을 덜기위해 추가적인 패딩 바이트를 붙여서 워드 단위로 좀 더 빠르게 읽을 수 있게 한다.
typedef struct {
    char ch;
    int i;
    double d;
} TYPE1;

typedef struct {
    int i;
    char ch;
    double d;
} TYPE2;


typedef struct {
    double d;
    char ch;
    int i;
} TYPE3;

typedef struct {
    char ch;
    double d;
    int i;
} TYPE4;
  • 패딩바이트를 보기위해 4개의 구조체를 위와 같이 선언을 하고, 그 크기를 다음과 같이 출력해보았다.
printf("TYPE1 : %d \n", sizeof(TYPE1));
printf("TYPE2 : %d \n", sizeof(TYPE2));
printf("TYPE3 : %d \n", sizeof(TYPE3));
printf("TYPE4 : %d \n", sizeof(TYPE4));  

그 결과는 다음과 같다.

TYPE1 : 16

TYPE2 : 16 

TYPE3 : 16

TYPE4 : 24  
  • int형 4바이트, char형 1바이트, double형 8바이트 총 13바이트가 출력되야 하지만, 그렇지 않다.


비트 필드 (bit field)

  • 구조체 비트 필트는 파일에 대량의 데이터를 저장할 때, 소모되는 메모리 공간을 줄이기 위해 구조체 멤버들에게 비트단위로 공간을 할당하여 메모리를 사용하는 방법이다.
  • 소량의 데이터를 다룰 때는 비트필드 처리를 위한 부가작업으로 오히려 득보다는 실이 많게 됨을 주의하자

(0~9999)년 (1-~12)월 (1~31)일에 대한 정보를 갖는 데이터를 저장하려 할 때, 모두 4바이트 정수형으로 정의하지 않고, 갖을 수 있는 데이터의 범위를 고려해 year는 15비트, month에 4비트, day에 비트를 할당한 비트 필드는 다음과 같다.

typedef struct {
    unsigned int year : 15;
    unsigned int month : 4;
    unsigned int day : 5;
} NEW_DATE;

콜론(:) 다음에 해당하는 멤버에 할당되는 비트수를 명시해준다. 비트필드는 unsigned 타입에만 지정할 수 있다. 위와 같은 선언은 다음과 같은 메모리 구조를 가지게 된다.



  • 주의할 점으로 비트필드로 선언된 구조체에는 scanf 를 사용하여 입력을 받을 수 없다.
  • scanf는 인자로 메모리의 주소를 받지만, 주소는 바이트 단위단위로 할당되기 때문에 비트 단위로 설정되기 때문이다.
  • 그래서 위와 같은 경우 int 형 임시변수를 선언하고 scanf로 입력받은 후, 비트필드의 멤버에 할당하는 방법 사용한다.
  • 하지만 이때도, 4바이트 데이터가 비트필드로 할당시 메모리 잘림현상이 발생하기 때문에, 데이터 손실하 않도록 주의해야 한다.


'언어로그 > C/C++' 카테고리의 다른 글

C 프로그램 실행과정  (0) 2011.02.22
C 언어란?  (0) 2011.02.22
비트필드  (0) 2010.12.10
함수의 이해 / 데이터 전달  (0) 2010.12.10
과제 #3 함수, 포인터의 사용  (0) 2010.12.10
과제#4 배열과 문자열  (0) 2009.10.03

함수의 이해 / 데이터 전달

언어로그/C/C++ 2010. 12. 10. 19:50

1. 함수가 필요한 이유?

  • 중복된 작업을 함수로 분리하면, 한번 작성으로 여러번 사용할 수 있어서 효율적인 프로그램이 된다.
  • 또한 큰 문제를 작은 문제들로 나누어 이해하기 쉬워지며, 수정사항이 발생하면 함수 부분만 수정하면 되기 때문에 유지보수도 용이해진다.


2. 함수의 원형(프로토타입)과 정의

  • C언어에서 함수는 원형(프로토타입)과 정의로 분리된다.
  • 함수의 원형(프로토타입)은 보통 헤더파일이나 메인함수 이전에 선언이 되며, 컴파일러에게 이러 이러한 함수를 아래에 정의했으니까 메인함수 또는 특정함수에서 이 함수를 사용해도 됨을 알려주는 것이다.
  • 함수의 정의는 실제적으로 함수가 하는 일을 기술하는 부분이다. C언어에서는 함수의 시그니처로 함수의 이름만을 사용하기 때문에, 파라미터의 타입과 반환값의 타입이 달라도 동일한 이름의 함수를 사용 할 수 없다.
#include <stdio.h>

void swap(int , int);// 함수원형(프로토타입)   

int main() {
...

return 0;

}
void swap(int a, int b) {   // 함수의 정의         
...

}  


3. Call By Value vs Call By Reference

  • 함수 호출시 파라미터를 넘기는 방식에 따라 Call By Value 또는 Call By Reference 라고 구분한다.
  • 함수 호출시 변수들의 데이터(값)가 복사되는데, 함수 내에서 이 복사된 변수에 대한 조작은 원본 변수에 아무런 영향을 미치지 못하는데 이러한 호출방식을 Call By Value라고 부른다.
  • 파라미터로 변수의 주소를 넘기면, 피호출자 쪽에서는 이 주소를 조작하여 원본 변수의 데이터를 변경할 수 있다. 이러한 호출방식을 Call By Pointer 또는 Call By Reference 라고 부른다.


Call By Value

main() {
    int a = 1, b = 5;

    swap(a, b);// 변수의 값을 전달함 

    }
    void swap(int a, int b)  {// main함수의 a, b는 변경되지 않음    
    int temp = a;

    a = b;

    b = temp      

}


Call By Reference

main()  {
   int a = 1, b = 5;
   swap(&a, &b);// 변수의 주소를 전달함    

}

void swap(int *a, int *b)  { // main함수의 a, b가 변경됨    
    int temp = *a;
    *a = *b;
    *b = temp;
}


'언어로그 > C/C++' 카테고리의 다른 글

C 프로그램 실행과정  (0) 2011.02.22
C 언어란?  (0) 2011.02.22
비트필드  (0) 2010.12.10
함수의 이해 / 데이터 전달  (0) 2010.12.10
과제 #3 함수, 포인터의 사용  (0) 2010.12.10
과제#4 배열과 문자열  (0) 2009.10.03

정규표현식(Regular Expression)

기타 2010. 12. 10. 14:27




'기타' 카테고리의 다른 글

지갑  (0) 2011.05.26
2011년 자바 개발자 컨퍼런스 등록!!  (1) 2011.05.23
Base64 Encoding  (0) 2011.02.18
muju  (33) 2011.02.14
정규표현식(Regular Expression)  (0) 2010.12.10
MD5(Message-Digest algorithm 5)  (0) 2010.12.10

과제 #3 함수, 포인터의 사용

언어로그/C/C++ 2010. 12. 10. 14:25

1. 최대값과 최소값을 구하는 함수

  • 세 개의 정수를 입력받아서 그중 가장 큰 수를 반환하는 함수와 가장 작은 수를 반환하는 함수 작성.

입력

  • 세 개의 정수 입력 : 7 4 9

출력

  • 최대값 : 9
  • 최소값 : 4

코드

/*
    입력: 세 개의 정수 
    출력: 가장 큰수와 가장 작은 수 
    조건: 가장 큰수를 반환하는  함수 
        가장 작은수를 반환하는 함수 작성  
*/

#include <stdio.h>

int max_num(int a, int b, int c);
int min_num(int a, int b, int c);

int main (int argc, char const* argv[])
{
    int a, b, c, max, min;

    printf("세 개의 정수 입력 : ");
    scanf("%d %d %d", &a, &b, &c);

    max = max_num(a, b, c);
    min = min_num(a, b, c);

    printf("\n최대값 : %d\n", max);
    printf("\n최소값 : %d\n", min);

    return 0;
}

int max_num(int a, int b, int c) {
    int temp = a > b ? a : b;
    return temp > c ? temp : c;
}


int min_num(int a, int b, int c) {
    int temp = a < b ? a : b;
    return temp < c ? temp : c;
}  



2. 온도변환 : 화씨와 섭씨 변환 함수

  • Fahrenheit 함수 : 섭씨온도를 입력하면 화씨 온도로 변환
  • Celsius 함수 : 화씨 온도를 섭씨 온도로 변환
  • 공식 : F = 1.8 * C + 32
## 온도 변환 ##  
1) 섭씨 입력  
2) 화씨 입력

## 메뉴선택: 1
입력:
섭씨 입력:  32

출력:
변환된 화씨 : 89.60

코드

/*
    입력: 섭씨온도 또는 화씨온도 
    출력: 섭씨온도 또는 화씨온도 
    조건: 섭씨온도는 화씨온도 / 화씨온도는 섭씨온도로 변환하는 함수 작성 
*/

#include <stdio.h>

double fahrenheit_to_celsius(double f);
double celsius_to_fahrenheit(double c);

int main (int argc, char const* argv[])
{
    double input, output;
    int select;

    printf(" ### 온도 변환 ### \n\n");
    printf("1) 섭씨 입력 \n");
    printf("2) 화씨 입력 \n");
    printf("\n메뉴 선택 : ");

    scanf("%d", &select);

    if (select == 1) {
        printf("\n섭씨입력 : ");
        scanf("%lf", &input);
        output = celsius_to_fahrenheit(input);
        printf("변환된 화씨 : %.2lf \n", output);
    } else if (select == 2) {
        printf("\n화씨입력 : ");
        scanf("%lf", &input);
        output = fahrenheit_to_celsius(input);
        printf("변환된 섭씨 : %.2lf \n", output);
    }

    return 0;
}

double fahrenheit_to_celsius(double f) {
    double c = (f - 32) / 1.8;
    return c;
}

double celsius_to_fahrenheit(double c) {
    double f = 1.8 * c + 32;
    return f;
}  



3. 최대값과 최소값의 주소를 반환하는 함수

  • 세 개의 정수를 입력 받아서 그 중 가장 큰 수의 주소를 반환하는 함수와 가장 작은수의 주소를 반환하는 함수를 작성 (입출력은 #1과 동일)
int *MAX(int *, int *, int *);  
int *MIN(int *, int *,  int *);

코드

/*
    입력: 세 개의 정수 
    출력: 가장 큰수, 가장 작은수 
    조건: 가장 큰수의 주소를 반환하는 함수 
       가장 작은수의 주수를 반환하는 함수 작성 
*/

#include <stdio.h>

int* max_num_addr(int *a, int *b, int *c);
int* min_num_addr(int *a, int *b, int *c);

int main (int argc, char const* argv[])
{
    int a, b, c, *max, *min;

    printf("세 개의 정수 입력 : ");
    scanf("%d %d %d", &a, &b, &c);

    max = max_num_addr(&a, &b, &c);
    min = min_num_addr(&a, &b, &c);

    printf("\n최대값 : %d\n", *max);
    printf("최소값 : %d\n", *min);

    return 0;
}

int* max_num_addr(int *a, int *b, int *c) {
    int *temp = *a > *b ? a : b;
    return *temp > *c ? temp : c;
}


int* min_num_addr(int *a, int *b, int *c) {
    int *temp = *a < *b ? a : b;
    return *temp < *c ? temp : c;
}



4. 반올림 계산 함수

  • 양의 부동소수점 수를 받아서 소수점 셋째 자리에서 반올림 하는 함수 작성

입력

  • 양의 부동소수점을 입력 하시오 : 123.456789

출력

  • 반올림 결과 : 123.460000

문제해결

  • 소수점 셋째자리 반올림을 위해, 1000을 곱한다. 그리고 1의 자리 수가 5이상이면 10을 더하고, 1의 자리 수를 버린다. 이 수를 다시 1000으로 나누면 소수점 셋째 자리에서 반올림한 결과를 얻을 수 있다.

코드

/*
    입력: 양의 부동소수 점 
    출력: 소수 셋째 자리까지 반올림 된 수 (소수 6째 자리까지 출력) 
    조건: 
*/

#include <stdio.h>

#define SPACE 1000.0

double roundTwo(double x);

int main (int argc, char const* argv[])
{
    double input, output;

    printf("양의 부동소수점을 입력하시오 : ");
    scanf("%lf", &input);

    output = roundTwo(input);

    printf("\n반올림 결과 : %.6lf \n", output);

    return 0;
}

// 소수 3째 자리에서 반올림  
double roundTwo(double x) {
    int temp  = (int)(x * SPACE);

    if (temp % 10 >= 5) {
        temp += 10;
    }
    temp -= (temp%10); 

    return temp / SPACE;
} 



5. 이진수를 십진수로 변환하는 함수

  • 사용자로 부터 이진수를 입력 받아서 십진수로 변환하는 프로그램을 작성.
  • 사용자로부터 이진수를 입력받는 함수 (입력값이 0과 1로만 이루어져 있는지 판별)
  • 이진수를 십진수로 변환하는 함수

입/출력

이진수를 입력하시오 (0 또는 1) : 123
이진수가 아닙니다. 0 또는 1만 입력하시오.

이진수를 입력하시오 (0 또는 1) : 1010

입력한 이진수 : 1010
변환된 십진수: 10  

문제해결

  • 이진수 여부를 판별하기 위해서는 입력된 수의 각 자리수가 0 또는 1이어야 한다. 각 자리 수 확인을 위해 입력된 수를 10으로 나눈 나머지를 통해 각 자리수를 확인할 수 있다. 이진수를 십진수로 변경은 이진수 각 자리수에 대해서 2를 자리수만큼 곱한 것들의 합으로 구할 수 있다. 이 때 2의 자리수만큼의 곱은 시프트 연산으로 대신해 코드를 간결하게 할 수 있다.

코드

/*
    입력: 이진수
    출력: 십진수 
    조건: 이진수를 입력받는 함수 
        이진수를 십진수로 변환하는 함수 작성 
*/

#include <stdio.h>

#define TRUE 1
#define FALSE 0

int input_binary(int *input);
int binary_to_decimal(int binary);

int main (int argc, char const* argv[])
{   
    int input, output;

    while (input_binary(&input) == FALSE) {
        printf("이진수가 아닙니다. 0 또는 1만 입력하시오. \n\n");
    }
    output = binary_to_decimal(input);

    printf("입력된 이진수: %d \n", input);
    printf("변환된 십진 수 : %d \n", output);

    return 0;
}

// 이진수를 입력받고, 검사 
int input_binary(int *input) {  
    int temp;

    printf("이진수를 입력하시오 (0 또는 1) : ");
    scanf("%d", input);

    temp = *input;  
    while (temp != 0) {
        if (temp % 10 > 1) {
            return FALSE;
        }
        temp /= 10;
    }
    return TRUE;
}

// 이진수를 십진수로 변환 
int binary_to_decimal(int binary) {
    int decimal = 0, b = binary; 
    int i, rem;

    for (i = 0; b != 0; i++) {
        rem = b % 10;
        rem = rem << i;
        decimal += rem;
        b /= 10;
    }

    return decimal;
} 


'언어로그 > C/C++' 카테고리의 다른 글

C 프로그램 실행과정  (0) 2011.02.22
C 언어란?  (0) 2011.02.22
비트필드  (0) 2010.12.10
함수의 이해 / 데이터 전달  (0) 2010.12.10
과제 #3 함수, 포인터의 사용  (0) 2010.12.10
과제#4 배열과 문자열  (0) 2009.10.03

MD5(Message-Digest algorithm 5)

기타 2010. 12. 10. 01:58

MD5(Message-Digest algorithm 5)

임의의 길이의 메시지를 입력받아, 128비트 짜리 고정길이의 출력값을 내는 암호화 해시함수. 역함수가 존재하지 않는 함수이다. 역함수가 존재하지 않는 함수라는 것은, 동일한 키를 알지 못한다면, 해싱된 결과로 키를 유추해 낼수 없다는 의미이다. 주로 파일의 내용이 변경됐지는 여부를 검사하기 위해 사용된다고 한다.


URL인코딩

HTTP 프로토콜에서 URL 에 주소를 지정할 때, 공백과 같은 특수문자를 포함할 수 있게 하기 위해서 만들어진 인코딩 방식으로, 알파벳과 수, @, .(dot) 문자들을 제외한 특수문자들을 아스키값을 2개의 16진수 문자로 표현하고, 앞에 %문자를 붙여 표현한 인코딩방식이다. 이 인코딩 방식을 적용하면, 아스키값 32를 값는 공백문자는 %20으로 표현된다. 인코딩된 문자열을 디코딩하면 원래의 문자열로 복원할 수 있는데, %를 포함한 3문자를 읽어서 16진수를 10진수로 변환하면 원래 문자를 얻을 수 있다. 다음은 URL인코딩과 디코딩을 수행하는 c 함수이다.

char * URLEncode(const char *origin)
{
    char *decoded, *src, *dst;
    int cntOfPercent = numOfEncodingChar(origin);  // 인코딩을 적용할 문자의 수 카운트
    src = origin;
    decoded = dst = (char*)malloc(strlen(origin) + 1 + cntOfPercent*2);  // 메모리 할당
    while (*src != '\0') {
        if ( (*src >= 'A' && *src <= 'Z') || (*src >= 'a' && *src <= 'z') ||
            (*src >= '0' && *src <= '9') || (*src == '@' || *src == '.') ) {
            *dst++ = *src++;// 인코딩 적용이 안되는 문자는 그대로 복사

        } else {
            *dst++ = '%';// %문자를 붙히고,
            sprintf(dst, "%02X", *src++);            // 16진수로 변환

            dst += 2;
        }
    }
    *dst = '\0';      // 널문자로 종료
    return decoded;
}


char * URLDecode(const char *encoded)
{
    char *decoded, *src, *dst;
    int cntOfPercent = numOfPercent(encoded);// %문자의 개수를 카운트
    src = encoded;
    decoded = dst = (char*)malloc(strlen(encoded) + 1 - cntOfPercent*2); // 메모리 할당

    while (*src != '\0') {
        if (*src == '%') {// %를 만나면 이후 2문자를 10진수로 변환
            src++;
            if (*src >= 'A' && *src <= 'F') {
                *dst = *src++ - 55;
            } else if (*src >= 'a' && *src <= 'f') {
                *dst = *src++ - 87;
            } else if (*src >= '0' && *src <= '9') {
                *dst = *src++ - '0';
            }
            *dst <<= 4;
            if (*src >= 'A' && *src <= 'F') {
                *dst++ += *src++ - 55;
            } else if (*src >= 'a' && *src <= 'f') {
                *dst++ += *src++ - 87;
            } else if (*src >= '0' && *src <= '9') {
                *dst++ += *src++ - '0';
            }
        } else {// 인코딩이 적용안된 문자는 그대로 복사
            *dst++ = *src++;
        }
    }
    *dst = '\0';
    return decoded;
}

// %의 개수를 카운트 (인코딩된 문자의 개수)
int numOfPercent(const char * str)
{
    int cntOfPercent = 0;
    char *pstr = str;
    while (*pstr++ != '\0') {
        if (*pstr == '%') {
            cntOfPercent++;
        }
    }
    return cntOfPercent;
}


// 인코딩할 문자 카운트 (알파벳, 숫자, . , @를 제외한 특수문자)
int numOfEncodingChar(const char * str)
{
    int cntOfEncodingChar = 0;
    char * src = str;
    while (*src++ != '\0') {
        if ( (*src >= 'A' && *src <= 'Z') || (*src >= 'a' && *src <= 'z') || 
            (*src >= '0' && *src <= '9') || (*src == '@' || *src == '.') ) { 
            ;
        } else {
            cntOfEncodingChar++;
        }
    }
    return cntOfEncodingChar;
}  


'기타' 카테고리의 다른 글

지갑  (0) 2011.05.26
2011년 자바 개발자 컨퍼런스 등록!!  (1) 2011.05.23
Base64 Encoding  (0) 2011.02.18
muju  (33) 2011.02.14
정규표현식(Regular Expression)  (0) 2010.12.10
MD5(Message-Digest algorithm 5)  (0) 2010.12.10