2.4 정수 자료형과 숫자 상수    [DOC]    [SMTS]

 표 2.1.1에서 분류한 것과 같이 정수형은 크게 다섯 가지(char, short, int, long, long long)의 자료형이 있으며 바이트 수가 클수록 숫자 데이터의 범위도 커지게 된다. 정수형 변수에는 정수형 상수를 저장할 수 있으며 소수점이 없는 숫자는 정수형 상수이다.


 예를 들어 부호가 있는 int 형 변수 ia 를 숫자 0으로 초기화하려면 다음과 같이 하면 된다.


int ia = 0;

이후에는 ia라는 int형 변수를 '사용'하여 정수 값을 저장하거나 산술 연산을 수행할 수 있다.


int ia = 0;
ia = 12 * 34; // *는 곱셈 연산자임

 C언어에서 정수를 표현할 때 0으로 시작되는숫자는 8진수이고, 0x로 시작하는 숫자는 16진수라는 것이다. 예를 들어서 123은 그냥 10진수 123이지만 0123 이라고 입력하면 8진수 123이기 때문에 10진수로 변환하면 83이다. 그리고 0x123은 16진수 123이기 때문에 10진수로 변환하면 291이 된다. 이것을 다음 표에 정리하였다.


[표 2.2.1] 숫자상수의 접두어 예

숫자 상수

십진수값

비고

123

123

10진수

0123

83

8진수

0x123

291

16진수

0b1110

14

2진수 (gcc에서 지원, C++14)


0123의 경우 십진수 123이라고 오해하기 쉬운데 0으로 시작하는 수는 8진수로 간주된다는 사실을 유의해야 한다.


 다음 예를 실행시켜보자.


ex02-02.c

#include <stdio.h>

int main() {
char ca = 123;
unsigned int uia = 0123;
long la = 0x123;

printf("%d, %d, %d", ca, uia, la);
}

실행 결과

123, 83, 291

이 결과로부터 8진수 123은 십진수 83이고 16진수 123은 십진수 291과 같다는 사실을 알 수 있다.

 정수형 상수는 기본적으로 int형으로 간주되므로 내부적으로 저장하는데 4 byte(혹은 2 byte)가 소요가 된다. 만약 숫자 상수를 특정한 자료형으로 지정해 주고 싶다면 접미어를 붙여서 그 데이터형을 지정할 수 있는데 U(혹은 u)를 붙이면 unsigned int형이고 l(혹은 L)은 long형, ul(혹은 UL)은 unsigned long형임을 나타낸다.


표 2.2.2 숫자상수의 자료형을 지정하는 접미어들

접미어

자료형

예제

u/U

unsigned int

37u, 123U
l/L

long

12l, 12L
ul/UL

unsigned long

89ul, 89UL

예를 들면 다음과 같다.


unsigned int uia = 0u;
unsigned long ula = 123ul;

하지만 보통은 숫자 상수는 대입하려는 변수의 자료형에 자동으로 변환되어 저장되므로 굳이 이렇게 일일이 자료형에 맞추어 접미어를 붙여줄 필요는 없다. 즉,


unsigned long ula = 123;

이라고 초기화하여도 123이라는 int형 상수는 자동으로 unsigned long 형으로 변환된 후 변수 ula에 저장된다.


 만약 숫자상수를 short 형이나 unsigned char 형으로 지정하고 싶다면 다음과 같이 해야 한다.


short sa = (short)1;
unsigned char uca = (unsigned char)123;

이와 같이 숫자 상수 앞에 (자료형)을 붙여 자료형을 강제로 변환하는 것을 형변환(casting)이라고 한다. 하지만 이 경우도 아래와 같이 할 수 있다.


short sa = 1;
unsigned char uca = 123;

이렇게 해도 자동으로 형변환이 일어나기 때문에 문제가 없다.


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

2.6 문자 상수  (0) 2016.03.28
2.5 실수 자료형과 실수 상수  (0) 2016.03.28
1.9 2진수와 16진수  (0) 2016.03.07
1.8 atom 설치 / 첫 프로그램 실행하기  (2) 2016.03.07
1.7 windows에서 mingw 설치하기  (0) 2016.03.07
Posted by 살레시오
,

1.9 2진수와 16진수    [DOC]    [SMTS]

1.9.1 2진수

   디지털 시스템에서 자료(data)는 모두 2진수로 저장된다. 2진수 시스템은 두수 (0,1)를 갖는 기수 2 시스템이다. 11010.11과 같은 2진수는 1과 0의 열과 2진 소수점으로 표현된다. 2진수와 같은 값을 갖는 10진수는 기수 2를 갖는 거듭제곱 수의 나열로 숫자를 확장해서 찾을 수 있다.  예를 들면 다음과 같다.


비트가 0일 때는 10진수로 변환하는 합에 영향을 미치지 않는다. 그러므로 10진수로의 변환은 비트가 1인 2의 거듭제곱수의 합으로 얻을 수 있다. 예를 들면 다음과 같다.


1.9.2 16진수

 16진수를 사용하여 2진수를 더 간결하게 표현하는 것이 길이가 4배 더 긴 2진으로 된 비트열을 사용하는 것보다 훨씬 편리하다. 그러므로 디지털 시스템에서는 2진수를 기술하기 위해 16진수를 많이 사용한다.


 16진수는 15까지 한자리로 표현되고 16이 되면 두 자리로 넘어간다. 따라서 10진 시스템에서 가져온 10개의 숫자와 10, 11, 12, 13, 14, 15를 하나의 숫자로 표현하기 위해 사용되는 문자 A, B, C, D, E, F를 갖는 기수 16 시스템이다. 16진수에 대한 예는 다음과 같다.


다음 표에 16진수 0부터 15까지를 2진수와 8진수로 표현한 것을 기술하였다.


[표 1.12.2]  

10진수

2진수

8진수

16진수

00

0000

00

0

01

0001

01

1

02

0010

02

2

03

0011

03

3

04

0100

04

4

05

0101

05

5

06

0110

06

6

07

0111

07

7

08

1000

10

8

09

1001

11

9

10

1010

12

A

11

1011

13

B

12

1100

14

C

13

1101

15

D

14

1110

16

E

15

1111

17

F


이중에서 2진수와 16진수와의 관계는 눈여겨 보아야 한다. 2진에서 16진수로의 변환은 2진 숫자를 소수점부터 시작하여 왼쪽과 오른쪽으로 4비트씩 나눔으로서 쉽게 얻어진다.

1.9.3 10진수로의 변환

 10진수에서 2진수로 변환하는 편리한 방법은 주어진 10진수를 반복해서 2로 나누어서 그때마다 나머지를 써두고, 그 몫을 다시 2로 나누는 방법을 몫이 0이 될 때까지 반복한 후 아래에서부터 위로 나머지를 읽어가는 방법이다. 예를 들어 10진수 103을 2진수로 변환하면 다음과 같다.


103/2

=51 +나머지 1

(LSD)

󰀵

51/2

=25 +나머지 1

25/2

=12 +나머지 1

12/2

= 6 +나머지 0

6/2

= 3 +나머지 0

3/2

= 1 +나머지 1

1/2

= 0 +나머지 1

(MSD)


따라서 (103)10=(1100111)2 가 된다.


 이번에는 (0.125)10 처럼 10진수의 소수값을 2진수로 변환시키는 방법을 알아보자. 주어진 소수값에 2를 곱한다음 그 결과값이 1을 넘으면 1을 써두고 1을 넘지 않으면 0을 써둔 다음 그 너머지 소수값에 다시 2를 곱한다. 이것을 소수값이 없어질 때까지 반복한 다음, 써둔 결과를 위에서 부터 읽어 내려간다. 즉,


0.125×2

=0.25 …정수값 0

(MSD)

0.25×2

=0.5 … 정수값 0

0.5×2

=1.0 … 정수값 1

(LSD)

󰀶


따라서 (0.125)10=(0.001)2이다.


 10진수에서 8진수 혹은 16진수로의 변환도 8 혹은 16으로 나누고 곱한다는 것만 빼고 위와 동일하게 얻어진다.

1.9.4 보수 (선택 사항)

 디지털시스템(digital system)에서는 음수를 표현하기 위해서 2의 보수(2‘s complement)를 사용한다. 1의 보수(1’s complement)는 0과 1을 서로 바꾸어서 얻을 수 있다. 즉 0→1, 1→0으로 변환하는 것이다. 예를 들어서

 n개의 자리수를 가진 2진수 N이 주어지면 2의 보수는 N≠0일 때 2n-N이고 N=0일 때 0으로 정의한다. 2의 보수는 1의 보수에 1을 더하여 얻을 수 있다. 예를 들어



또한 2의 보수는 최하위자리 0과 첫 번째 자리 1을 모두 변하지 않게 하고 다른 모든 상위자리 비트에 있는 1을 0으로, 0을 1로 바꾸어 만들 수 있다. 그래서 (1101100)2의 하위 자리수에 있는 2개의 0과 첫번째 1을 그대로 두고 다른 4개의 상위자리의 비트를 0을 1로 1을 0으로 바꾸어서 (0010100)2를 얻을 수 있다. 보수의 보수가 원래의 값을 갖는다는 것도 중요한 사실이다.

앞에서도 밝혔듯이 디지털 시스템에서는 2의 보수로서 음수를 표시한다. 예를 들어 8bit 숫자 체계에서 -10을 얻으려면 +10의 2의 보수를 구하면 된다. 즉 의 2의 보수인 이 -10이 되는 것이다. 이러한 개념은 감산 하드웨어를 간략하게 하는데 매우 유용하다.


[표 1.12.3] 8비트 수의 2의 보수

2진수

부호 없는 수

부호 있는 수

2의 보수

0000 0000

0

0

-

0000 0001

1

1

-

0000 0010

2

2

-

0000 0011

3

3

-

0111 1110

126

126

-

0111 1111

127

127

-

1000 0000

128

-128

1000 0000

1000 0001

129

-127

0111 1111

1000 0010

130

-126

0111 1110

1111 1101

253

-3

0000 0011

1111 1110

254

-2

0000 0010

1111 1111

255

-1

0000 0001


1.9.5 디지털 데이터 단위

 디지털 시스템에서 모든 데이터는 2진수로 표시된다. 2진수에서 각 자리의 수를 비트(bit)라고 하는데 이것이 디지털 데이터의 최소 단위이다. 2진 신호가 몇 개가 묶였느냐에 따라서 다음과 같이 구분한다.

  • 비트 (bit) : 0/1을 표시하는 최소 데이터 단위

  • 니블 (nibble) : 4 bits

  • 바이트 (byte) : 8 bits

  • 워드 (word) : 2 bytes = 16 bits

  • 더블 워드 (dword) : 2 words = 4 bytes = 32 bits


 다음 표에 220 까지의 십진수를 나열하였다. 이 중에서 210까지는 외우는 것이 앞으로 프로그래밍하는데 있어서 여러모로 편리하다.


[표 2.12.1] 2의 거듭제곱

n

2n

n

2n

0

1

1

2

11

2,048

2

4

12

4,096

3

8

13

8,192

4

16

14

16,384

5

32

15

32,768

6

64

16

65,536

7

128

17

131,072

8

256

18

262,144

9

512

19

524,288

10

1,024

20

1,048,576


또한 8자리 2진수의 최대값은 255, 16자리 2진수의 최대값은 65,535 라는 것도 알아두면 나중에 C언어 변수의 가용 범위를 계산할 때 유용하다.


 디지털 데이터의 용량을 표기할 때 물리적인 단위와는 다소 다르다.


  • 킬로(kilo) : 210 = 1,024

  • 메가(mega) : 220 = 1,048,576

  • 기가(giga) : 230 = 1,073,741,824

  • 테라(tera) : 240 = 1,099,511,627,776


예를 들어서

이다.


Posted by 살레시오
,

1.8 atom 에디터 설치 / 첫 프로그램 실행하기    [DOC] [SMTS]

 프로그램을 입력하기 위해서는 에디터가 필요하다. 편집/저장 기능이 있는 프로그램을 아무 것이나 사용해도 상관없으나 본 교재에서는 atom이라는 에디터를 사용하기로 한다. 이 에디터는 프로그램 저장소로 유명한 github에서 만들어서 무료로 사용할 수 있도록 배포되고 있다. 이 프로그램도 choco 명령어를 이용하면 쉽게 설치할 수 있다. 단, .NET framework 4.5 이상이 사전에 설치되어 있어야 한다.


c:\Users\user>choco install atom

만약 .NET framwork 이 설치되어 있지 않다는 오류가 난다면 atom.io 에서 윈도우용 인스톨러를 다운로드 받아서 설치하는 것이 더 편리하다.


[그림 1.7.1] atom.io 홈페이지. 인스톨러를 다운로드 받을 수 있다.


설치가 끝난 후 윈도우버튼을 확인해 보면 atom 아이콘이 보일 것이다. 이것을 실행하면 된다.


[그림 1.7.2] atom 에디터의 외형


atom 에디터는 컴파일러는 포함되어 있지 않지만 프로그래밍에 유용한 여러 최신 기능들과 플러그인을 무료로 사용할 수 있다. 또한 맥과 리눅스 용도 있어서 한 번 익혀 놓으면 실행 환경이 바뀌더라도 동일한 UI로 사용할 수 있다는 장점도 있다.


 이제 텍스트 에디터를 이용하여 새로운 파일을 생성하여 다음과 같은 프로그래밍을 작성한 후 저장해 보자.


ex01-01.c
#include <stdio.h>
int main() {
   printf("Hello world!\n");
}

그 다음에 콘솔창에서


cc ex01-01.c

라고 입력하면 링크/컴파일이 수행되고 a.exe 실행파일이 생성된다. 이 실행파일을 실행하면 화면에 “Hello world!”가 출력되는 것을 확인할 수 있다.


 이 프로그램에서 다른 부분은 차차로 설명하기로 하고 printf(...) 는 화면에 문자열을 출력하는 함수라는 것만 알아두자. 문자열은 큰따옴표 “...”로 묶은 문자들의 집합을 의미한다. 따라서 printf(“Hello world!\n”) 은 “Hello world!\n”이라는 문자열을 화면에 표시하는 일을 수행한다.



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

2.4 정수 자료형과 정수형 숫자 상수  (0) 2016.03.28
1.9 2진수와 16진수  (0) 2016.03.07
1.7 windows에서 mingw 설치하기  (0) 2016.03.07
1.2 C 언어 소개  (0) 2016.03.04
1.1 프로그래밍 개요  (0) 2016.03.04
Posted by 살레시오
,

1.7 윈도우즈에 mingw 설치    [DOC]    [SMTS]

 윈도우즈에서 실습을 진행하기 위하여 무료로 사용할 수 있는 gcc 컴파일러를 사용하고자 한다. gcc는 리눅스 응용 프로그램 개발에 사용되는 C 컴파일러이므로 우분투와 같은 리눅스 시스템에서는 바로 사용하는데 아무런 문제가 없다. 만약 윈도우즈를 사용한다면 gcc를 윈도우즈에서 사용할 수 있도록 해주는 mingw 패키지가 있으므로 이것을 설치하여 사용하면 된다.

1.7.1 tdm-gcc 설치하기

 윈도우즈에서  mingw를 설치하는 가장 간단한 방법은 tdm-gcc 를 다운로드 받아서 설치하는 것이다. 자신의 윈도우가 32bit 인지 64bit 인지를 확인한 후 해당 버전의 설치판을 다운로드 받아서 설치하기만 하면 된다.

1.7.2 chochlatey 이용하기

 윈도우즈에서 mingw를 설치하는 다른 방법은 chocolatey 라는 윈도우 패키지 매니저를 사용하는 것이다. 다음과  같이 [windows키]+[R]을 누른 후 ‘cmd’를 입력한 후 [ctrl]+[shift]+[enter] 키를 누른다. 그러면 관리자모드로 명령창이 실행된다.


[그림 1.7.1] cmd 실행 창


여기서 chocolatey 홈페이지에 있는 설치 명령을 복사해서 실행시키면 쉽게 설치할 수 있다.


 chocolatey가 설치된 이후에는 choco라는 명령어를 명령창에서 사용할 수 있다. 정상적으로 설치되었다는 것을 확인하고 싶다면 그냥 choco라고 입력하면 chocolatey의 버전이 출력된다.


C:\Users\jhpark>choco
Chocolatey v0.9.9.11

이제 mingw를 다음과 같이 설치할 수 있다.


c:\Users\user>choco install mingw

 어떤 방법으로든 mingw가 정상적으로 설치되었다면 c:\tdm-gcc\mingw32 혹은 c:\tools\mingw32 폴더가 생성되고 그 안에 필요한 파일들이 복사되어있을 것이다. 이제 명령창을 다시 실행시키면 gcc 를 실행시킬 수 있다.


C:\Users\jhpark>gcc --version
gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 4.8.3
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

위와 같이 출력되었다면 이제 gcc 컴파일러를 사용할 준비가 된 것이다.

1.7.3 컴파일 환경 설정

 본 교재에서는 c99 표준을 기준으로 기술되었다. 따라서 gcc를 이 표준에 맞추어 C코드를 컴파일 하도록 하려면 -std=c99 라는 옵션을 주어야 한다. 컴파일을 수행할 때마다 매번 입력하기 번거로우므로 c:\tools\mingw32\bin 폴더 안에 다음과 같은 배치파일을 작성하여 넣어 두자.


cc.bat

@echo off
gcc -std=c99 %*

이제 gcc명령 대신 cc명령으로 C99표준에 맞추어 C프로그램을 컴파일 할 수 있다.


 실습을 위해 별도의 폴더를 하나 생성하여 cmd를 실행할 때마다 그 폴더에서 시작하도록 설정하는 것이 앞으로 실습을 진행하는데 편리하다. 예를 들어 d:\cprog 라는 폴더를 만들고 모든 예제를 이 폴더에 저장하여 실행하고 싶다면 c:\windows\system32\cmd.exe 파일을 찾아서 바탕화면에 단축아이콘을 등록한다. 단축아이콘에서 마우스 오른 버튼을 눌러 속성창을 띄우면 시작 위치를 입력하는 곳이 있다.


[그림 1.7.2] cmd 속성창


그리고 단축키(예를 들어 ctrl+shift+c)를 지정해 놓으면 손쉽게 지정된 폴더에서 시작하는 cmd창을 실행시킬 수 있다.



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

1.9 2진수와 16진수  (0) 2016.03.07
1.8 atom 설치 / 첫 프로그램 실행하기  (2) 2016.03.07
1.2 C 언어 소개  (0) 2016.03.04
1.1 프로그래밍 개요  (0) 2016.03.04
(C언어) scanf() 함수  (0) 2016.02.01
Posted by 살레시오
,

1.2 C언어 소개    [DOC]    [SMTS]

 C 언어는 1972년 유닉스(UNIX) 라는 OS(Operating System, 운영체제)를 개발하기 위한 목적으로 고안된 프로그램 언어로서 벨 연구소의 Ken Tompson이 개발한 B 언어를 개선한 것이다. 같은 연구소에 근무하던 Dennis Ritchie가 DEC PDP-11 이라는 컴퓨터 시스템에서 실행되는 유닉스 운영체제를 바로 이 C 언어로 작성하였고 유닉스는 지속적으로 발전하여 지금까지도 서버(server)의 운영체제로 널리 쓰이고 있으며 리눅스(Linux)의 모체가 되었다.


그림 1.1.1 C언어의 창시자 古 데니스리치(Dennis Ritchie)


 C 언어는 40년도 더 지난 오늘날까지도 지속적으로 개정되면서 많은 사람들에게 사용되어지고 있을 정도로 인기를 얻었다.  C 언어의 역사나 발전 과정과 같은 세세한 부분은 굳이 소개할 필요가 없다고 생각되어 생략한다.  C 언어의 특징은 다음과 같다.


  • 사용자 중심의 고급 언어이다. 즉, 인간이 읽고 해독하기 용이하다.

  • 그러면서도 하드웨어를 직접 제어할 수 있는 저급 언어의 특징을 갖는다.

  • 문법이 간결하고 키워드가 다른 언어에 비해서 상대적으로 적다.

  • 이식성이 좋다. 즉, 같은 코드로 여러 운영 체제에서 사용 가능하다. (C 언어가 사용되기 시작한 초창기에 이것은 매우 중요한 특성이었다.)

  • 대부분의 경우 매우 효율적이며 고속으로 실행된다.

  • C++ 혹은 JAVA로 건너가기 위한 선행 언어이다.


여기서 저급 언어(low-level language)는 기계가 해독하기 용이하지만 사람이 읽고 해독하는데 매우 어려운 언어를 지칭한다. 대표적인 저급 언어로 기계어(machine language)와 어셈블리어(assembly language)가 있다. 반대로 고급 언어(high-level language)란 인간의 언어와 유사하여 사람이 읽고 해독하기 용이한 프로그래밍 언어라는 의미이며 기계어와 어셈블리어를 제외한 대부분의 프로그래밍 언어가 이 분류에 속한다.


이후에 기술이 발전하여 컴퓨터의 속도가 빨라짐에 따라 소프트웨어의 덩치도 커지게 되었고, C 언어로는 규모가 큰 프로그램을 개발할 때 프로그램의 코드를 관리하는데 어려움을 겪게 되었다. 이러한 점을 개선하기 위해서 C 언어와의 하위 호환성을 유지하면서 객체 지향 특성(object oriented programming) 및 편의 기능들을 추가하여 1983년 즈음에 Bell 연구소의 Bjarne Stroustrup 이 C++ 언어를 개발하였으며 java, javascript, C# 같은 많은 언어들이 C/C++ 의 문법을 기반으로 개발되고 널리 사용되고 있다.


[그림 1.1.2] 가장 많이 사용되는 프로그래밍 언어 (2015년, www.codeeval.com)


 이 그림에서 보듯이 근래에는 C언어가 차지하는 비중은 크지 않으나 마이크로콘트롤러나 DSP를 사용한 임베디드 프로그래밍 분야나 성능이 중요한 시스템의 프로그래밍 분야는 C언어가 아직도 주력으로 사용되고 있다.

Posted by 살레시오
,

1.1 프로그래밍 개요     [DOC]    [SMTS]

 근래에 들어서 전 세계적으로 소위 코딩(coding)에 대한 관심이 높아지고 있으며 우리나라도 코딩 교육의 중요성을 인식하고 중등 학생들도 관련 과목이 정규 교과에 반영되도록 하는  여러 정책들이 만들어지고 있다.


 코딩이란 컴퓨터가 주어진 일을 수행하도록 프로그램(program)을 작성하는 것을 말한다. 프로그램이란 인간이 작성하고 기계(주로 컴퓨터와 같은 디지털 시스템)가 해독하여 실행할 수 있는 문서이다. 프로그램을 작성하는 문법을 정한 규약을 프로그래밍 언어(programming language)라고 한다. 본 교재에서 다루는 C 언어도 다양한 프로그래밍 언어 중 하나이다.


  • 코딩 : 컴퓨터가 주어진 일을 수행하도록 프로그램(progrma)을 작성하는 것

  • 프로그램 : 인간이 작성하고 기계(주로 컴퓨터와 같은 디지털 시스템)가 해독하여 실행할 수 있는 문서

  • 프로그래밍 언어 : 프로그램을 작성하는 문법을 정한 규약


[그림 1.1.1] 현대의 디지털 시스템의 예


 프로그램이 필요한 대상은 작은 마이크로컨트롤러(micro-controller) 시스템부터 소형 임베디드 시스템(embedded system), 스마트폰, 태블릿, 컴퓨터, 서버, 데이터 센터 등 그 폭이 매우 넓다. 현대의 인간이 생활하는데 필수 불가결한 시스템들이 모두 프로그램에 의해서 동작하고 있으며 따라서 코딩하는 기술은 매우 중요할 뿐만 아니라 새로운 산업까지 일으킬 수 있는 부가가치가 높은 영역으로 인식되고 있다.



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

1.7 windows에서 mingw 설치하기  (0) 2016.03.07
1.2 C 언어 소개  (0) 2016.03.04
(C언어) scanf() 함수  (0) 2016.02.01
(C언어) 구조체의 포인터  (0) 2016.02.01
(C언어) 구조체 배열  (0) 2016.02.01
Posted by 살레시오
,

 함수 scanf()는 (보통은 키보드로) 입력을 받아들이는 기능을 수행하면 stdio.h 에 정의되어 있다. 만약 하나의 정수를 입력받아서 a라는 변수에 저장하고 싶다면 다음과 같이 해야 한다.


scanf(“%d”, &a);


이렇게 하면 사용자로보터 숫자 입력을 받아서 변수 a에 저장한다. ‘&’는 주소 연산자로서 포인터를 설명하는 장에서 자세히 알아볼 것이고 여기에서는 scanf()함수에서는 변수 앞에 &를 붙여야 한다고만 알아두고 넘어가자.


ex02-04.c

#include <stdio.h>

int main() {
int ia;
printf("input an integer :");
scanf("%d", &ia);
printf("your input is %d.",ia);
}

실행 결과

input an integer :1234
your input is 1234.


실수를 입력받을 때는 %f (float형) 나 %lf (double 형) 지시자를 사용하면 된다.


ex02-05.c

#include <stdio.h>

int main() {
float fa;
printf("input a real number :");
scanf("%f", &fa);
printf("your input is %f.", fa);
}

실행 결과

input a real number :1.23
your input is 1.230000.


두 개 이상의 입력을 한 번에 받으려면 다음과 같이 하면 된다.


ex02-06.c

#include <stdio.h>

int main() {
int ia, ib;
printf("input two integers :");
scanf("%d %d", &ia, &ib);
printf("your inputs are %d and %d.", ia, ib);
}

실행 결과

input two numbers :11 22
your inputs are 11 and 1.


여기서 scanf() 함수 내에서 "%d %d"와 같이 %d와 %d가 공백문자로 구분되어 있다면 사용자가 숫자르 입력할 때에도 공백문자로 구별해야 한다. 만약


scanf("%d,%d", &ia, &ib);


와 같이 콤마(,)로 구분되어 있으면 사용자도 11,22 와 같이 콤마로 구별해서 숫자를 입력해야 한다. 그렇지 않으면 오동작이 일어난다.

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

1.2 C 언어 소개  (0) 2016.03.04
1.1 프로그래밍 개요  (0) 2016.03.04
(C언어) 구조체의 포인터  (0) 2016.02.01
(C언어) 구조체 배열  (0) 2016.02.01
(C언어) 구조체 변수를 필드로 가지는 구조체  (0) 2016.02.01
Posted by 살레시오
,

구조체 변수도 포인터로 선언할 수 있으며 문법은 기본 자료형의 경우와 동일하다.


Point *pa;


이렇게 선언하면 pa는 Point 구조체 포인터 변수이다. 포인터 변수의 경우 필드는 다음과 같이 ‘->’ 연산자를 사용하여 접근할 수 있다.


pa->x = 0;
pa->y = 1;


즉, 구조체 포인터의 접근자는 점(.)이 아니라 ‘->’ 이다. 혹은 미리 정의된 Point 변수를 대입시킬 수도 있다.


Point a = {0,1};
Point *pa;
*pa = a;


 함수로 구조체 변수를 넘길 때 복사본이 넘어가는 것은 기본 자료형과 같다. 따라서 어떤 함수에서 넘겨받은 구조체 변수의 필드를 변경하는 것은 원래 변수에 아무런 영향을 미치지 않는다.


ex08-10.c

#include <stdio.h>

typedef struct {
double x;
double y;
} Point;

void showInfo(Point a) {
printf("(%f, %f)", a.x, a.y);
}

void changeToOrigin(Point a) {
a.x = 0;
a.y = 0;
}

int main(int argc, char **argv) {
Point a = {11,12};
printf("a:(%.2f, %.2f)\n", a.x, a.y);
changeToOrigin(a);
printf("a:(%.2f, %.2f)\n", a.x, a.y);
}

실행 결과

a:(11.00, 12.00)
a:(11.00, 12.00)


위 예에서 changeToOrigin()함수를 호출할 때 Point 변수 a를 넘기고 이것이 함수 내부에서 원점으로 변경되었지만 원래 변수에는 전혀 영향을 미치지 않느다. 왜냐면 구조체 변수의 복사본이 함수로 넘어가기 때문이다.


 하지만 함수로 포인터를 넘기면 원래 구조체 필드를 직접 접근할 수 있다.


ex08-10b.c

#include <stdio.h>

typedef struct {
double x;
double y;
} Point;

void showInfo(Point a) {
printf("(%f, %f)", a.x, a.y);
}

void changeToOrigin(Point *a) {
a->x = 0;
a->y = 0;
}

int main(int argc, char **argv) {
Point a = {11,12};
printf("a:(%.2f, %.2f)\n", a.x, a.y);
changeToOrigin(&a); //<- 포인터를 넘긴다.
printf("a:(%.2f, %.2f)\n", a.x, a.y);
}

실행 결과

a:(11.00, 12.00)
a:(0.00, 0.00)


위에서는 changeToOrigin()함수가 Point형 포인터를 받아서 필드를 변경한다. 호출하는 쪽에서도 a변수의 포인터(&a)를 넘겨준다. 이러면 changeToOrigin()함수 내부에서 원본을 변경할 수 있다. 실행 결과에서 보면 변수 a의 필드들이 변경되었음을 알 수 있다.

Posted by 살레시오
,

 기본 자료형과 마찬가지로 구조체 변수도 배열을 형성할 수 있다. 예를 들어 Point 형 변수 세 개를 배열로 생성하고 싶다면 다음과 같이 하면 된다.


Point pa[3];


이렇게 하면 크기가 3인 Point형 배열 변수 pa가 생성된다. 초기화 방법은 배열의 초기화와 동일하다.


Point p0 = {0,0};
Point p1 = {1,1};
Point p2 = {2,2};
Point pa[3] = {p0, p1, p2};


또는 다음과 같이 바로 초기화를 할 수도 있다.


Point pa[3] = {{0,0}, {1,1}, {2,2}};


배열 각 요소를 통하여 구조체의 필드를 접근할 수 있다.


Point pa[3];
pa[0].x = 0;
pa[0].y = 0;
pa[1].x = 1;
pa[1].y = 1;
pa[2].x = 2;
pa[2].y = 2;


동일한 방법으로 초기화 이후에도 각 필드의 값을 자유롭게 접근하여 읽거나 변경할 수 있다.


 배열의 크기가 커지면 반복문을 이용하여 구조체 필드를 초기화하는 것이 일반적이다. 예를 들면 다음과 같다.


ex08-09.c

#include <stdio.h>

typedef struct {
double x;
double y;
} Point;

int main(int argc, char **argv) {
Point pta[100];
for (int k=0; k<100; k++) {
pta[k].x = 1;
pta[k].y = 1;
}
}


또는 미리 정의된 Point형 변수를 이용할 수도 있다.


ex08-09.c

#include <stdio.h>

typedef struct {
double x;
double y;
} Point;

int main(int argc, char **argv) {
Point pt = {1,1};
Point pta[100];
     // 100개의 요소를 pt로 초기화시킨다.
for (int k=0; k<100; k++) {
pta[k] = pt;
}
}


이와 같이 구조체도 배열을 생성하여 사용할 수 있다.

Posted by 살레시오
,

 어떤 구조체의 필드가 다른 구조체의 변수가 될 수도 있다. 직사각형의 정보를 갖는 Rect라는 구조체를 작성해 보자. 이 구조체는 마주보는 두 꼭지점의 의 좌표를 가지고 있어야 한다.


typedef struct {
double x;
double y;
} Point;

typedef struct {
Point leftTop;
Point rightBot;
} Rect;

여기에서 보면 Rect 구조체는 두 개의 Point 구조체 변수를 가지고 있다. 이런 식으로 구조체의 필드가 다른 구조체의 변수가 될 수 있다.


 구조체 Rect를 초기화 시키는 방법은 다음과 같이 몇 가지 방법이 있다.


// 초기화 방법 1 : 모든 구조체 변수를 생성과 동시에 초기화함
Rect ra = {{0, 1}, {11, 12}};
// 초기화 방법 2 : 이미 정의된 Point 변수 이용
Point p1 = {0, 1}, p2 = {11, 12};
Rect rb = {p1, p2};
// 초기화 방법 3: 선언 후 각각의 필드에 초기값 대입
Rect rc;
rc.leftTop.x = 0;
rc.leftTop.y = 1;
rc.rightBot.x = 11;
rc.rightBot.y = 12;


이제 사각형의 면적을 구하는 함수를 추가한 전체 소스 코드는 다음과 같다.


ex08-08.c

#include <stdio.h>

typedef struct {
double x;
double y;
} Point;

typedef struct {
Point leftTop;
Point rightBot;
} Rect;

double calcArea(Rect);

int main(int argc, char **argv) {
// 초기화 방법 1 : 모든 구조체 변수를 생성과 동시에 초기화함
Rect ra = {{0, 1}, {11, 12}};
// 초기화 방법 2 : 기정의 된 Point 변수 이용
Point p1 = {0,1}, p2 = {11, 12};
Rect rb = {p1, p2};
// 초기화 방법 3: 선언 후 각각의 필드에 초기값 대입
Rect rc;
rc.leftTop.x = 0;
rc.leftTop.y = 1;
rc.rightBot.x = 11;
rc.rightBot.y = 12;
printf("area of ra : %f\n", calcArea(ra));
printf("area of rb : %f\n", calcArea(rb));
printf("area of rc : %f\n", calcArea(rc));
}

double calcArea(Rect r) {
double dx = r.rightBot.x - r.leftTop.x;
double dy = r.rightBot.y - r.leftTop.y;
return dx*dy;
}

실행 결과

area of ra : 121.000000
area of rb : 121.000000
area of rc : 121.000000


이와 같이 구조체의 필드로 다른 구조체 변수도 얼마든지 사용할 수 있다. 다만 구조체를 정의하는 순서에 유의하면 된다. 당연한 얘기지만 Rect 구조체가 Point 구조체 뒤에 와야 한다.

Posted by 살레시오
,