클래스의 모든 멤버 변수와 멤버 함수는 정적(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++은 기본적으로 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언와의 호환성 때문에 남겨 놓은 구조체를 이용하는 것 보다는 클래스를 사용하는 것이 더 바람직하다.



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()함수는 인라인 함수로 자동으로 간주된다.



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를 이용하여 객체화를 시도하면 프로그램을 좀 더 직관적으로 작성할 수 있다.




'프로그래밍언어.Lib > C,C++' 카테고리의 다른 글

C++ 의 구조체(struct)  (0) 2015.06.12
C++ 인라인(inline) 멤버 함수  (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 살레시오
,

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() 함수를 작성하라.


Posted by 살레시오
,

5.3 배열의 예제 및 풀이 #2     [doc]     [smts]

다음과 같은 배열 예제를 작성해 보자.


  1. int형 배열에 0부터 255까지의 정수를 순서대로 저장한다.

  2. 모든 배열의 요소와 각각의 16진수 값을 출력한다.


먼저 크기가 256인 정수형 배열을 선언한다.


int ia[256];


이 경우 선언과 동시에 초기화를 할 수도 있겠지만 초기화할 요소의 숫자가 많으므로 반복문을 이용하여 수행한다.


for (int k=0; k<256; k++) {
ia[k] = k;
}

이것에 의해서 0번 요소는 0, 1번 요소는 1, …, 255번 요소는 255로 초기화된다. 이제 각각의 요소를 출력하기 위해서 다시 for 반복문을 사용한다.


for(int k=0; k<256; k++) {
printf("ia[%d] = %d : %x\n", k, ia[k], ia[k]);
}

printf()함수의 %x 서식문자는 정수형 숫자 데이터를 16진수로 출력하는 것이다.


전체 프로그램은 다음과 같다.


#include  <stdio.h>
int main(void)
{
int ia[256];
for(int k=0; k<256; k++) {
ia[k] = k;
}
for(int k=0; k<256; k++) {
printf("ia[%d] = %d : %x\n", k, ia[k], ia[k]);
}
}

실행 예:

ia[0] = 0 : 0
ia[1] = 1 : 1
ia[2] = 2 : 2

… 중간 생략…

ia[252] = 252 : fc
ia[253] = 253 : fd
ia[254] = 254 : fe
ia[255] = 255 : ff

이 예제와 같이 많은 수의 배열 요소를 초기화할 때에는 반복문이 사용되기도 한다.


Posted by 살레시오
,

5.2 배열의 예제및 풀이 #1     [doc]     [smts]

다음과 같은 예제를 배열을 이용하여 풀어 보자.


  1. 배열에 사용자가 입력한 다섯 개의 float 형 데이터를 저장한 후 그것을 화면에 출력하라.

  2. 입력 받은 숫자들 중 가장 큰 최대값을 화면에 출력하라.


먼저 다섯 걔의 float형 값을 갖는 배열을 선언해야 한다.


float fa[5];

그 다음 사용자로부터 입력 받은 수를 저장하는 반복문을 작성해야 한다.


float fi;
for(int k=0; k<5; k++) {
scanf("%f", &fi);
fa[k]=fi;
}

이 반복문에서 정수형 변수 k는 0,1,2,3,4 값에 대해서 반복을 수행하며 입력된 실수를 배열 fa에 저장하게 된다.


이제 다 입력 받은 데이터를 화면에 출력하는 것도 반복문을 사용하면 된다.


for(int k=0; k<5; k++) {
printf("fa[%d] : %f\n", k, fa[k]);
}

여기서 printf() 함수의 첫 번째 %d에는 인덱스가, %f 자리에는 배열의 k번째 요소가 출력이 된다.


전체 프로그램은 다음과 같다.


#include  <stdio.h>
int main(void)
{
float fa[5];
float fi;
for(int k=0; k<5; k++) {
scanf("%f", &fi);
fa[k]=fi;
}

for(int k=0; k<5; k++) {
printf("fa[%d] : %f\n", k, fa[k]);
}
}

실행 예:

11
-22
1.5
4.7
-123.456
fa[0] : 11.000000
fa[1] : -22.000000
fa[2] : 1.500000
fa[3] : 4.700000
fa[4] : -123.456001

이제 사용자가 입력한 숫자들 중 최대값을 찾는 알고리듬을 다음과 같이 고안해 보자. 최대값을 저장할 변수를 fmax로 선언한다.


float fmax;


그리고 사용자가 처음 입력한 숫자를 fmax의 값으로 대입한 후 그 이후에는 새로 입력된 숫자가 이전에 저장된 fmax 값보다 클 경우 fmax 값을 갱신한다. 다섯 개의 숫자에 대해서 이 작업을 수행하면 마지막에 fmax 변수에는 가장 큰 값이 남아 있게 된다.


for(int k=0; k<5; k++) {
scanf("%f", &fi);
fa[k]=fi;
if (k==0) { // 첫 번째 데이터가 입력된 경우
fmax = fi;
} else {  // 두 번째 데이터 이후
if (fi > fmax)
fmax = fi;
}
}
}

위에서 보면 if ~ else 제어문으로 첫 번째 데이터와 그 이후의 데이터를 구분했으며 k변수가 0이면 첫 데이터라고 판단한다. 반복문이 종료되면 fmax 변수에는 최대값이 저장되어 있으므로 그것을 출력하면 된다.


printf("The maximum value is %f.", fmax);

전체 프로그램은 다음과 같다.


#include  <stdio.h>
int main(void)
{
float fa[5];
float fi;
float fmax;
for(int k=0; k<5; k++) {
scanf("%f", &fi);
fa[k]=fi;
if (k==0) {
fmax = fi;
} else {
if (fi > fmax)
fmax = fi;
}
}
printf("The maximum value is %f.", fmax);
}

실행 예:

11
-22
1.5
4.7
-123.456
The maximum value is 11.000000.

이 프로그램을 조금만 고치면 최소값을 출력하도록 할 수 있다. 직접 수정해서 결과를 확인해 보기 바란다.


Posted by 살레시오
,

4장 연습문제

pb04-01:사용자가 입력한 int형 변수 x와 y에 대해 x를 y로 나눈 몫과 나머지를 화면에 각각 출력하는 프로그램을 작성하라. 단, y가 0이라면 아무 것도 출력하지 않고, 나머지가 0일 경우 몫만 출력해야 한다.


pb04-02:양의 정수를 입력받아서 1이면 "1st", 2라면 “2nd", 3이면 ”3rd" 나머지의 경우는 숫자 뒤에 “th”를 붙여서 화면에 출력하는 프로그램을 작성하라. 만약 0이하의 숫자가 입력되었다면 다시 입력하도록 한다.


pb04-03: 월소득(monthly income)을 long형으로 입력 받아서 그것에 대한 소득세(income tax)를 계산하여 출력하는 프로그램을 작성하라. 소득세율은 다음과 같다.


소득이    500,000원 이하는 0%

2,500,000원 이하는 0.5%

4,000,000원 이하는 1.0%

                     7,000,000원 이하는 2.0%,

                     그 이상은 4.0%

pb04-04: 2에서 9사이의 정수를 입력받아 해당하는 구구단을 출력하는 프로그램을 작성하라. 그 외의 숫자가 입력되었다면 다시 입력받도록 한다.


pb04-05:정수 하나를 입력 받아서 그 약수들을 출력하는 프로그램을 작성하라.


pb04-06:정수 두 개를 입력 받아서 두 수의 최대공약수(greatest common divisor)를 출력하는 프로그램을 작성하라.


pb04-07:다음 반복문이 화면에 표시하는 결과는 무엇인가?

int iA;
for (iA=36; iA>0; iA/=2) {
  printf("%d ", iA);
}

pb04-08:정수 두 개를 입력 받아서 두 수의 최소공배수(least common multiple)를 출력하는 프로그램을 작성하라.


pb04-09: 1000이하의 모든 소수(prime number)를 출력하는 프로그램을 작성하라. (소수란 1과 자신의 수로만 나누어 떨어지는 정수를 말한다.)


pb04-10: 사용자가 입력한 정수값이 소수(prime number)이면 프로그램을 종료하고 아니면 다시 정수값을 입력받는 프로그램을 작성하라.


pb04-11: 양의 정수를 입력받아서 다음과 같이 화면에 출력하는 프로그램을 작성하라.

pb04-12: float형 변수 fa, fb, fc 에 각각 사용자로 부터 정수값을 입력 받은 후 크기 순으로 나열했을 경우의 중간 값을 화면에 출력하는 프로그램을 작성하라. 예를 들어 1.2 10.0 –3.5 를 사용자가 입력했다면 크기순으로 정렬하면 10.0 > 1.2 > -3.5 이다. 따라서 가운데의 1.2를 출력해야 한다.


pb04-13: 1000 이하의 양의 정수 중 3의 배수이거나 5의 배수인 것들을 역순으로 출력하는 프로그램을 작성하라. 즉 다음과 같이 화면에 출력되어야 한다. 만약 3의 배수이고 동시에 5의 배수인 경우 대괄호 안에 숫자를 출력한다.

1000 999 996 995 993 [990] 987 985 984 981 980 978 [975] 972 ....9 6 5 3


pb04-14: 다음 프로그램이 실행된다면 화면에 어떻게 출력되는가?

#include <stdio.h>
int main(int argc, char **argv) {
  for(char ca='a';ca!='g';ca++) {
  printf("%c ",ca);
  }
}

Posted by 살레시오
,

3장 연습 문제     [gdoc]     [smts]

  1. 연산자 ++, --가 변수에 붙는 방향에 따라 동작이 어떻게 달라지는지 기술하라.

  2. 반지름이 1.5인 원의 원주의 길이와 면적을 계산하여 출력하는 프로그램을 작성하라.

  3. 하나의 정수를 입력받아서 짝수이면 "even number!" , 홀수이면 "odd number!"라고 화면에 표시하는 프로그램을 작성하라. (조건 연산자를 이용할 것)

  4. 어떤 int형 정수를 입력받아서 그 수의 절대값을 화면에 출력해 주는 프로그램을 작성하라.

  5. 세 개의 int형 정수를 입력받아서 그 중 가장 큰 수를 화면에 출력해 주는 프로그램을 작성하라.

  6. 분수의 분자(numerator)와 분모(denominator)를 각각 입력받아(long 형) 가분수(improper fraction), 진분수(proper fraction) 여부를 출력하는 프로그램을 작성하라. 만약 가분수일 경우 정수+진분수의 형태로도 출력해야 한다.

  7. 두 개의 복소수를 입력받아서 곱셈 결과를 출력하는 프로그램을 작성하라. 단, 복소수의 실수부와 허수부는 float형으로 받는다.

  8. 2차 방정식 x2+ax+b=0 의 계수 a, b값(int형)을 키보드로 읽어들여서 판별식의 조건에 따라 두 실근일 경우 “real roots”, 중근일 경우 “an equal root”, 허근일 경우 “complex roots” 라고 화면에 표시하는 프로그램을 작성하라. 단, 중근일 경우에는  중근을 출력해야 한다.


--- 이하는 생략 가능 ---------------

  1. 변수 ucB의 b2가 0이라면 화면에 “LED off”, 1이라면 “LED on”이라고 출력하는 프로그램을 작성하라.

  2. 변수 ucC의 초기값을 0x0F이다. 이 변수값 전체가 주기적으로 반전되는 프로그램을 작성하라. (단 시간을 지연시키는 함수는 _delay_ms(unsigned shot usN )이라고 가정하고 usN에는 밀리세컨드 숫자를 입력한다고 하자.)

  3. 변수 ucA의 상위 니블을 반전시키는 코드를 작성하라.

  4. unsigned char형 변수값을 이진수로 표기해주는 프로그램을 작성하라.


Posted by 살레시오
,

 C++에서 (C언어에서는 지원되지 않음) 함수가 호출될 때 입력 인자에 값이 넘어오지 않는다면 미리 정해진 값을 함수 내부에서 가지도록 할 수 있다. 이렇게 기본값을 가지는 함수의 인자를 기본값 인자(default parameter)라고 하며 함수의 선언부에서 예를 들면 다음과 같이 명시해 주어야 한다.


void func(int ia=0); // 함수의 선언에 ia의 기본값을 10으로 지정
….
int func(int ia) { //함수 정의. ia는 기본값 10을 가진다.
   return ia+10;
}


변수 ia는 호출될 때 값이 넘어오지 않으면 자동으로 0값을 가지도록 선언되었다. 즉, 이 함수를 호출할 때 입력인수를 주어도 되고 안 해도 된다.

func(); // 변수 ia는 0값을 자동으로 갖는다.
func(10); // 변수 ia에 10값을 넘겨준다.

 만약 디폴트 입력 인수기능이 없이 함수 중복으로만 이를 구현한다면 다음 그림의 좌측과 같이 두 개의 함수를 별도로 작성해야 할 것이다.


void func() {

   int ia = 0;

   // 함수 본체

   ....

}

void func(int ia) {

   // 함수 본체

   ....

}

void func(int ia = 0);

함수 중복으로 구현한 경우

디폴트 입력 인수 함수로 간략화


이것을 살펴보면 기본 인자 기능이 프로그램을 상당히 간결히 해주는 유용한 기능임을 알 수 있다.


#include "stdio.h"

void print(char *name = "John");// 기본값을 지정

int main(void)
{
print();
print("Jang-Hyun Park");
}

void print(char *name)
{
printf("Hi. My name is %s\n", name);
}


Hi. My name is John
Hi. My name is Jang-Hyun Park

 다른 예를 들어보면 다음과 같다.

void send(int ia, string str=“Hello”);

이 함수는 다음과 같이 두 가지로 호출이 가능하다.


send(10);
send(10, “Hi”);

 

기본값 인자가 설정된 변수만 생략 가능하다는 점에 유의해야 한다. 따라서 다음과 같은 호출은 오류를 발생시킬 것이다.

send(); //오류 발생
send(“Hi”); //오류 발생

 만약 다음과 같이 디폴트 입력 인수를 두 개 가진 함수라면

void sum(double da, double db=10.0, double dc=20,0);

다음과 같이 세 가지 방법으로 호출할 수 있다.

sum(1.0); // da는 1.0, db는 10.0, dc는 20.0 값을 갖는다.
sum(1.0, 2.0); // da는 1.0, db는 2.0, dc는 20.0 값을 갖는다.
sum(1.0, 2.0, 3.0); // da는 1.0, db는 2.0, dc는 3.0 값을 갖는다.

 디폴트 입력 인수를 가진 함수를 선언할 때 주의할 점은 이것들이 모두 끝 쪽에 몰려있어야 하며 디폴트 입력 인수를 가지는 변수 다음에 일반 변수는 못 온다는 것이다. 다음 예는 모두 잘못된 것이다.

 void sum(int ia, int ib=5, int ic, int id=10);// 에러 발생
 void sum(int ia=10, int ib, int ic);// 에러 발생

그리고 다음과 같은 함수 중복도 오류를 발생한다.


void print(string stra);
void print(string stra = “Hello”); // 허용되지 않는 함수 중복

 

그 이유는 두 함수가 입력 인수의 개수와 형이 같기 때문이다. 그리고 다음과 같은 함수 중복도 오류를 발생한다.

void func(int ia, string strA=“Hi”);
void func(int ia); // 허용되지 않는 함수 중복

두 함수는 분명히 입력 인수의 개수가 다르지만 만약 func(10) 이라고 호출했을 때 두 개 중 어느 것을 호출해도 문제가 없기 때문에 컴파일러는 오류를 발생시킨다.



Posted by 살레시오
,