레이블이 C언어인 게시물을 표시합니다. 모든 게시물 표시
레이블이 C언어인 게시물을 표시합니다. 모든 게시물 표시

2015년 6월 30일 화요일

Windows 7에서 MinGW 설치하고 설정하기


 윈도에서 gcc/g++ 을 사용할 수 있도록 하는 툴이 minGW 이다. IDE(eclipse, netbeans, codelite 등등 어느 것이나)를 설치한 후 MinGW를 깔고 적절히 설정해야 프로그램을 개발할 수 있다. (MinGW나 cygwin 이나 설치 과정과 설정이 상당히 번거롭다는 점은 감안하자. 제대로만 하면 엄청난 툴을 무료로 사용할 수 있다.)

설치 과정

먼저  http://www.mingw.org 로 접속하여 인스톨 프로그램을 다운로드 받는다.


오른쪽 [Download Installer]를 클릭하면 인스톨러를 다운로드 받을 수 있다.


실행하면 아래와 같은 화면이 나타난다.


설치 디렉토리를 설정하고 설치를 진행한다. (보통은 폴더를 바꾸지 않는다.)

설치가 완료 되면 아래와 같은 MinGW Installation Manager가 실행된다.


이때 Basic Setup Tree에서 mingw-developer-toolkit, mingw32-base, mingw32-gcc-g++, msys-base를 선택한다. 각 항목에서 클릭한 후 ‘Mark’메뉴를 선택한다.


메뉴 “Installation > Apply Changes”를 통해 시스템에 적용한다.




[Apply] 를 눌러 설치를 진행한다. (이 단계에서 시간이 좀 걸린다.)



기본 설치가 완료되면 [Close]를 눌러 Applying scheduled changes 창을 닫는다. MinGW 인스톨러도 종료한다.

환경 설정

 설치만 했다고 끝나는 것은 아니고 Windows의 환경변수에 MinGW에 대한 경로를 설정해야 한다.

먼저 시작버튼>내 컴퓨터(마우스 오른쪽 버튼)>속성 메뉴를 선택한다.

좌상단 맨 밑의 “고급 시스템 설정”을  선택한다.

“고급 탭” 선택 후 하단의 [환경변수(N)] 버튼을 클릭한다.

아래 “시스템 변수(S)” 항목 중 “Path” 항목을 찾아 선택하고 [편집…] 버튼을 선택한다.



“변수 값(V)” 항목에서 이전에 있던 값은 그대로 두고 가장 오른쪽에 커서를 위치한 뒤
“;C:\MinGW\bin;C:\MinGW\msys\1.0\bin” 를 추가한다. 앞의 경로는 gcc/g++/gdb/make 를 실행가능하게 해주고 뒤에 것은 리눅스 명령을 윈도환경에서 사용 가능하게 해주는 것이다. 맨 앞의 세미콜론(;)을 빠뜨리지 말자.

[확인]버튼을 누른다.

테스트



“시작버튼/실행창&검색창”을 통해 “cmd"를 실행하여 도스창을 연다. 그리고 ls 명령을 입력하여 실행되어야 정상이다.


이제 gcc와 g++의 버전을 확인해 보자.


이렇게 나왔다면 MinGW설치가 완료된 것이다.


2015년 6월 29일 월요일

C++ 의 객체 배열의 동적 생성과 반환

 C++ 에서 동적으로 메모리를 생성하고 반환하는 명령은 new와 delete인데 이것을이용하면 객체의 배열도 동적으로 생성하고 반환할 수 있다. new를 이용하여 Rect 라는 클래스 객체의 배열을 동적으로 생성하는 구문은 다음과 같다.

Rect *pRect = new Rect[3];

이렇게 하면 연속된 세 개의 Rect 객체가 생성되는데 이 때 각 객체에 대해 기본 생성자 Rect() 가 호출된다. 이렇게 생성된 객체 배열은 보통의 배열처럼 사용된다.

pRect[0].setWidth(11);
(pRect+1)->setWidth(21); //포인터의 멤버 함수 호출 시 -> 사용
pRect[2].setWidth(33);

이렇게 할당 받은 배열의 메모리를 반환하는 형식은 다음과 같다.

delete [] pRect;

delete 명령과 pRect 포인터 이름 사이의 [] 를 빠뜨리면 안 된다. 이렇게 하면 세 개의 Rect 객체가 소멸되는데 이 때 각 객체의 소멸자가 호출된다.

 한 가지 주의할 점은 new를 이용하여 동적으로 객체 배열을 생성할 때, 매개 변수가 있는 생성자를 호출할 수 없다는 점이다. 만약 어떤 객체를 배열로 생성하여 사용할 경우 이 점을 염두에 두고 생성자와 멤버 함수를 설계해야 한다.

class Rect {
public :
   ….
   Rect();
   Rect(double width, double height); //(2)
   ….
};

위의 예에서 두 번째 생성자 (2)는 배열을 생성하면서 동시에 호출할 수 없다. 따라서 다음과 같이 분리해 놓고

class Rect {
public :
   ….
   Rect();
   void set(double width, double height);
   ….
};

객체 배열 생성 후 반복문으로 순차적으로 set()함수를 호출하는 방법을 사용해야 한다.

Rect *pRect = new Rect[100];
for (int k=0; k<100; k++)
   pRect[k].set(11,22);


2015년 6월 25일 목요일

C/C++ 의 if 문 예제 1

 여기에서는 if 문을 사용한 예제를 풀어보도록 하겠다.

1. 세 개의 float 형 숫자를 사용자에게 입력 받아서 가장 큰 수를 출력하는 프로그램을 작성하라.

 세 float형 변수를  f1, f2, f3 라고 하고 결과값(중간 수)를 저장하는 변수를 fMax 라고 하 하자. 간단한 알고리듬을 다음과 같이 생각해 볼 수 있다.

(a) f1과 f2 중 큰 것을 fMax에 저장한다.
(b) f3이 fMax보다 크다면 fMax 값을 f3 값으로 갱신한다.
(c) fMax를 화면에 출력한다.

이것을 그대로 프로그램으로 구현하면 다음과 같다.

#include  <stdio.h>
int main(void)
{
float f1, f2, f3;
printf("Input three numbers : ");
scanf("%f,%f,%f",&f1, &f2, &f3);
float fMax = (f1>f2)? f1:f2; //(a)를 구현
if (f3 > fMax) //(b)를 구현
fMax = f3;
printf("The maximum value is %f.", fMax);//(c)를 구현
}

실행 예는 다음과 같다.

Input three numbers : 11,22.5,-10
The maximum value is 22.500000.

 이 프로그램을 조금만 바꾸면 최소값을 구하는 프로그램으로 변경할 수 있다.

2. 세 개의 float 형 숫자를 사용자에게 입력 받아서 가운데 수를 출력하는 프로그램을 작성하라.

이 문제는 앞의 문제보다는 한 번 더 생각해야 한다. 여기서도 세 float형 변수를  f1, f2, f3 라고 하고 결과값(중간 수)를 저장하는 변수를 fMid 라고 하고 임시값을 저장하는 변수명을 fTmp라고 하자. (Tmp는 temporary 를 줄인 단어임) 알고리듬은 다음과 같이 생각해 볼 수 있다.

(a) f1과 f2 중 작은 수를 fMid 에 저장하고 큰 수를 fTmp에 저장한다.
(b) f3가 fMid보다 크다면 현재 fMid 값이 최소값이라는 의미다. 따라서 f3와 fTmp중 작은 것이 중간값이므로 그것을 fMid에 저장한다.
(c) f3가 fMid 보다 작다면 (a)에서 구한 fMid 값이 중간값이므로 그것을 출력한다.
(d) fMid를 출력한다.


 이제 이 알고리듬을 프로그램으로 작성해 보면 다음과 같다.

#include  <stdio.h>
int main() {
float f1, f2, f3;
printf("Input three numbers : ");
scanf("%f,%f,%f", &f1, &f2, &f3);
float fMid, fTmp;
if (f1>f2) { // 알고리듬 (a)를 구현한 것임
fMid = f2;
fTmp = f1;
} else {
fMid = f1;
fTmp = f2;
}
if (f3 > fMid) // (b)를 구현한 것임
fMid = (f3>fTmp)? fTmp:f3;
printf("The middle value is %f.", fMid);
}

위에서 보면 알고리듬 (c)가 성립한다면 두 번째 if 문이 실행되지 않고 바로 printf()문이 실행이 되므로 올바르게 작동하는 것을 이해할 수 있을 것이다.

실행 예는 다음과 같다.

Input three numbers : -11,22.5,100.345
The middle value is 22.500000.


2015년 6월 12일 금요일

C++로 작성한 Button 클래스 (아두이노) 예제

 여기에서는 입력 장치로 많이 사용되는 푸시 버튼을 객체화 시키는 예제를 작성해 보도록 하겠다. 푸시버튼도 디지털 핀에 연결할 수 있으며 외부에서 풀업(pull-up)을 시켜주느냐 아니면 내부 풀업을 연결하느냐를 지정할 수 있도록 하겠다. Led 클래스와 마찬가지로 연결된 핀 번호는 private 변수에 저장한다. 그리고 내부에 풀업이 되었는지의 여부를 저장하는 변수도 private변수에 저장한다.

 클래스의 선언을 다음과 같다.
class Button {
public:
   Button(byte, boolean); // 생성자
   boolean isPushed(); // 버튼이 눌렸다면 true를 반환하는 멤버 함수
private:
   byte _pin; // 연결된 핀
   boolean _internalPullup; //내부에 풀업이 되었는가
};
생성자를 보면 입력 인수의 타입만 지정해 주었음을 알 수 있다. 생성자와 멤버 함수의 구현부는 다음과 같다.
// 생성자의 구현
Button::Button(byte pin, boolean internalPullUp = true) {
   _pin = pin;
   _internalPullup = internalPullUp;
   if (_internalPullup)
       pinMode(_pin, INPUT_PULLUP);
   else
       pinMode(_pin, INPUT);
}
// 멤버 함수의 구현
boolean Button::isPushed() {
   return (digitalRead(_pin) == LOW)? true:false;
}
생성자의 구현을 보면 다음과 같이 기본값 인자가 사용되었다.

Button::Button(byte pin, boolean internalPullUp = true) {...}
이렇게 구현해 놓으면 생성자는 인자를 하나를 받을 수도 있고 두 개를 받을 수도 있는데 하나만 있다면 두 번째는 자동으로 true로 지정된다. 즉, 다음과 같이 두 가지로 생성하는 것이 가능하다.
Button btn1(12); // 내부 풀업 저항을 연결하는 경우
Button btn2(11, false); // 외부에서 풀업 된 경우
두 번째 인자의 값에 따라서 pinMode()함수를 적절하게 호출하였음을 알 수 있다.

 풀업 저항이 연결되었을 경우 푸시버튼을 누른 상태에서 digitalRead()함수의 반환값은 LOW가 된다. 따라서 이에 맞게 멤버 함수 isPushed() 가 작성되었음을 알 수 있다.
 만약 클래스 선언이 Button.h에, 구현부가 Button.cpp 에 저장되어 라이브러리를 구성했다면, 이것을 이용하여 버튼이 눌리면 내장 LED가 켜지고 그렇지 않으면 꺼지는 프로그램을 다음과 같이 작성할 수 있다.
#include <Button.h> // 라이브러리 인클루드
Button btn1(12); //12번 핀에 내부 풀업 연결
void setup() {
   pinMode(13, OUTPUT);
}
void loop() {
   if (btn1.isPushed()) // 만약 버튼이 눌렸다면
       digitalWrite(13, HIGH);
   else // 그렇지 않다면 (눌리지 않았다면)
       digitalWrite(13, LOW);
}
 
이와 같이 class를 이용하여 객체화를 시도하면 프로그램을 좀 더 직관적으로 작성할 수 있다.