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

3.12 연산자 우선 순위와 결합 방향    [doc]    [smts]

3.12.1 연산자 우선 순위

한 수식에 여러 개의 연산자를 사용하는 경우에 연산자들의 우선순위를 고려하지 않을 수 없다. 연산자 우선순위를 정리하면 다음과 같다.


  1. 괄호, 배열, 구조체, 공용체멤버를 나타내는 지시자 (), [], ->, . 은 우선순위가 가장 높다.

  2. 한 개의 피연산자를 갖는 단항연산자(!, ++, -- 등)이 그 다음으로 우선순위가 높다.

  3. 그 다음은 산술 연산자 (+, - *, /, %)이다.

  4. 쉬프트연산자와 비교연산자는 비트연산자보다 연산순위가 높다.

  5. 맨 하위에 대입연산자와 콤마(,)연산자가 있다.


[표 3.12.1] 연산자 우선 순위와 결합 방향

순위

연산자

결합 방향

1

( ) [ ] -> .

2

! ~ ++ -- - + (cast) *(pointer) &(addr) sizeof

3

* / %

4

+ -

5

<< >>

6

< <= > >=

7

== !=

8

&

9

^

10

|

11

&&

12

||

13

?:

14

= += -= *= /= %= ^= |= <<= >>=

15

,


연산자 우선 순위와 결합 방향을 고려하여 프로그래밍하는 것은 프로그래머의 몫이며 프로그래밍은 가독성(간결성)과 효율(길이) 측면에서 고민하게 되는 경우가 자주 발생한다. 한 수식에 부득이하게 연산자를 여러 개를 써야 한다면 괄호 등을 적극 활용하여 우선 순위를 명확히 하는 것이 좋다.


3.12.2 연산자 결합 방향

한 수식에서 동일한 우선순위를 가진 연산자들이 연속적으로 나타나 있으면 연산자의 결합 방향을 고려하여야 한다. 대부분의 연산자들은 왼쪽에서 오른쪽으로 결합을 한다. 하지만 반대로 오른쪽에서 왼쪽으로 결합하는 연산자가 있다.


  1. 단항연산자, 형변환연산자, sizeof등은 오른쪽에서 왼쪽으로 결합한다.

  2. 조건 연산자 (?) 는 오른쪽에서 왼쪽으로 결합한다.

  3. 대입 연산자는 오른쪽에서 왼쪽으로 결합한다.


[표 3.11.1] 연산자 결합 방향 예시

수식

결합 결과

a = x +y - z

a = (x + y) - z

a = x * y / z

a = (x * y) / z

a = x && y || z

a = (x && y) || z

a = y+= z

a = (y+= z)

a = *x++

a = *(x++)


예를 들어서 sA=sY+=sZ 와 같은 표현식은 내부적으로 정해진 결합 순서에 의해서 오른쪽에서 왼쪽으로 결합하겠지만 프로그래머가 아예


sA = (sY += sZ);

와 같이 괄호를 명시하든가 더 가독성을 높이려면


sY += sZ;
sA = sY;

와 같이 두 줄로 나누어 쓰는 것이 더 나아보일 수도 있다. 이는 전적으로 작성자의 성향에 달려있다고 할 수 있다.



Posted by 살레시오
,

 이전 포스트에서처럼 배열은 선언을 먼저 하고 나중에 초기화할 수도 있지만 선언과 동시에 초기화할 수도 있다. 배열을 선언하면서 초기화하는 문법은 다음과 같다.


자료형 배열명[크기] = {값0, 값1, 값2, ... };


배열을 선언하면서 동시에 초기화를 하면 배열 크기는 생략할 수 있다. 이 경우 배열의 크기는 초기값의 개수에 따라 결정된다.


 앞서 들었던 예를 이 방법으로 초기화시키면 다음과 같다.


int iaLength[] = {170, 169, 178, 159, 164};


이렇게 하면 초기값의 개수에 의해서 배열의 크기는 5로 자동으로 결정되게 된다. 만약 배열에 저장할 값들이 미리 정해져 있다면 이 방법이 훨씬 더 간단함을 알 수 있다.


 선언할 때 배열의 크기를 지정했는데 주어진 초기값들이 그 크기보다 작다면 나머지 배열의 요소는 0으로 채워진다. 예를 들어


short saA[100]={1};


의 경우 변수 saA의 첫 번째 요소 saA[0]는 1로, 나머지 saA[1]부터 saA[99]까지는 0으로 초기화 된다.


 하지만 아예 초기값을 주지 않은 경우라면, 예를 들어


char caA[20];


와 같은 경우라면 다음 절에 설명하듯이 이 배열이 전역/정적 배열인지 지역배열인지에 따라서 동작이 달라진다.


이제 배열을 이용하며 다섯 명의 평균키를 구하는 예제를 작성하면 다음과 같다.


#include <stdio.h>
int main()
{
   int iaHeights[] = {170, 169, 178, 159, 164};
   float fAverage = 0.f;
   for (int k=0; k<5; k++) {
       fAverage += iaHeights[k];
   }
   fAverage /= 5;
   printf("average : %f\n", fAverage);
}


여기에서는 산술 평균 (다 더한 후 개수로 나눈 값)을 구해서 화면에 표시해 준다.




Posted by 살레시오
,

5.1 배열의 선언과 초기화     [doc]     [smts]

배열(array)을 설명하기 위해서 다음 표에 기록되어 있는 5명 학생의 몸무게를 데이터로 저장하는 문제로 설명을 시작하도록 하겠다.


[표 5.1.1] 다섯 명의 키 데이터

번호

1

2

3

4

5

키(cm)

170

169

178

169

164


이 5명의 키 자료들을 입력하기 위해서 다음과 같이 int형 변수 5개를 각각 사용할 수 있을 것이다.


int iHeight1 = 170;
int iHeight2 = 169;
int iHeight3 = 178;
int iHeight4 = 159;
int iHeight5 = 164;

이렇게 데이터를 저장하여 관리하여도 문제가 없지만 여러 가지 이유로 비효율적이다.


이와 같이 동일한 성질의 데이터들을 하나의 이름으로 다루기 위해서 배열이라는 자료형이 있다. 배열은 같은 자료형의 데이터들을 연속적인 메모리 공간에 차례대로 저장해서 같은 변수명으로 관리할 수 있다.


 C 언어에서 배열을 선언하는 문법은 다음과 같다.


자료형 배열명[배열크기];

앞에서 예를 든 다섯 명의 키를 저장하는 배열을 선언하기 위해서 다음과 같이 하면 된다.


int iaHeights[5];

여기에서 iaHeights 는 배열의 이름(배열명)이며 배열의 요소(element)의 자료형은 int형이고 배열의 크기는 5이므로 이 배열에는 최대 다섯 개의 int형 값을 저장할 수 있는 것이다.


[표 5.1.2] iaHeights 배열의 메모리 구조

인덱스

0

1

2

3

4

요소

int형

int형

int형

int형

int형


배열 변수를 선언하였다면 이제 다음과 같이 초기화할 수 있다.


iaHeights[0] = 170; //첫 번째 데이터 초기화
iaHeights[1] = 169; //두 번째 데이터 초기화
iaHeights[2] = 178; //세 번째 데이터 초기화
iaHeights[3] = 159; //네 번째 데이터 초기화
iaHeights[4] = 164; //다섯 번째 데이터 초기화

여기서 '배열명[0]' 은 배열의 첫 번째 요소를 지칭한다. 대괄호 [...] 안의 숫자는 배열의 인덱스(index)라고 한다. 인덱스는 1부터가 아니라 0부터 시작하는 것에 유의해야 한다. 배열의 요소는 일반 변수와 동일하게 읽을 수 있으며 갱신할 수 있다.


 다섯 명의 키를 처리하기 위해서 다섯 개의 별개의 변수를 각각 사용하는 것보다 이렇게 배열을 이용하는 것이 훨씬 효율적인데 이는 데이터의 일관성을 유지할 뿐만 아니라 반복문을 사용하기에 용이해서 그렇다.


이제 이 다섯 명의 키를 화면에 출력하는 프로그램을 작성해 보자.


0501-01.c
#include <stdio.h>
int main()
{
  int iaHeights[5]; //배열 선언

  iaHeights[0]=170;
  iaHeights[1]=169;
  iaHeights[2]=178;
  iaHeights[3]=159;
  iaHeights[4]=164;

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

 위와 같이 배열은 선언을 먼저 하고 나중에 초기화할 수도 있지만 선언과 동시에 초기화할 수도 있다. 배열을 선언하면서 초기화하는 문법은 다음과 같다.


자료형 배열명[크기] = {값0, 값1, 값2, ... };

배열을 선언하면서 동시에 초기화를 하면 배열 크기는 생략할 수 있다. 이 경우 배열의 크기는 초기값의 개수에 따라 결정된다.


앞서 들었던 예를 이 방법으로 초기화시키면 다음과 같다.


int iaLength[] = {170, 169, 178, 159, 164};

이렇게 하면 초기값의 개수에 의해서 배열의 크기는 5로 자동으로 결정되게 된다. 만약 배열에 저장할 값들이 미리 정해져 있다면 이 방법이 훨씬 더 간단함을 알 수 있다.


선언할 때 배열의 크기를 지정했는데 주어진 초기값들이 그 크기보다 작다면 나머지 배열의 요소는 0으로 채워진다. 예를 들어


short saA[100]={1};

의 경우 변수 saA의 첫 번째 요소 saA[0]는 1로, 나머지 saA[1]부터 saA[99]까지는 0으로 초기화 된다.


하지만 아예 초기값을 주지 않은 경우라면, 예를 들어


char caA[20];

와 같은 경우라면 다음 절에 설명하듯이 이 배열이 전역/정적 배열인지 지역배열인지에 따라서 동작이 달라진다.


이제 배열을 이용하며 다섯 명의 평균키를 구하는 예제를 작성하면 다음과 같다.


0501-02.c
#include <stdio.h>
int main()
{
  int iaHeights[] = {170, 169, 178, 159, 164};
  float fAverage = 0.f;
  for (int k=0; k<5; k++) {
      fAverage += iaHeights[k];
  }
  fAverage /= 5;
  printf("average : %f\n", fAverage);
}

여기에서는 산술 평균 (다 더한 후 개수로 나눈 값)을 구해서 화면에 표시해 준다.



Posted by 살레시오
,

 비트 마스킹은 다음과 같이 세 가지로 정리된다.

       ❶ 특정 비트를 0으로 만든다. (reset)

       ❷ 특정 비트를 1로 만든다. (set)

       ❸ 특정 비트을 반전시킨다. (toggle)

특정한 비트를 0으로 만들려면 0과 AND연산을 하면 되고 1로 만들려면 1과 OR연산을 하면 된다. 반전시키려면 1과 XOR연산을 취하면 된다. 다음 표에 이것을 정리하였다.

[표 1] 비트 마스크의 종류


x

x&0

0

0

1

0



x

x|1

0

1

1

1



x

x^1

0

1

1

0


이러한 비트 연산 특성을 이용하면 이진수의 특정위치의 비트들을 강제로 1, 0으로 만들거나 혹은 반전시킬 수 있으며 마이크로콘트롤러의 프로그래밍에서 사용빈도가 매우 높은 기법이다.

 비트 이동연산자 << 를 마스킹기법과 조합하여 사용하여 원하는 하나의 비트를 조작하기도 한다. 예를 들어서 unsigned short형 변수 usA가 0xa00b일 때 다른 비트값들은 그대로 유지한 채 8번 비트(b8)만 강제로 1로 만들고 싶다면 다음과 같이 하면 된다.


unsigned short usA = 0xa00b;
usA |= (1<<8);


여기서 (1<<8)의 결과는 이진수로 표시하면 0b 0000 0001 0000 0000 이며 b8만 1로 세트된 데이터이다. 반대로 n번 비트를 0으로 만들고 싶다면 ~(1<<n)과 AND연산을 하면 되고(1<<n 을 반전시켰음에 유의하라), n번 비트를 반전시키려면 (1<<n)과 XOR연산을 취하면 된다.


unsigned short usA = 0xa00b;
usA &= ~(1<<8); //8번 비트만 0으로 만든다


unsigned short usA = 0xa00b;
usA ^= (1<<8); //8번 비트만 반전한다.


 이러한 방법은 특정한 비트가 0인지 1인지를 조건 검사할 경우에도 사용된다. 만약 unsigned char형 변수 ucVar의 6번 비트(b6)가 0인지를 검사하려면 다음과 같이 조건 검사를 하면 될 것이다.


if (ucVar & (1<<6) == 0 ) {
   ...
   // ucVar 의 6번 비트가 0일 경우 수행할 명령들
   ...
} else {
   ...
   // ucVar 의 6번 비트가 1일 경우 수행할 명령들
   ...

}


일반적으로 n번 비트가 0인지를 조사하려면 (1<<n)과 변수와 and연산을 취하여 그 결과가 0인지 검사하면 된다. 이 조건이 거짓이라면 그 비트는 1이라는 결론을 얻을 수 있다.



Posted by 살레시오
,