이전 포스트에서 C++의 double형 연산과 long long int 형 연산 속도를 측정한 적이 있는데 똑같은 일을 JAVA에서 수행하고 시간을 측정해 보았다. (JAVA는 long형이 64비트 정수형이고 c++의 long long int 형에 대응한다.)


package javaapplication5;
public class JavaApplication5 {
   public static void main(String[] args) {
       long iter = 100000000; //1억번
       
       System.out.println("Start");
       long ls, le;
       double da=12.3, db=45.6;
       ls = System.nanoTime();
       for(long k=0;k<iter;k++) da *= db;
       le = System.nanoTime();
       double tm1 = (le-ls)/1e9;
       System.out.println("elapsed time 1 = "+tm1);
       
       long la=2, lb=2;
       ls = System.nanoTime();
       for(long k=0;k<iter;k++) la *= lb;
       le = System.nanoTime();
       double tm2 = (le-ls)/1e9;
       System.out.println("elapsed time 2 = "+tm2);
       
       System.out.println(tm1/tm2 + " times faster.");
   }   
}


수행 결과는 의외였다.



JAVA로 실행한 결과가 훨씬 더 수행시간이 짧다. 당연히 JAVA가 수행시간이 더 걸릴 줄 알았는데 아니었다. 아래가 g++ 로 컴파일하여 수행시간 결과다. 똑 같은 일은 c++ 은 14.591초, 자바는 0.357초 걸렸다.



윈도에서는 g++ 성능이 낮고 최적화를 전혀 하지 않았음을 감안하더라도 성능 차이가 이렇게 날 줄 몰랐다. 자바도 중간어를 JIT 컴파일해서 실행하므로 c++과의 실행 속도 차이가 그다지 크지 않다고 알고는 있었는데 직접 해보니 사실이었다. 한 가지 자바에서는 정수형과 실수형의 연산 속도 차이가 c++에서만큼 크지 않다는 것도 알 수 있었다.


 그렇다면 c++을 고집할 필요가 없는 것 아닌가 싶다. JAVA를 이용하는 것이 훨씬 더 편하고 쉽다. 더군다나 CUDA4J 같은 GPU를 사용할 수 있는 라이브러리도 있으니 성능 향상이 필요할 때는 이것을 사용하면 되지 않을까.


 실수 연산과 정수 연산의 시간 차이를 알아보기 위해서 자바로 실험을 조금 더 해 보았다.


package javaapplication5;
import static java.lang.Math.exp;
public class JavaApplication5 {
   public static void main(String[] args) {
       long iter = 100000000;
       
       System.out.println("Start");
       long ls, le;
       double da=12.3, db=45.6, dc=0, dd=0;
       ls = System.nanoTime();
       for(long k=0;k<iter;k++) {
           dd = da*db;
           dc = exp(dd);
           da += 1e-8;
       }
       le = System.nanoTime();
       //System.out.println(da + ", " + dc);
       double tm1 = (le-ls)/1e9;
       System.out.println("elapsed time 1 = "+tm1);
       
       long la=2, lb=2, lc = 0, ld=0;
       long[] larr = new long[2000];
       
       ls = System.nanoTime();
       for(long k=0;k<iter;k++) {
           long ll = k%2000;
           ld = la*lb;
           lc = larr[(int)ll];
           la++;
       }
       le = System.nanoTime();
       double tm2 = (le-ls)/1e9;
       System.out.println("elapsed time 2 = "+tm2);
       
       System.out.println(tm1/tm2 + " times faster.");
   }
}


이 연산에서는 30배 정도 속도에서 차이가 난다.


Posted by 살레시오


 윈도에서 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설치가 완료된 것이다.



Posted by 살레시오

 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);




Posted by 살레시오

 C/C++의 double형은 수치 해석 분야의 기본적인 자료형이다. float형은 정밀도가 떨어지므로 주로 이 자료형이 사용되며 GPU도 이 자료형의 계산을 고속으로 수행하도록 설계된 것으로 알려져 있다.


 그런데 long long int 형은 8바이트 정수형 자료형인데 단순 곱셈의 경우 수행 속도에 시간 차가 많이 난다. 다음과 같은 간단한 c++ 프로그램을 내 노트북에서 실행시켜서 확인해 보았다.


#include  <stdio.h>
#include <time.h>
#define ITER 100000000 //1억번
int main() {
clock_t clkStart, clkEnd;
double dt1, dt2;
clkStart = clock();
double da = 10.1, db=11.2;
for (long k=0; k<ITER; k++) {da*=db;}
clkEnd = clock();
printf("%.3f sec\n", dt1=((double)clkEnd-clkStart)/CLOCKS_PER_SEC);

clkStart = clock();
long long lla = 101, llb=112;
for (long k=0; k<ITER; k++) {lla*=llb;}
clkEnd = clock();
printf("%.3f sec\n", dt2=((double)clkEnd-clkStart)/CLOCKS_PER_SEC);
printf("%.2f percent", dt2/dt1*100);
}


이 프로그램은 단순히 double형 두 개를 곱셈 후 대입하는 동작 1억 번과 long long 형 덧셈 후 대입하는 동작 1억 번의 수행 시간을 구하는 것이다.  결과는 다음과 같이 후자가 전자 대비 3%의 시간밖에 걸리지 않았다.



 문제는 GPU 기반의 라이브러리인 CUDA에서 정수형 연산도 실수형 만큼 효율적인가 하는 것이다. 하지만 그러지 않더라도 나름 의미가 있지 않을까.





Posted by 살레시오

C/C++ 의 if 문 예제 1

C,C++ 2015.06.25 17:11

4.1.1 조건문을 사용한 예제 1     [doc]    [smts]

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


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


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


(a) f1과 f2 중 큰 것을 fMax에 저장한다.

(b) f3이 fMax보다 크다면 fMax 값을 f3 값으로 갱신한다.

(c) fMax를 화면에 출력한다.


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


ex04-06.c
#include  <stdio.h>
int main() {
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.

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


Posted by 살레시오

 클래스의 모든 멤버 변수와 멤버 함수는 정적(static) 멤버로 지정될 수 있다. 정적 멤버 변수는 인스턴스가 생성될 때마다 독립적으로 생기는 멤버 변수와 달리 해당 클래스에 하나만 생성되고 모든 인스턴스에서 공동으로 접근할 수 있는 변수이다. 마찬가지로 정적 멤버 함수도 클래스당 하나만 생기며 모든 인스턴스에서 공동으로 호출할 수 있다.


 멤버를 정적 멤버로 선언하려면 선언문 앞에 static 이라는 지정자를 붙이면 된다. 모든 멤버들이 static으로 선언될 수 있으며 정적 멤버들도 접근 지정자 (public, protected, private)을 붙일 수 있다.

1 정적 멤버 변수

 이전 포스트의 LED 클래스의 예를 가지고 정적 멤버 변수를 추가시켜 보면 다음과 같다.

class Led {
   public:
       Led();
       void turnOn();
       void turnOff();
       static int iCount; // 정적 멤버 변수
   private:
       byte _pin;
};

이 예제에서 iCount는 정적 멤버 변수로 선언되었다. 정적 멤버 변수를 초기화하기 위해서는 클래스 내부에서는 불가능하다. 다음과 같이 초기화 하려고 하면 에러를 발생한다.


class Led {
   public:
       Led();
       void turnOn();
       void turnOff();
       static int iCount = 0; // 오류 발생
   private:
       byte _pin;
};

 

따라서 클래스 외부에서 전역 변수처럼 초기화시켜야 한다.

int Led::iCount = 0;

정적 변수를 접근하는 방법은 두 가지가 있는데 먼저 클래스 이름으로 접근하는 것이다. 이때 범위 지정 연산자인 ::을 이용한다.


Led::iCount ++; // iCount값을 하나 증가시킨다.

 

또는 인스턴스를 이용해서도 접근할 수 있다.

Led led1(12), led2(11);
led1.iCount = 10;
led2.iCount = 30;

비록 인스턴스 멤버 변수를 접근하는 문법과 똑같지만 서로 다른 인스턴스를 통해서 정적 변수를 참조했다고 할지라도 결국 같은 하나의 정적 변수 iCount를 접근하는 것이다.

 정적 변수의 첫 번째 활용 목적은 인스턴스들 사이에서 공유할 변수를 만들고자 하는 것이다. 예를 들어서 인스턴스가 몇 개나 생성되었는지를 기록하고자 할 때 앞의 예에서 iCount를 사용하면 될 것이다. 이 경우 생성자 내에서 iCount 값을 증가시키면 새로운 인스턴스가 생성될 때마다 이 변수값이 증가되므로 이것으로 개수를 알 수 있다.

int Led::iCount = 0; // 전역에서 정적 멤버 변수 초기화
Led::Led(int pin) { //생성자
   _pin = pin;
   pinMode(_pin, OUTPUT);
   iCount++; // 인스턴스 생성 시 하나 증가
}
Led::~Led(int pin) { //소멸자
   iCount--; // 인스턴스 소멸 시 하나 감소
}

또한 전역 변수를 쓰는 대신 관련된 클래스 내부에 정적 멤버 변수를 집어넣어서 C언어의 전역 변수처럼 사용할 수도 있다.

2 정적 멤버 함수

 멤버 함수 앞에 static 이라는 키워드를 붙이면 정적 멤버 함수가 된다. 정적 변수와 마찬가지로 정적 멤버 함수는 인스턴스에 속하는 멤버 함수가 아니라 클래스에 속하는 하나의 함수이다. 정적 함수 내부에서는 오직 정적 변수만을 사용할 수 있으며 함수도 정적 함수만을 호출할 수 있다. 반대로 일반 멤버 함수에서는 정적 멤버를 접근하는데 전혀 제약이 없다. 다음 예를 보자.

class Util {
   public:
       int iA;
       static double dA;

       void getA() {
           iA += (int)dA; // 정적과 비정적 변수를 모두 사용가능
           return iA;
       }

       static void getB() { // 정적 함수
           return dA; //정적 변수만 사용 가능
       }
};


비정적 함수 getA() 내부에서는 변수 iA와 정적 변수 dA를 사용하는데 아무런 제약이 없으나 정적함수 getB() 에서는 정적 변수 dA만 사용할 수 있다. 마찬가지로 정적 함수 내에서는 정적인 함수만 호출할 수 있으며 일반적인 멤버 함수는 호출할 수 없다.



Posted by 살레시오

C++ 의 구조체(struct)

C,C++ 2015.06.12 08:04

 C++은 기본적으로 C와 호환성을 갖게끔 설계되었으며 이것은 C로 작성된 프로그램은 큰 수정 없이 C++컴파일러가 컴파일을 할 수 있다는 의미이다. C에서 struct(구조체)가 있으므로 C++도 이것이 있는데 표준 C구조체의 기능을 확장하여 C++의 클래스와 동일한 기능을 갖는다는 점에 유의해야 한다. 따라서 구조체도 멤버 변수뿐만 아니라 멤버 함수도 가질 수 있으며 접근 지정자도 사용 가능하다. 예를 들어서

struct Name {
   private:
       int iA;
       void func1();
   public:
       double dA;
       void func2();
   protected:
       short sA;
};

C++의 구조체의 인스턴스 생성은 클래스와 동일한데 C언어의 경우에는 struct 키워드를 붙여야 하지만 C++에서는 그렇지 않다.


Name ins1;

 

구조체와 클래스의 유일한 차이점은 구조체의 기본 지정자가 public 이라는 점이다. 즉, 접근 지정자가 명시적으로 지정되지 않으면 구조체는 public으로 지정된다.

struct Name {
   int iA;
   double dA;
};

이 예에서 멤버 변수 iA와 dA는 모두 public이므로 외부에서 자유롭게 접근 가능하다. 이렇게 정해진 이유는 역시 C언어와의 호환성 때문인데 C언어의 구조체 멤버는 기본적으로 외부에서 모두 접근이 가능하기 때문이다. 따라서 위의 구조체는 다음의 클래스와 기능적으로 동일하다.


class Name {
   public:
       int iA;
       double dA;
};

 구조체를 사용하느냐 클래스를 사용하느냐는 전적으로 사용자의 몫이겠지만 C++ 프로그램을 작성한다면 궂이 C언와의 호환성 때문에 남겨 놓은 구조체를 이용하는 것 보다는 클래스를 사용하는 것이 더 바람직하다.



'C,C++' 카테고리의 다른 글

C/C++ 의 if 문 예제 1  (0) 2015.06.25
C++ 클래스의 정적(static) 멤버  (0) 2015.06.12
C++ 의 구조체(struct)  (0) 2015.06.12
C++ 인라인(inline) 멤버 함수  (0) 2015.06.12
C++로 작성한 Button 클래스 (아두이노) 예제  (0) 2015.06.12
C/C++ 함수 예제  (0) 2015.06.09
Posted by 살레시오

 C++ 에서 함수를 호출하는데 있어서는 어느 정도 댓가가 따른다. 함수를 호출하기 직전에 기존 정보를 저장하고 인자를 넘겨주고 실행 순서를 바꾼 후 함수의 수행이 끝나면 사용한 메모리를 정리하고 반환값을 받는다. 즉 함수 호출 전후에 필수적으로 수행해야하고 메모리와 시간을 요하는 작업들이 있는 것이다. PC에서 수행되는 프로그램을 작성할 때에는 이러한 오버헤드는 무시할 수 있을 것이다. 하지만 아두이노와 같은 메모리나 성능이 매우 제약된 프로세서를 프로그래밍할 경우에는 무시 못할 성능 저하 요인이 될 수도 있다.


 C++의 인라인(inline)함수는 함수의 길이가 매우 짧을 경우에 효율을 높이기 위해서 도입된 방법으로서 함수의 선언부 앞에 inline 이라는 키워드로 구현된다. 이전의  코드로 예를 들면 다음과 같다.

inline boolean Button::isPushed() {
   return (digitalRead(_pin) == LOW)? true:false;
}


컴파일러는 인라인 함수를 호출하는 곳에 인라인 함수의 코드를 그대로 삽입하여 함수의 호출이 일어나지 않도록 한다. 이렇게 되면 함수를 호출할 때 드는 비용이 없어지기 때문에 속도가 더 올라간다. 반대 급부로 프로그램의 길이는 더 길어지게 된다.

 다른 객체지향 언어(JAVA, C# 등등)도 마찬가지지만 C++도 비교적 작은 크기의 함수를 많이 사용한다. 대표적인 것이 멤버 변수를 접근하는 getter/setter 함수인데 이러한 사용 빈도가 높고 크기가 작은 함수들을 inline으로 정의해 놓으면 더 높은 실행 효율을 얻을 수 있다.


 함수를 inline으로 설정했다고 모두 코드를 치환하는 것은 아니고 컴파일러에 따라서 동작 방식이 다르다. 자기 자신을 호출하는 재귀함수나 반복문, switch문 등이 포함된 함수는 inline으로 지정했다고 하더라도 컴파일러에 의해서 인라인 선언이 무시될 수도 있다. 또한 생성자를 포함하여 모든 멤버 함수가 인라인으로 선언될 수 있다. 이전 포스트의 Button클래스의 멤버 함수를 인라인 함수로 지정하면 다음과 같다.

class Button {
   public:
     Button(byte, boolean); // 생성자
     boolean isPushed(); // 버튼이 눌렸다면 true를 반환하는 멤버 함수
   private:
     byte _pin; // 연결된 핀
     boolean _internalPullup; //내부에 풀업이 되었는가
};
// 생성자의 구현
inline Button::Button(byte pin, boolean internalPullUp = true) {
   _pin = pin;
   _internalPullup = internalPullUp;
   if (_internalPullup)
       pinMode(_pin, INPUT_PULLUP);
   else
   pinMode(_pin, INPUT);
}
// 멤버 함수의 구현
inline boolean Button::isPushed() {
   return (digitalRead(_pin) == LOW)? true:false;
}

 멤버 함수의 크기가 작을 경우 클래스의 선언부에 바로 함수를 구현해도 무방하다. 즉, 위 예의 isPushed() 함수를 다음과 같이 클래스의 선언부에 바로 구현해도 된다.

class Button {
   public:
     Button(byte, boolean); // 생성자
     boolean isPushed();{
       return (digitalRead(_pin) == LOW)? true:false;
     }
     boolean isPushed(); // 버튼이 눌렸다면 true를 반환하는 멤버 함수
   private:
     byte _pin; // 연결된 핀
     boolean _internalPullup; //내부에 풀업이 되었는가
};
// 생성자의 구현
inline Button::Button(byte pin, boolean internalPullUp = true) {
   _pin = pin;
   _internalPullup = internalPullUp;
   if (_internalPullup)
       pinMode(_pin, INPUT_PULLUP);
   else
       pinMode(_pin, INPUT);
}

 단 한 가지 주의할 점은 컴파일러는 클래스 선언부에 바로 구현된 멤버 함수들에 대해서는 inline선언이 없어도 인라인 함수로 자동으로 처리한다. 따라서 이 예에서 isPushed()함수는 인라인 함수로 자동으로 간주된다.



'C,C++' 카테고리의 다른 글

C++ 클래스의 정적(static) 멤버  (0) 2015.06.12
C++ 의 구조체(struct)  (0) 2015.06.12
C++ 인라인(inline) 멤버 함수  (0) 2015.06.12
C++로 작성한 Button 클래스 (아두이노) 예제  (0) 2015.06.12
C/C++ 함수 예제  (0) 2015.06.09
C/C++ 배열의 예제 및 풀이 #2  (0) 2015.06.08
Posted by 살레시오

 여기에서는 입력 장치로 많이 사용되는 푸시 버튼을 객체화 시키는 예제를 작성해 보도록 하겠다. 푸시버튼도 디지털 핀에 연결할 수 있으며 외부에서 풀업(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를 이용하여 객체화를 시도하면 프로그램을 좀 더 직관적으로 작성할 수 있다.




'C,C++' 카테고리의 다른 글

C++ 의 구조체(struct)  (0) 2015.06.12
C++ 인라인(inline) 멤버 함수  (0) 2015.06.12
C++로 작성한 Button 클래스 (아두이노) 예제  (0) 2015.06.12
C/C++ 함수 예제  (0) 2015.06.09
C/C++ 배열의 예제 및 풀이 #2  (0) 2015.06.08
C/C++ 배열 예제 및 풀이 #1  (0) 2015.06.08
Posted by 살레시오

C/C++ 함수 예제

C,C++ 2015.06.09 21:31

7장 연습문제

pb07-01 자신의 영문 이름과 나이를 출력하는 함수 showMe() 함수를 작성하라. 그리고 이 함수를 100번 연속으로 호출하는 코드를 작성하라.



pb07-02 정수를 받아서 그 정수가 짝수이면 “even number”, 홀수이면 “odd number” 라고 화면에 출력하는 함수를 작성하라. 이 함수의 선언은 다음과 같다.

void isEven(int ia);


pb07-03 구의 반지름을 입력받아서 구체의 부피를 반환하는 함수를 작성하라. 함수의 선언을 다음과 같다.(V = 4πr3/3)

double calcVolumn(double dr);


pb07-04 unsigned char형 정수를 받아서 1부터 그 수까지의 합을 반환하는 함수를 작성하라. 함수의 선언은 다음과 같다.

long sumup(unsigned char uc);


pb07-05 세 개의 int형 정수를 받아서 그중 가장 큰 수를 반환하는 함수를 작성하라. 함수의 선언은 다음과 같다.

int getMax(int ia, int ib, int ic);


pb07-06 (a) char형 문자를 하나 받아서 그 문자가 소문자이면 1, 그 외의 문자이면 0을 반환하는 함수를 작성하라. 함수의 선언은 다음과 같다.

int isLower(char ca);


(b) 작성된 함수를 이용하여 주어진 문자열이 모두 소문자일 경우 “bingo” 라고 화면에 표시하는 프로그램을 작성하라.


pb07-07 (a) unsigned long형 인자를 두 개 받아서 그 두 수의 최대 공약수를 반환하는 함수를 작성하라. 반환값은 long형이다. 함수의 선언부는 다음과 같다.


long getGCD(unsigned long la, unsigned long lb);

(b) 최소 공배수를 구하는 함수 getLCM() 함수를 작성하라.


'C,C++' 카테고리의 다른 글

C++ 인라인(inline) 멤버 함수  (0) 2015.06.12
C++로 작성한 Button 클래스 (아두이노) 예제  (0) 2015.06.12
C/C++ 함수 예제  (0) 2015.06.09
C/C++ 배열의 예제 및 풀이 #2  (0) 2015.06.08
C/C++ 배열 예제 및 풀이 #1  (0) 2015.06.08
C/C++ 제어문 연습 문제  (0) 2015.05.26
Posted by 살레시오