Transcript C 기초

C 언어
- 기본 -
1
C언어소개
1969년에... AT&T 연구소의 Ken Thompson은 연구소의
한쪽 구석에 방치되어 있던 작은 컴퓨터를 보고 운영체제 'UNIX'
의 개발을 시작했습니다. 이 작업에 가담하고 있었던 Dennis
Ritchie 이라는 사람이 'C' 라고 하는 언어를 만들었고. 결국
UNIX 는 C 언어로 다시 프로그래밍되었습니다.
그런데, 왜 이름이 'C' 일까요?
원래 'CPL(Combined Programming Language)' 이라는 언어가
있었는데, 그 언어에서 'BCPL(Basic CPL)' 이라는 언어가 파생
되었고, 다시 그 언어에서 파생한 언어를 BCPL의 선두 문자를
따서 'B' 라고 이름을 붙였습니다. C 언어는 다시 그 B 언어에서
파생되었기 때문에 BCPL의 2번째 문자를 따서 (혹은 B의 다음
알파벳을 따서) 'C' 라고 지어졌다고 합니다.
2
요약하자면 C언어는 UNIX 운영체제 하에서 시스템 프로그래밍
을 하기 위해 개발된 아주 강력한 기능을 가진 프로그래밍 언어입
니다.
C 언어는 구조화 프로그래밍을 지향하는 언어이고 정말로 가장
쓸모있는 언어라고 할 수 있습니다.
이유는 C 언어에서는 못하는게 없기 때문이죠. 좀 과장된 표현 같
기도 하지만 다른 언어들과 비교해 볼 때 못하는 거란 없습니다.
그리고 C 언어로 만든 프로그램의 속도는 어셈블리어만큼이나
빠른 속도를 내기 때문에 빠른 속도를 요구하는 프로그램에도 적
합하죠. 단 게임과 같은 곳에서는 C 언어의 속도조차도 느리기 때
문에 어셈블리가 요구되는 곳이 있지만, 요즘 C 언어 컴파일러들
은 인라인 어셈블러라는 것을 지원해서 C 소스 내에 어셈블리 코
드를 추가할 수 있습니다. 이런 점으로 볼 때 C로는 못하는게 없
다고 봐도 되겠죠?
그래도 실감이 나지 않으시면 C 언어로 만들어진 대표적인 프로
그램을 예로 들어 볼까요?
3
그런데 그럴려면 한가지 문제가 있네요. 이 문제가 뭐냐 하면... C언어로 만들어
진 유명한 프로그램이 너무나도 많다는 것이죠. 그래도 몇 가지 예를 들어 보죠.
우선 OS에서는 UNIX의 커널의 일부분을 제외한 모든 부분이 C로 만들어졌습
니다. 정말 굉장하죠?
그리고 Windows 95(98)도 커널의 일부분과 *.VxD만 빼면 모두 C 로 만들어졌습
니다. 그것두 우리가 잘 알고 있는 Visual C++의 버전 2.1로 만들어졌죠.
또 하나 굉장한 사실이 있는데..
Windows NT는 커널 부분까지 C 로 만들어졌다는 것이죠. C 언어로 만들어진
프로그램에는 게임도 많은데, 대부분의 게임은 C 언어로 만들어졌다고 보면 됩
니다.
예전의 도스용 게임을 시작할 때
DOS/4GW Protected Mode Run-time Version 1.97
copyright (c) Rational Systems Inc. ............
이런 것을 많이 보셨을 겁니다. 유명한 게임을 시작할 땐 다 이게 나오는데, 이게
나오는 건 C 언어도 만들어진 것입니다. Watcom C++라는 개발 툴로 만들어진
것이죠. 또 한가지 놀라운 사실이 있는데, C 언어 컴파일러도 C 언어로 만든다
는 것이죠.
이정도면 C 언어로 못하는게 없다는 말이 이해가 되시겠죠?
그럼 이제 그 C 언어의 세계로 들어가 보도록 하죠.
4
C언어에는 어떤 종류가…?
C 언어에는 어떤 종류가...'라는 제목을 보고 글이 자꾸 읽고 싶어 지신다
면 그 분은 분명 C 언어 초보자입니다. 하지만 이 제목을 보고선 무언가
이상하다고 느끼시면 진정한 전문가라고 할 수 있죠.
이유가 궁금하시죠? 이유는 C 언어에는 종류가 없기 때문이죠. 종류가
없는데 제목이 저러니 당연히 이상할 수 밖에요. C 를 처음 하시는 분들
이 많이 질문하시는 것들 중 하나가 'C 와 Visual C의 차이점이 무엇인가
요?' 입니다. 제가 이 질문을 받았다면 이렇게 답해 드리고 싶군요.
'C 는 언어이고 Visual C 는 언어가 아닙니다.' 라구요. 여기서 Visual C
라는 건 Microsoft라는 회사에서 만든 C 언어로 프로그래밍할 때 필요한
도구를 말합니다. 즉 언어가 아니라는 것이죠. 단지 C 언어로 프로그래
밍을 할 때 필요한 도구에 지나지 않습니다. 언어는 바로 C 이죠.
그러므로 Visual C 와 Borland C 등은 문법에선 차이가 있을 수 없습니
다
5
정리하면 C는 언어이고, Visual C, Borland C 등은 언어가 아니라 C 언어
를 사용해 프로그램을 제작하기 위한 도구이며, 모두 C 언어 프로그램을
제작하기 위한 도구이므로 기본 문법의 차이는 있을 수 없다는 것을 꼭
기억하시기 바랍니다. 그리고 여기서 한가지 말씀드릴 것이 있는데, 위
에 Visual C 라고 썼지만 실제는 이게 아니고 Visual C++입니다.
그럼 또 한가지 의문이 생기실텐데 Visual C++에서 C++가 아닌 C 언어
프로그램을 작성할 수 있는지 말입니다.
이 의문의 답은 당근 Yes!!입니다.
C++라는 언어는 C 언어를 객체 지향 프로그래밍이란 것을 할 수 있도록
확장시킨 언어이죠. 그래서 C++언어는 C 언어를 포함한다고 할 수 있
죠. 그러므로 Visual C++에서 아무리 C++라고 쓰여져 있어도 C 프로그
래밍은 가능합니다.
6
C언어는 어떻게 …
이제 C 언어 프로그램이 어떻게 실행되는지를 알아봅시다. C 언어로 프로그램을
만들면 실행파일(.EXE)을 만들 수가 있습니다. 실행파일이 만들어질 때는 다음
과 같은 과정을 거칩니다.
(1) 소스 코드 ==텍스트 에디터==> (2) 소스 파일 ==선행처리기==> (3) 선행
처리기 지시어가 번역된 소스 파일 ==컴파일러==> (4) 목적 파일(.OBJ) ==링커,
라이브러리==> (5) 실행파일(.EXE)
(1) 소스 코드 (Source)
프로그램의 내용 자체를 소스 코드라고 합니다.
(2) 소스 파일 (Source file)
소스 코드를 텍스트 파일에 기술하여 만들어진 파일을 소스 파일이라고 합니다.
C언어의 소스 파일은 확장자가 .C 입니다. C 언어 프로그램 만드는 가장 첫번째
과정이라고 할 수 있죠. (참고로 C++용 소스는 확장자가 .CPP 가
많습니다.)
7
(3) 선행처리기 지시어가 번역된 소스 파일
C 언어 프로그램 내에는 여러가지 지시어들이 있는데 이건 C 언어 문법과는 별
개이고 번역도 컴파일러가 하지 않습니다.
이걸 번역하는 프로그램을 선행처리기라고 합니다.
(4) 목적 파일 (Object file)
지시어가 번역된 소스 파일은 다음으로 컴파일러라는 프로그램에 의해 기계어
로 번역됩니다. 이 번역된 파일을 목적 파일이라고 하고, 확장자는 .OBJ가 됩니
다. 그런데 여기서 이상한 점이 있죠? 기계어로 번역하면 실행할 수 있을 건데
왜? Why? 모땀시? 실행파일을 만들지 않고 목적파일이라는 것을 만들까요? 하
지만 기계어로 번역되었다고 해서 실행할 수는 없습니다. 실행파일이 되기 위해
선 런타임 라이브러리라는 것이 목적 파일과 합쳐져야 하기 때문이죠. 이 런타
임 라이브러리가 무엇인지는 나중에 설명하기로 하고 그냥 런타임 라이브러리
라는 것이 합쳐져야 한다는 것만 알아두세요.
(5) 실행 파일 (Executable file)
목적파일은 위에서 말한 런타임 라이브러리와 합쳐져서 실행파일이 되는데, 이
때 합쳐주는 프로그램을 링커(Linker)라고 합니다. 링커에 의해 목적 파일은 실
행파일이 되죠. 그럼 실행할 수가 있게 됩니다.
8
우선순위
연
산
자
우
선
순
위
연산자
함수,괄호
배
열
구 조 형
형
포 인 터
증가감소
산
술
1
()
[]
.

2
3 4
5
6
7
<
<=
>
>=
==
!=
8 9
10
& ^
|
11
12
&&
||
13
14
(형)
sizeof
*
&
++
-+(단항)
관
동
계
등
비
트
~
논
조
리
건
!
*
+
/
%
<<
>>
?:
=
+=
*=
등
배 정
콤 마
결 합 성
15
좌우 우좌
좌

우
우좌
,
좌우
9
기본 데이터 형

기본 데이터형
– 문자형
• char
1byte
– 정수형
• short
• int
• long
2bytes
2bytes
4bytes
– 실수형
• float
• double
4bytes
8bytes
– unsigned
10
Hello world
#include <stdio.h>
void main()
{
printf("Hello world!");
}
11
Printf #1
#include <stdio.h>
void main()
{
printf(Honey moon baby);
printf('Help me');
printf("Wonder boy");
printf("New line\n");
printF("<<<+++>>>");
printf('1');
}
12
Printf #2
#include <stdio.h>
void main()
{
printf("<%d>\n", 10);
printf("<%d>\n", 10 + 10);
printf("<%5d>\n", 10);
printf("<%-5d>\n", 10);
printf("<%05d>\n", 10);
printf("<sum is %d>\n", 10 + 20);
printf("%d %d\n", 10+20, 10*20);
printf("%d\t%d\n", 10+20, 10*20);
}
13
Printf #3
#include <stdio.h>
void main()
{
char c = 'c';
printf("%c %d %x \n", c, c, c);
}
14
Printf formats
#include <stdio.h>
void main()
{
printf("%c\n", 152);
printf("%d\n", 152);
printf("%o\n", 152);
printf("%x\n", 152);
printf("%f\n", 152.0);
printf("%e\n", 152.0);
printf("%E\n", 152.0);
printf("%g\n", 152.0);
}
15
Printf formats
포맷
의미
%c
문자 출력
%s
문자열 출력
%d
10진수로 출력
%o
8진수로 출력
%x
16진수로 출력
%f
Floating number
%e
Exponential number
%E
대문자 E로된 %e
%g
%f 혹은 %e
%p
포인터 출력
16
오늘의 해결과제
1> 소스 파일(SOURCE FILE)
여러분이 직접 짠 프로그램 이름은 맘대로 지어도 좋으나 확장자는
꼭 .c 로 만듭시다.( 예) my.c )
2> 오브젝트 파일(OBJECT FILE)
컴파일러가 my.c를 이용해 만든 파일 ( my.obj)
3> 실행파일(EXECUTABLE FILE)
링커가 my.obj를 이용해 만든파일 ( my.exe)
보통은 3개 이름이 똑같으므로 확장자(extention) .c .obj .exe 로 구별
하여 한 형제들 이라는 것을 압니다. my.exe 처럼 실행 파일을 만든후
에는 언제든지 "my" 하고 리턴 키(enter key) 만 치면 자기가 짠 프로그
램을 실행 시킬 수 있습니다. (단 my.exe 가 있는 디렉토리에 가서 )
17
오늘의 해결과제
< DOS 상식>
실행 파일 은 3가지 가 있습니다.아래와 같이 확장자가 .exe .com .bat
로 된 파일은 앞 부분 "xxx" 만 치면 프로그램이 실행 됩니다.
1> xxx.exe
2> xxx.com
3> xxx.bat우리가 C 소스(source) 프로그램을 짜는 이유는 이중에
서 .exe 파일을 만들기 위함 이지요. .exe 파일이 CPU가 알아듣는 기계
어로 가득찬 파일이고,우리는 이과정을 "컴파일 한다" 라고 얘기합니다.
아래 파일을 3 개씩 관계 있는 것 끼리 묶어 보세요
형제 파일 3 개중 파일크기가 가장 큰것은 ?
다음 파일 들 중 text 파일은 어떤 것 입니까 ?
형제 파일 3 개를 태어난 순서대로 정렬 하면 ?
사람이 직접쳐서 만든 파일은 어떤 것입니까 ?
.exe 파일은 누가 만듭니까 ?
18
변수 이름
알파벳 문자
 숫자
 밑줄 문자
 대소문자 구별
 숫자로 시작 불가
 예약어 사용 불가
 공백, 특수문자 사용 불가

19
예약어 모음
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
20
변수 선언과 초기화
void 함수 이름()
{
변수 선언부
처리부
}
21
변수 선언
void main()
{
int 2002worldcup;
short grand$total;
double float;
char string-variable[100];
int 변수1;
}
22
변수 초기화
void main()
{
char c = 'c';
int integer = 100;
double pi = 3.14;
long l = 1839394012034;
int i = 0 , j = 1, l = 123;
}
23
void main(void)
{
int i = 0;
int i1, i2;
unsigned int ui = 10203;
long int li = 339220000l;
i1 = 1;
i2 = i + i1;
printf("i = %d\n", i);
printf("i1 = %d\n", i1);
printf("i2 = %d\n", i2);
printf("ui = %d\n", ui);
printf("li = %d\n", li);
}
24
void main(void)
{
float f = 3.142;
float f1;
float f2;
double d = 22.83e2;
f1 = 83.382;
f2 = f + f1;
printf("f = %f\n", f);
printf("f1 = %f\n", f1);
printf("f2 = %f\n", f2);
printf("d = %g\n", d);
}
25
main()
{
int a=1.e5; b=1e5;
float c = a * b;
printf(“%2.1E \n”,c);
}
26
#include <stdio.h>
void main()
{
char c;
short s;
int i;
long l;
float f;
double d;
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
char uc;
short us;
int ui;
long ul;
float uf;
double ud;
}
27
#include <stdio.h>
void main()
{
char c;
short s;
int i;
long l;
float f;
double d;
c = 'A';
c = 'AB';
c = "AB";
s = 3;
s = -3;
s = 0x3;
28
i = 3;
i = -3;
i = 03;
l = 1234l;
l = 1234L;
f = 0.1234f;
f = .1234F;
d = 1.234e+2;
d = 1.234E+2;
}
29
오늘의 해결과제
1.
입.출력 함수들(printf, scanf, getchar, putchar…)
을 사용하여 자신의 이름을 입력받아 다시 출력
하는 프로그램을 작성하시오.
2.
Library 함수들을 MSDN(도움말)에서 찾아서 그
예제들을 실행시키고 함수 사용법과 그 소스 파일
들을 분석해 오시오.(가장 기본적인 MSDN 사용법
익힐것)
30
문자 변수와 상수
void main()
{
char sex;
sex
sex
sex
sex
=
=
=
=
'M';
"M";
'Male';
"Male";
}
31
Escape sequences
(특수문자 : ‘\’)
‘\’ 이후 존재하는 문자를 ASCII코드로 부터 escape하여 다른 의미를
표시하기
위한 특수문자이다.
\a : alert(bell)
\b :
backspace
\f :
form feed
\n :
newline
\r :
carriage return
\t :
horizontal tab
number
\v :
vertical tab
\\ :
\? :
\’ :
backslash
question mark
single quote
\” : double quote
\ooo : octal number
\xhh : hexadecimal
\0 :
null
32
특수 문자
// Escape sequence
#include <stdio.h>
#include <conio.h>
void main()
{
putch(“\a”);
putch('\b');
putch('\f');
putch('\n');
putch('\r');
putch('\t');
putch('\v');
33
putch('\\');
putch('\?');
putch('\'');
putch('\"');
putch('\064');
putch('\x64');
putch('\0');
}
34
puts
#include <stdio.h>
#include <conio.h>
void main()
{
puts("가");
puts("C:\\windows");
puts(0x65);
puts("\n");
};
35
오늘의 해결과제
1.
자연수를 1~100까지 차례대로 출력하고 숫자에
해당하는 10진수,8진수로 출력하는 프로그램을
작성하시오.
2.
오늘 배운 여러가지 자료형들(int,char,double,float
…등등)을 어떠한 경우에 구분해서 사용해야 하는
지 생각해 보고 자료형에 맞는 변수를 만들어서
입력받고 출력해보는 프로그램을 작성하시오.
36
ASCII
32 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' 40 (
41 ) 42 * 43 + 44 , 45 - 46 . 47 / 48 0 49 1 50 2
51 3 52 4 53 5 54 6 55 7 56 8 57 9 58 : 59 ; 60 <
61 = 62 > 63 ? 64 @ 65 A 66 B 67 C 68 D 69 E 70 F
71 G 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O 80 P
81 Q 82 R 83 S 84 T 85 U 86 V 87 W 88 X 89 Y 90 Z
91 [ 92 \ 93 ] 94 ^ 95 _ 96 ` 97 a 98 b 99 c 100 d
101 e 102 f 103 g 104 h 105 i 106 j 107 k 108 l 109 m 110 n
111 o 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w 120 x
121 y 122 z 123 { 124 | 125 } 126 ~ 127 • 128 €129 ?130 ?
37
설명문

/*로 시작해서 */ 로 끝남.

프로그램의 도입부에서 프로그램을 설명

함수, 특정 코드 부분의 기능을 설명

중첩될 수 없음
38
연산자의 종류













괄호 : ()
배열 : []
구조형 : . ->
형:
(type) sizeof
포인터 : * &
증가, 감소 : ++ -산술 : + - * / %
관계, 동등 : < > <= >= == !=
비트 : ~ << >> & ^ |
논리 : ! && ||
조건 : ? :
배정 : = += -= *= /= 등
콤마 : ,
39
사칙연산
void main()
{
int a = 20, b = 25;
printf("a
printf("a
printf("a
printf("a
+ b = %d\n", a + b);
- b = %d\n", a - b);
* b = %d\n", a * b);
/ b = %d\n", a / b);
}
40
비트 연산자
void main()
{
int a = 0xffff;
int b = 0x0f0f;
printf("a = %x\n", a);
printf("a & %x = %x\n", a & b);
printf("a | %x = %x\n", a | b);
printf("a ^ %x = %x\n", a ^ b);
printf("~a = %x\n", ~a);
}
41
비트쉬프트 연산자
void main()
{
int a = 0x1248;
printf("a
printf("a
printf("a
printf("a
printf("a
= %x\n", a);
<< 1 = %x\n",
<< 2 = %x\n",
<< 3 = %x\n",
<< 4 = %x\n",
a
a
a
a
<<
<<
<<
<<
1);
2);
3);
4);
}
42
관계연산자
void main()
{
int a = 15;
if(a <= 30)
printf("a <= 30\n");
if(a =< 30)
printf("a =< 30\n");
if(a >= 30)
printf("a >= 30\n");
if(a =! 30)
printf("a =! 30\n");
printf("a = %d\n", a);
}
43
논리 연산자
void main()
{
int a, b;
a = 0;
b = 0;
if( !( (a != 0) || (b != 0) ) )
printf("a and b are zero numbers\n");
else
printf("a or b is non-zero number\n");
}
44
증가, 감소 연산자
void main()
{
int a, b;
a = b = 30;
printf("(%d, %d) ", a, b);
printf("%d\n", ++a);
printf("(%d, %d) ", a, b);
printf("%d\n", a++);
printf("(%d, %d) ", a, b);
printf("%d\n", ++a + ++b);
printf("(%d, %d) ", a, b);
printf("%d\n", b++ + b++);
printf("(%d, %d) ", a, b);
}
45
증감 연산자
main()
{
int i = 10, j = 2;
i += j++;
printf("i = %d, j = %d\n",i,j);
/* ⑴ */
{ int i = 2;
i += j;
j -= i;
printf("i = %d, j = %d\n",i,j);
/* ⑵ */
{ int j = 5;
j *= i + 1;
++i;
printf("i = %d, j = %d\n",i,j); /* ⑶ */
}
printf("i = %d, j = %d\n",i,j);
/* ⑷ */
}
printf("i = %d, j = %d\n",i,j);
/* ⑸ */
}
46
복합대입 연산자
void main()
{
int a = 16;
a = a ^ 1;
printf("%d\n", a);
a ^= 1;
printf("%d\n", a);
}
47
조건 연산자
void main()
{
int a=5; int b=1;
int c;
c = a > b ? a : b;
printf("max is %d\n", c);
}
48
콤마 연산자
void main()
{
int i, j;
for(i=0 j=1, i < 10, i++ j+=2)
{
printf("i = %2d, j = %2d\n", i, j);
}
}
49
형변환
void main()
{
int sum = 10, n = 3;
int i, j;
float x;
printf("%d\n", (int)12.8);
printf("%f\n", (int)12.8 * 3.1);
printf("%d\n", (int)(12.8 * 3.1));
printf("%f\n", (float)sum/n);
i = j = 1;
x = i + j;
j = x - i / x;
}
50
sizeof 연산자
#include <stdio.h>
#include <conio.h>
main()
{
clrscr();
printf("\n char
printf("\n long
printf("\n int
printf("\n short
printf("\n unsigned
printf("\n float
printf("\n double
}
: %d byte", sizeof( char));
: %d byte", sizeof( long));
: %d byte", sizeof( int));
: %d byte", sizeof( short));
: %d byte", sizeof( unsigned));
: %d byte", sizeof( float));
: %d byte", sizeof( double));
51
오늘의 해결과제
1.
Char,int,short,long type을 sizeof 연산자를 사용하여
크기를 비교해 출력하는 프로그램을 작성하시오.
52
문자 입출력

Text stream : stream of character

c = getchar()

putchar()

File copying example
53
문자 입출력

getchar() != EOF
void main()
{
int c;

EOF?
c = getchar();
while(c != EOF) {
putchar(c);
c = getchar();
}
}
54
제어문(1)
#include <stdio.h>
main()
{
char c;
do {
c = getchar();
if (c >= 'a' && c <= 'z')
/* 읽은 문자가 소문자이면 */
putchar(c-32);
/* 대문자로 출력 */
else if (c >= 'A' && c <= 'Z' && c != 'Q') /* 대문자고 'Q'가 아니면 */
putchar(c+32);
/* 소문자로 출력 */
else
putchar(c);
/* 읽은 문자를 출력('Q'도 포함) */
} while (c != 'Q');
}
55
제어문(2)
main()
{
int i;
printf("Input a number(1 ~ 3): ");
scanf("%d",&i);
switch (i) {
/* 괄호 안의 수식이 정수 데이터 유형이 아닌 경우에는 */
/* 자동적으로 정수 데이터 유형으로 변환되게 된다 */
case 1: printf("ONE\n");
case 2: printf("TWO\n");
case 3: printf("THREE\n");
default: printf("Error\n");
}
}
56
제어문(3)
#include <stdio.h>
main()
{
int i;
for (i = 1; i <= 70; i++) /* 첫번째로 '*'를 70개 출력시킴 */
putchar('*');
putchar('\n');
printf(" OUTPUT BY HONG GIL DONG\n");
for (i = 1; i <= 70; i++) /* 두번째로 '*'를 70개 출력시킴 */
putchar('*');
putchar('\n');
printf(" INPUT DATA1\n");
57
for (i = 1; i <= 70; i++) /* 세번째로 '*'를 70개 출력시킴 */
putchar('*');
putchar('\n');
printf(" OUTPUT1\n");
for (i = 1; i <= 70; i++) /* 네번째로 '*'를 70개 출력시킴 */
putchar('*');
putchar('\n');
}
58
표준입력함수

int scanf( const char *format [,argument]... );
표준입력 스트림으로부터 format에 지정된 형식에 따라 데이터를
읽어들이는 함수.

int getchar( void );
표준입력 스트림으로부터 한 문자를 읽어들이고 그 값을 결과값
으로 리턴하는 표준 함수.

헤더 파일 : <stdio.h>
59
표준입력(1)
#include <stdio.h>
void main( void )
{
int i, result;
float fp;
char c, s[81];
wchar_t wc, ws[81];
printf( "\n\nEnter an int, a float, two chars and two strings\n");
result = scanf( "%d %f %c %C %s %S", &i, &fp, &c, &wc, s, ws );
printf( "\nThe number of fields input is %d\n", result );
printf( "The contents are: %d %f %c %C %s %S\n", i, fp, c, wc,
s, ws);
}
60
표준입력(2)
#include <stdio.h>
void main( void )
{
int i, ch;
for( i = 0; (ch = getchar()) != '\n'; i++ )
putchar(ch);
printf(“\n\n”);
ch = getchar();
printf(“ASCII code of character ’%d’ is %d”, ch, ch);
}
61
문자 입출력(1)
#include <stdio.h>
main()
{
char c;
long int nc = 0l;
/* 문자의 수를 기억 */
int nl = 0;
/* 라인의 수를 기억 */
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
/* 라인을 다 읽었으면 */
++nl;
/* 라인의 수를 증가 */
}
printf("%ld characters, %d lines\n",nc,nl);
}
62
문자 입출력(2)
#include <stdio.h>
main()
{
long int res = 0;
char c;
while ((c = getchar()) == '0' || c == '1')
res = res * 2l + c - '0';
/* 2진수인 동안 */
/* 읽은 수를 10진수로 변환 */
printf("Dec = %ld, Oct = %lo, Hex = %lx\n",res,res,res);
}
63
문자 입출력(3)
main()
{
char c1 = 'A';
char c2 = 'B';
char c3 = 'C';
printf("c1 = %c, %d\n",c1,c1);
printf("c2 = %c, %d\n",c2,c2);
printf("c3 = %c, %d\n",c3,c3);
}
64
문자 입출력(4)
main()
{
char c = 65;
char d = 'z';
unsigned char u = 179;
printf("c = %c, d = %d, u = %c\n",c,d,u);
printf("c + 10 = %c, d - 5 = %c, u + 1 = %c\n",c+10,d-5,u+1);
printf("%c %c %c %c %c %c\n",'a'+1,'z'-3,'0'+2,'9'-4,'F'+32,'q'-32);
}
65
문자 입출력(5)
main()
{
unsigned char c1, c2;
unsigned char c3, c4, c5;
printf("Input two characters: ");
scanf("%c%c%c",&c1,&c2,&c3);
printf("Input three characters: ");
scanf("%c%c%c",&c3,&c4,&c5);
printf("Result: %c%c%c%c%c\n",c3,c4,c5,c1,c2);
}
66
오늘의 해결과제
1.
점수를 읽어(이는 정수값으로 0~100점 사이를 가정) 값이
90이상이면 A를, 80~89면 B를, 70~79면 C를, 60~69면
D를, 그 이하이면 F를 출력시키는 프로그램을 작성하시오.
(힌트:우선 정수값 하나를 읽어들이므로 이를 위한 변수로
i를 사용하시오)
67
제어문 / 반복문

If-Else
expression이
참이면(non-zero n)
거짓이면(zero n)
statement1 실행
else에 속하는 statement2
실행
else는 옵션이므로 없을 수도 있다. 그리고 else는 그것과 만나는 가장
가까운 if 와 짝이 된다.
68
if~else문

if ( n > 0 )
if ( a < b )
z = a;
else
z = b;
 if ( n > 0 ) {
if ( a < b )
z = a;
}
else
z = b;
69
switch문
switch 문은 다중 선택을 위한 방법을 제공한다.
1.
2.
3.
우선 expression이 각 case 의 const-expr(integer 혹은
char)와 같은지 check.
해당하는 statement들을 분기명령(예. break 등)이 없으
면 나머지 모든 statements 들을 실행.
만일 expression 이 제시된 모든 case 와 일치하지 않으
면 default 이하의 statement 만을 실행.
switch ( expression ) {
case const-expr : statements; break;
case const-expr : statements; break;
.....
default
: statements
}
70
braek & continue
Break & Continue
1.
Break : loop와 switch 문에서 사용
break를 포함하는 loop나 switch문의 나머지 부분을 무시하고 다음
statement를 수행하게 한다.
2.
Continue : loop문에서 사용
Program의 흐름이 loop 내의 나머지 부분을 무시하도록 하며, 다
음 차례의 순환을 하도록 한다.
71
Loop 문

Loop statement

Program 내에서 임의의 조건을 만족시킬 때까지 일정한 code들을
계속적으로 반복하여 수행하는 부분을 loop 라 한다.

while

expression이 false 이거나 혹은 zero가 될 때까지 statement를 계
속적으로 반복 실행한다.

while은 loop를 순환하기 전에 순환 여부를 먼저 check 하게 된다.
따라서 statement 부분을 전혀 실행시키지 않고서 loop를 빠져나갈
수도 있다.
72
while
while ( expression )
{ statements; }
73
for
expression1 은 조건을 초기화 시켜 주는 것으로서 가장 먼저 expr1
이 수행되
고, expr2 가 참( or Non-zero )이면 statements가 실행되고,
마지막으로 expr3이 실행된다.
그리고 다시 loop 순환 조건인 expr2를 check 하게 된다.
For 문 또한 while 과 마찬가지로 statement 실행 이전에 조건을 검
사한다
for
while
for ( expr1; expr2; expr3 )
{
statements;
}
expr1
while ( expr2 )
{
statements;
expr3;
}
74
for
for
75
do~while

Do-While
do
{
statements
}
while ( expression );
expression 이 거짓이거나 혹은 zero 가 될 때까지 반복 실행하게
되며 loop 순환조건인 expression 은 적어도 statement 가 1 회 실
행되고 나서 조건을 검사하게 된다.
76
Goto & Label

Goto & Label
Goto 문은 Program 의 흐름이 지시된 label 을 갖고 있는 곳으로
jump 시킨다.
 Label 과 그 statement 의 구별은 colon (:)으로 하며 label 은 goto
문의 앞뒤 어디에 있어도 상관이 없다.
 또한 label 의 명칭은 변수명의 규칙에 따른다.


논리적인 programming 을 위하여 이러한 무조건적인 jump 를 하게
되는 goto 문의 사용은 가급적 하지 않는 것이 좋다.
하지만, 예외적으로 다음과 같이 둘 이상의 loop 안에서 한번에 빠
져 나오는 경우에 사용되기도 한다.
77
조건문
void main()
{
int age;
printf("당신의 나이를 입력하세요 : ");
scanf(&age);
if(age >= 60) printf("60대");
else if(age >= 50) printf("50대");
else if(age >= 40) printf("40대");
else if(age >= 30) printf("30대");
else if(age >= 20) printf("20대");
else if(age >= 10) printf("10대");
else if(age >= 0) printf("유소년");
else printf("해당사항 없읍니다");
printf("\n");
}
78
Switch 문
main()
{
const a = 1.1,b = 2.2, c=3.3;
switch(a)
{
case 1.1:puts(“1”);
break;
case 2.2:puts(“2”);
break;
default: puts(“Hola!”);
break;
}
}
79
Switch 문
void main()
{
int age;
printf("당신의 나이를 입력하세요 : ");
scanf("%d", age);
switch(age)
{
case 6:
printf("60대");
break;
80
case 5:
printf("50대");
break;
case 4:
printf("40대");
break;
case 3:
printf("30대");
break;
case 2:
printf("20대");
break;
case 1:
printf("10대");
break;
case 0:
printf("유소년");
break;
81
default:
printf("해당사항 없읍니다");
break;
}
printf("\n");
}
82
For 문
void main()
{
int level;
int age;
printf("당신의 나이를 입력하세요 : ");
scanf("%d", &age);
for(level = 0;age >= 10; ++level)
{
age = age - 10;
}
printf("%d0대\n", level);
}
83
오늘의 해결과제
1. 1에서 100까지 출력하는 프로그램을 만드시오.
2. 1부터 100까지의 합을 구하는 프로그램을 for문을
사용하여 작성하시오.
3. 2, 4, 6, … 100 까지 출력하는 프로그램을 만드시오
84
While 문
void main()
{
int level;
int age;
printf("당신의 나이를 입력하세요 : ");
scanf("%d", &age);
level = 0;
while(age >= 0)
{
age = age - 10;
level = level + 1;
}
printf("%d0대\n", level);
}
85
오늘의 해결과제
1. 구구단 표를 출력하는 프로그램을 만드시오
2. if~else if문을 사용해서 입력받은 학생들 10명의 성
적을 학점으로 변경시키는 프로그램을 작성하시오.
(예: 3.4점  B학점)
86
Do-while 문
void main()
{
int level;
int age;
printf("당신의 나이를 입력하세요 : ");
scanf("%d", &age);
level = 0;
do
{
age = age - 10;
level = level + 1;
}
while(age >= 0);
printf("%d0대\n", level);
}
87
Break, continue
#include <ctype.h>
void main()
{
char* s = "2002 World Cup Korea";
int i, cnt;
printf("%s\n", s);
for(i=0, cnt=0; i < sizeof(s); ++i)
{
if(isdigit(s[i]))
cnt++;
else
break;
}
printf("숫자의 길이는 %d 입니다.", cnt);
}
88
#include <conio.h>
void main()
{
char c;
while(1)
{
c = getch();
if(c != 'q')
{
continue;
putch(c);
}
break;
}
}
89
Goto, label
void main()
{
int i=0;
printf("line 1\n");
line2:
printf("line 2\n");
printf("line 3\n");
if(i < 3)
goto line2;
}
90
오늘의 해결과제
1.
학생 10명의 성적을 입력받아서 합계와 평균
을 구하는 프로그램을 작성하시오.
2.
N개의 숫자를 읽어 들여 이들 중 최대값과
최소값, 그리고 합과 평균을 계산하여 출력하
는 프로그램을 작성하시오.
91
오늘의 해결과제(필수)
1.
For문을 사용하여 화면에 아래와 같이 다이아몬드를 출력하는
프로그램을 작성하시오.
*
***
*****
*******
*********
***********
*************
***********
*********
*******
*****
***
*
92
•
배열의 이해
int ar[l][m][n];
여기서 눈여겨 볼 것은 배열의 첫번째 요소는 배열의 포인터가 된다는
것이다.이 배열의 포인터는 ar이 된다.또 ar[l]은 ar[l][m][n]의 포인터
가 되고 ar[l][m]은 배열 ar[l][m][n]의 포인터가 된다.
포인터를 이용해서 배열을 여러 가지로 참조 할 수 있다.
int ar[l][m][n];
ar[l][m][n] = *(ar[l][m]+n) = *(*(ar[l]+m)+n)
<
매개 변수가 배열인 함수 >
배열을 함수와 매개 변수로 받을 때는 배열 포인터를 써야 한다.
함수의 원형에는 "변수형 매개변수이름[]" 또는 "변수형 *매개변수이름"
과 같이 써야 한다.
93
배열 #1
void main()
{
int a[10];
int i;
for(i=0; i<10; i++)
a[i] = i*2;
printf("2's multiple\n");
for(i=0; i<10; i++)
printf("%d ", a[i]);
printf("\n");
}
94
배열 #2
void main()
{
int a[10][10];
int i, j, k=2;
for(j=1; j<=10; j++)
{
for(i=1; i<=10; i++)
{
a[j][i] = i*k;
k = k + 1;
}
}
95
printf("Table of multiples.\n");
for(j=0; j<10; j++)
{
for(i=0; i<10; i++)
{
printf("%2d ", a[i][j]);
}
printf("\n");
}
}
96
배열 #3
void main()
{
int a[2][10][10];
int i, j, k;
for(i=1; j<=2; k++)
for(j=0; j<10; j++)
for(k=0; k<10; k++)
a[i-1][j][k] = (i*100)+(j*10)+k;
97
printf("Table of multiples.\n");
for(i=0; i<2; i++)
{
for(j=0; j<10; i++)
{
for(k=0; k<10; k++)
{
printf("%3d ", a[k][j][i]);
}
printf(“\n”);
}
printf("\n");
}
}
98
배열 #4
void main(void)
{
int i, data[] = { 78, 55, 99, 75, 84, 39, 67, 98, 87, 100 };
long int sum = 0;
float ave;
for (i = 0; i < 10; i++)
sum += data[i];
ave = (float)sum / 10;
printf("TOTAL = %ld AVERAGE = %.2f\n",sum,ave);
}
99
배열 #5
main()
{
int ia[10] = { 0, };
/* 초기값이 모두 0 */
int i;
printf("*** Input numbers between 0 and 99 ***\n");
scanf("%d",&i);
while (i >= 0 && i <= 99)
{
++ia[i / 10];
scanf("%d",&i);
}
printf("FREQUENCIES\n");
for (i = 0; i < 10; i++)
printf("%2d ~ %2d : %10d\n",i*10,(i+1)*10-1,ia[i]);
}
100
오늘의 해결과제
1.
소수를 구하는 프로그램을 배열이나 포인터를 이용
하지 말고 작성하시오.
2.
소수를 구하는 프로그램을 배열을 이용하여 만드시
오
2 3 5 7 11 13 17 19 23 29 31 37 41 43
47 53 59 61 67 71 73 79 83 89 97 101 103
107 109 113 127 131 137 139 149 151 157 163 167
173 179 181 191 193 197 199
101
포인터의 이해
int *pnt;
pnt : 다른 int형 변수의 번지수를 저장한다.
*pnt : pnt가 가지고 있는 번지수가 가르키는 내용을
말한다.
int i;
i : 메모리 상에 정수 값을 저장할 장소를 만든다.
&i : i가 만들어진 메모리 상이 번지를 말한다.
포인트 변수의 형 선언
포인트 변수는 형에 관계하지 않고 2byte만 차지한
다.그럼 무었 때문에 형 선언을 하느가? 바로 변수형
에 따라 메모리 참조를 할 때 그에 맞는 증가나 감소
를 하기 위함이다
102
포인터 연산
포인터 변수와 포인터 변수 끼리의 뺄셈은 가능하나 덧셈은
허용되지 않는다.
포인터와 단항 연산자를 혼합해서 사용 할 경우 주의사항!
1.
2.
3.
4.
++*pt : *pt에 1을 더함
*++ptr : 번지수를 하나 증가한 다음 내용을 취함
++*pt : 번지수가 가르키는 내용 증가
*ptr++ : 가르키는 번지의 내용을 후휘 연산 기법으로 증가
103
포인터 배열
문자열을 변수에 저장 할 때 메모리를 절약하기 위해 사용한다.
char *name[]={"ju fal ge","son o gong","sam jang bub sa"};
이 것을 배열로 선언 한다면
char name[][16]={"ju fal ge","son o gong","sam jang bub
sa"};
으로 48byte가 들지만 포인터 배열로 선언하면 37byte 밖에
들지 않는다.포인터 배열은 초기값이 들어 갈만큼 메모리가
잡히기 때문이다
104
이중 포인터
포인터의 포인터를 말한다.
int **a,*b,c; 라고 선언 했다면...
정수형 : c,*b,**a
정수형 포인터 : &c,b,*a
정수형 이중 포인터 : *b,a
105
main() 함수의 인자
원형
int main(int argc,char *argv[],char *env[]);
int argc
명령 라인에서 쓰인 인자의 갯수+1갖는다.
char *argv[]
명령 라인에서 입력한 인자들이 존재하는 메모리의
번지수를 기억한다.
argv[0] : 패스명과 실행 파일 이름
argv[1] 부터는 인자의 내용이 순서대로 들어가 있
다.
char *env[]
환경 변수이다.각자 실행을 해보길...
106
Void형과 NULL 포인터
void *ptr;
형을 무시하고 일을 처리 해야 할 때 사용한다.
어떠한 포인터도 void형 포인터에 대입 될수 있으나
void형 포인터느 캐스트 연산자와 함께 다른 포인터
변수에 대입되야 한다.
NULL 포인터란 초기값이 0인 포인터 즉 0x0000을
가르키는 포인터다.
107
함수 포인터
함수 포인터는 하의 함수를 가르키며 실행까지도 할 수 있다.
함수되돌리는값 (*포인터이름)(가르킬함수의매개변수리스트);
함수가되돌리는값 : 리터형
포인터이름 : 일반 변수명 쓰듯 정한다.
가르킬매개변수리스트 : 함수 포인터가 가르키는 함수의 매개
변수 리스트이다.
int (*fptr)(int i);
fptr = func; /*()를 하지 않는다*/
int func(int q)
{...}
함수 이름 중 ()와 그 안에 들어 있는 부분을 제외한 함수의 이름
은 함수 포인터 상수가 된다.
108
알고 넘어가기(1)
main()
{
int i;
/* int형 변수의 내용은 필요로한 int값을 저장할 수 있고 */
int *iptr; /* int형 포인터 변수의 내용은 int형 변수의 번지수를 저장
할 수 있다 */
i = 256;
/* 256 == 0x100 */
iptr = &i;
printf("%d\n",*iptr); /* *iptr은 iptr이 가리키고 있는 메모리의 내용 */
}
109
알고 넘어가기(2)
< 포인터를 이용한 참조에 의한 호출 >
C에서는 모든 것을 값에 의한 호출 형태로 인자를 전달하고 있다.
값만 넘어가기 때문에 받은 쪽에서는 부른 쪽의 데이터를 변경할 수
없게 된다.
반면에 참조에 의한 호출의 경우에는 변수 자체가 넘어가기 때문에
받은 쪽에서 부른 쪽의 데이터를 변경할 수 있게 되는데 C에서는
참조에 의한 호출을 전혀 지원하지 않기 때문에 이를 기본적으로는
할 수 없지만 포인터를 사용하면 이와 같은 효과를 낼 수 있다.
즉, 실인자에 값을 주는 것이 아니라 변수가 할당되어 있는 번지를
건내주므로써 간접적인 참조에 의한 호출을 행한다.
다음이 그 프로그램이다.
110
< 포인터를 이용한 참조에 의한 호출 예
제>
main() {
void swap(int *, int *);
int i = 10, j = 20;
printf("i = %d, j = %d\n",i,j);
swap(&i,&j);
/* & 연산자를 사용하여 주소를 넘겨주고 있다 */
printf("i = %d, j = %d\n",i,j);
}
void swap(int *ip, int *jp) {
/* 받는 쪽은 주소를 받아야 하므로 포인
터가 된다 */
int t;
t = *ip;
*ip = *jp;
*jp = t;
}
결과 i = 10, j = 20i = 20, j = 10
111
< 포인터 연산에 관한 프로그램>
main() {
int i = 10, *ip = &i;
int j, k;
char c = 'D', *cp = &c;
double *jp = (double *) 2000;
*ip++ = ++i;
++*--ip;
++*cp++;
*--cp = c + 3;
jp += 5;
j = jp - (double *) 80;
k = (int)(jp - 80);
printf("i = %d, j = %d, k = %d, c = %c\n",i,j,k,c);
}
결과i = 12, j = 245, k = 1400, c = H
112
< 포인터 연산에 관한 프로그램 설명>
우선 *ip++ = ++i의 경우 i의 값을 1 증가시키고(i = 11이 된다)
이를 *ip에 할당하고(*ip는 i이므로 i = 11) ip가 sizeof(int) 만큼 증가된다.
그 다음 ++*--ip;에서 --ip를 먼저 계산하므로 ip는 도로 원래의 값이 되며
따라서 *ip는 i가 되고 이를 1 증가하므로 i = 12가 된다. ++*cp++는 *cp와
cp가 1 증가하므로(sizeof(char)는 1이다) c는 'E'가 되고 cp는 1증가한다.
그 다음 *--cp = c + 3에서 c + 3은 'E' + 3이 되며 *--cp에서 --cp로 다시 cp가
c의 주소를 가지므로 *--cp는 c가 된다. 따라서 c는 'E' + 3 = 'H'를 갖게 된다.
그리고 jp += 5에서 jp가 2000을 값으로 가지므로 jp = 2000 + sizeof(double)
* 5가 되어 2040이 되며, 그 다음 j = jp - (double *) 80에서 80이 주소로 형 변
환
되었으므로 포인터 사이의 뺄셈이 되어 (2040 - 80) / sizeof(double)이 되므
로
j는 245가 된다. 마지막으로 k = (int)(jp - 80)의 경우 jp - 80에서 80이 주소가
아닌 정수이므로 jp - 80 * sizeof(double)이 되어 2040 - 80 * 8 = 1400이 되므113
로
포인터 #1
void main()
{
int a;
int *p;
a = 100;
p = &a;
printf("a = %d\naddress of a = %p\n", a, p);
}
114
포인터 #2
#include <stdio.h>
void main()
{
int i, a[10];
int *p;
p = a;
115
for(i = 0; i < 10; i++ )
{
printf("a[%d] = %d\n", i, *p);
p += 4;
}
}
116
포인터 #3
void main()
{
int i, *p, *q;
i = 382;
p = &i;
*q = *p;
printf("i = %d, p = %d, q = %d\n", i, *p, *q);
*p = 192;
printf("i = %d, p = %d, q = %d\n", i, *p, *q);
}
117
포인터 #4-(1)
main()
{
char c = 'a';
int* pi = &c;
void* pv = &c;
char* pc1 = pi;
char* pc2 = pv;
printf("%c\n", *pc1);
printf("%c\n", *pc2);
}
118
포인터 #4-(2)
main()
{
int i;
int a[5], *ip;
for(i=0; i<5; i++) a[i] = i;
ip = a;
printf("%d\n", *(ip+3*sizeof(int)));
}
119
포인터 #4-(3)
main()
{
char* p = NULL;
/*char *p = "abc";*/
if(p) printf("Pointer is not null\n");
if(!p) printf("Pointer is null\n");
if(p ? 0 : 1) printf("Pointer is null\n");
}
120
포인터 #4-(4)
main()
{
char c = '.';
char* p, *q;
printf("%c %c %c\n", c, *p, **q);
}
121
포인터 #5
#include <stdio.h>
void main()
{
char str[40] = "2002 World Cup Korea";
char a, b, *c, *pt;
int i;
char buf[100];
a = str[0];
b = *str;
printf("The 1st output is %c %c\n", a, b);
122
a = str[9];
b = *str+9;
printf("The 2nd output is %c %c\n", a, b);
c = str+12;
printf("The 3rd output is %c %c\n", str[12], *c);
for (i = 0 ; i < 100 ; i++)
buf[i] = i + 100;
buf[i] = 0;
pt = buf + 20;
printf("The 4th output is %d %d\n", buf[20], *pt);
}
123
포인터 #6
#include <stdio.h>
void fix(int x, int *y)
{
printf("%d %d\n", x, *y);
++x;
++*y;
printf("%d %d\n" ,x, *y);
}
int main()
{
124
int a, b;
a = 0;
b = 1;
printf("%d %d\n", a, b);
fix(a, &b);
printf("%d %d\n", a, b);
return 0;
}
125
포인터 #7
#include <stdio.h>
void
void
void
void
(*func_ptr)(double);
print1(double data_to_ignore);
print2(double arg);
print3(double arg);
void print1(double data_to_ignore)
{
printf("Data ignored\n");
}
126
void print2(double arg)
{
printf("print2(%f)\n", arg);
print3(arg);
}
void print3(double arg)
{
printf("print3(%f)\n", arg);
}
int main()
{
double pi = 3.14159;
double pi2 = 2.0 * pi;
127
print1(pi);
func_ptr = print1;
func_ptr(pi);
func_ptr = print2;
func_ptr(pi2);
func_ptr(13.0);
func_ptr = print3;
func_ptr(pi);
print3(pi);
return 0;
}
128
배열과 포인터#8
main()
{
int ia[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ip, i;
ip = ia+9;
/* 배열의 이름은 그 배열의 맨 처음 변수의 주소와 같다 */
for (i = 0; i < 10; i++)
/* 즉 ia+9는 &ia[9]와 같다 */
printf(" ia[%d] = %2d\n",9-i,*(ip-i));
}
ia[9] = 10
ia[8] = 9
ia[7] = 8
ia[6] = 7
ia[5] = 6
ia[4] = 5
ia[3] = 4
ia[2] = 3
ia[1] = 2
ia[0] = 1
129
배열과 포인터#9
main()
{
int i, j;
char ch[2][2] = { '1', '2', '3', '4' };
char* p[2] = { ch+0, ch+1 };
*(ch) = 'c';
*(ch+1) = 'd';
for(i=0; i<2; i++)
for(j=0; j<2; j++)
printf("%c ", *(ch+i)[j]);
}
130
배열과 포인터#10
int array[5][4] = { 1, 1, 1, 1, 1 };
main()
{
int i, j;
int (*ap)[4];
// int **ap;
//memset(array, 0, sizeof(array));
ap = array;
for(i=0; i<5; i++)
{
*(ap[i]+i) = i+1;
}
for(j=0; j<4; j++) {
for(i=0; i<5; i++)
printf("%d ", array[j][i]);
putchar('\n');
}
}
131
배열과 포인터#11
main()
{
int *pa, a[10];
pa = &a;
memset(a, 0, sizeof(pa));
a:
a(&a[0], 10);
goto a;
}
int a(int a[])
{
int i;
static int j = 0;
for(i=0; i<b; i++) {
a[i] = j++;
printf("a[%d] = %d\n", i, a[i]);
}
return 0;
}
132
배열과 포인터 #11
void main()
{
static int ar[2][3] = { 1, 2, 3, 4, 5, 6 };
int i, j;
for (i = 0; i < 2; i++)
for (j = 0; j < 3; j++)
printf("Address of ar[%d][%d] = %u\n",i,j,&ar[i][j]);
printf("ar = %u, *ar = %u, **ar = %u\n",ar,*ar,**ar);
printf("ar+1 = %u, *(ar+1) = %u, **(ar+1) = %u\n",ar+1,*(ar+1),**(ar+1));
printf("ar[0] = %u, *ar[0] = %u\n",ar[0],*ar[0]);
printf("ar[0]+1 = %u, *(ar[0]+1) = %u\n",ar[0]+1,*(ar[0]+1));
printf("ar[1] = %u, *ar[1] = %u\n",ar[1],*ar[1]);
printf("ar[1]+1 = %u, *(ar[1]+1) = %u\n",ar[1]+1,*(ar[1]+1));
}
133
이중 포인터
void main(void)
{
int **dptr, *ptr, i;
i = 10;
ptr = &i;
dptr = &ptr;
printf(" i = %4d, *ptr = %4d, **dptr = %4d\n",i,*ptr,**dptr);
printf(" &i = %4p, ptr = %4p, *dptr = %4p\n",&i,ptr,*dptr);
printf("&ptr = %4p, dptr = %4p, &dptr = %4p\n",&ptr,dptr,&dptr);
}
134
오늘의 해결과제(1)
1.
20크기의 문자 배열을 정의하고 여기에 문자열 “Welcome to
Bitcamp를 넣으시오. 그리고 나서 포인터를 사용하여 이 문자열을
출력하시오.
Welcome to choongang
2.
문자열 S안에서 찾고자 하는 문자 스트링 t의 위치를 나타내는 함수
를 작성하시오. 이때, 찾고자 하는 문자열 t가 없을 때에는 –1를
리턴한다.
Char* strfind(char*, char*t);
3.
입력한 데이터를 단어 단위로 알파벳 순으로 정렬하는 프로그램을
작성하시오. 단, 각 단어의 길이는 30자 이내로 가정하며, 단어의
구분은 ‘ ‘ 나 \t’, ‘\n’으로 하고 알파벳 이외의 다른 글자들은
ASCII 코드 순으로 정렬하시오.
135
오늘의 해결과제(2)
1.
포인터 배열을 이용하여 사람 이름을 정렬하는 프로그램을
작성하시오
2.
몇 년도의 몇 번째 일을 입력으로 받아서 그 해의 월, 일로 출력
하는 프로그램을 작성하시오.(예:1995 303입력 -> October 30 )
136
함수 (메모리)
간단한 Computer 구조
Data Bus
Monito
r
CPU
RO
M
RAM
I/O
Keyb.
Mouse
...
Addr. Bus
137
함수 (메모리)
1-Register CPU 구조
data
processor
MR LR AC
AC : Accumulator
A
L
U
LR : LINK Register
command
processor
Decorde
r 제어장치
IR
PC
MR : Multiplicator Register
ALU : Arithmatic Logic Unit
MB
R
MAR
MBR : Memory Buffer Register
m
e
m
o
r
y
MAR : Memory Address Register
IR : Instruction Register
PC : Program Counter
138
함수(구성방법)

C 프로그램의 일반적인 구성 양식
/* 프로그램명, 화일명, 날짜, version 등 */
#include < .....>
다. */
#include " ..... "
*/
/* 표준 헤더를 포함시킨
/* 사용자 정의 헤더를 포함시킨다.
#define .....
/* 매크로 상수나 매크로 함수를 정
의*/
int function1( ..... );
/* 사용자함수를 선언한다. */
extern int n1, n2;
/* 외부 변수를 선언한다. */
/* 윗부분을 별도의 헤더 파일로 작성하고,
139
함수(구성방법)
#include " ..... " 문으로 포함시키는 것이 좋다. */
int n1, n2;
/* 외부 변수를 정의한다. */
void main()
{
...
}
/* main 함수를 정의한다. */
int function1( ..... )
{
...
}
/* 사용자함수를 정의한다. */
140
함수 기본 구조
되돌림자료형 함수이름 (매개변수리스트)
{ 변수 선언 및 초기화부
구문
}
되돌림 자료형이 없을 경우 void를 쓰며 매개 변수가 없을 경우
()로 나타낸다.
141
함수의 원형
* 되돌림형 함수이름 (자료형 변수명,자료형 변수명,....);
* 컴파일러에게 그 함수의 매개 변수형과 되돌림값의 형을
알려준다.
* 변수명은 생략 할수 있다.
* 프로그램 앞부분에 나열해 두거나 헤더 파일에 나열한
다.
* 원형은 마지막에 세미콜론을 찍는다는 것을 주의하자!
142
Return 문
* return문은 값을 되돌리며 return 이후에 나오는 문장은
무시하고 함수를 빠져나온다.
* return문에 의해 되돌려지는 값은 함수의 되돌림형과 일
치하여야 한다.일치하지 않으면 C의 형변환 규칙에 의해
변환된다.
ex) return; return(i > 0 ? 6 : 8); 등등
143
값에 의한 호출과 참조에 의한 호출
* 값에 의한 호출(call by value)
C는 기본적으로 값에 의한 호출을 한다.값에 의한 호출
이란 변수의 값을 복사해서 넘겨주는 것을 말한다.값을
넘겨주는 변수에는 아무런 영향을 주지 못한다.
* 참조에 의한 호출(call by value reference)
C는 포인터를 이용해서 변수의 값에 직접 영향을 미칠수
있다.이것은 배열과 포인터에서 더 자세히 다루기로 한
다.
144
블럭에서 변수 사용
* auto
자동 변수로 블록 내에서 생성 자동으로 블록이 끝나면
소멸,컴파일중 만들어지는 것이 아니라 프로그램 실행
중에 임시로 만들어 졌다,사라진다.기본적으로 변수는 자
동 변수이므로 생략 가능하다.
* extern
외부변수 또는 외부함수로 나타냄.다른 파일에 변수나
함수가 존재하는 것을 알려주기 위한 것으로 실제로 메
모리에 변수를 만드는 것이 아니라 다른 파일에서 만들
어진 변수를 사용만한다.
145
* register
레지스터에 변수를 만들어 빠른 속도로 실행한다.int나 unsigned
형만이 가능한 16bit 변수다.
선언한다고 해서 모두 만들어 지는 것은 아니고 컴파일러에게 요구
하는 것이다.선언하지 않아도 컴파일러가 만들기도 한다.
* static
변수나 함수를 정적으로 선언한다.블럭이 시작되기도 전에에 메모
리에 생성 되었다가 끝나도 계속 유지하며 생성된 블록에서만 사용
이 가능하다.
* 전역 변수,지역 변수
전역변수는 블록 밖에서 선언된 변수로 모든 블럭에서 사용이 가능
하고 지역 변수는 블럭 내에서 생성되 블럭 내에서만 사용 가능하
다.지역 변수가 전역 변수보다 우선하다.
146
함수 들어가지 전(1)
#include
main() {
int i;
for (i = 1; i <= 70; i++)
/* 첫번째로 '*'를 70개 출력시킴 */
putchar('*');
putchar('\n');
printf(" OUTPUT BY HONG GIL DONG\n");
for (i = 1; i <= 70; i++)
/* 두번째로 '*'를 70개 출력시킴 */
putchar('*');
putchar('\n');
printf(" INPUT DATA1\n");
for (i = 1; i <= 70; i++)
/* 세번째로 '*'를 70개 출력시킴 */
putchar('*');
putchar('\n');
printf(" OUTPUT1\n");
for (i = 1; i <= 70; i++) /* 네번째로 '*'를 70개 출력시킴 */
putchar('*');
putchar('\n'); }
147
위의 프로그램을 보면 다음 문장이 4번 반복되는 것을 알 수 있다.
for (i = 1; i <= 70; i++)
putchar('*');
putchar('\n');
따라서 이를 한번만 입력하고 필요할 때마다 불러 쓰면 편한데... 그래서
사용하게 된 것이 바로 함수이다.
위의 경우 함수를 사용하게 되면 다음과 같이 된다.
#include
print_star() {
int i;
for (i = 1; i <= 70; i++) '*'를 70개 출력시키는 함수
putchar('*');
putchar('\n'); }
148
함수 들어가지 전(2)
main() {
print_star();
printf(" OUTPUT BY HONG GIL DONG\n");
print_star();
printf(" INPUT DATA1\n");
print_star();
printf(" OUTPUT1\n");
print_star();
}
149
위의 프로그램을 앞의 프로그램과 비교해 보면 훨씬 정리된
느낌을 줄 것이다.
또 print_star란 것이 '*'를 한 줄 출력시키는 것이라는 것을 안다면
위의 프로그램이 앞의 프로그램 보다 훨씬 더 이해하기 쉽다.
그리고 위의 print_star는 필요할 때마다 사용할 수 있고 다른 사람의
다른 프로그램에서도 사용할 수 있다는 장점을 갖게 되는데 이것이
함수를 사용하는 가장 큰 이유라고 할 수 있다.
그러나 함수를 많이 사용하면 수행시간이 많이 걸리기 때문에 속도는
떨어지게 된다.
따라서 속도에 민감한 프로그램을 작성하고자 할 때에는 함수의 사용에
신중을 기해야 한다.
150
인자의 전달
인자의 전달이란 실인자의 값이 형식 인자의 값으로
어떻게 전달되는가 하는 것을 의미한다.
void swap(int x, int y) {
int t;
t = x;
x = y; y = t;
}
main() {
int x = 10;
int y = 20;
swap(x, y);
printf("x = %d, y = %d\n",x,y); }
151
위의 swap 함수는 x와 y의 값을 서로 바꾸고 있다. 그러면 main 함수에
서swap(x, y)를 호출하였으니 x와 y의 값이 바뀌어야 할 텐데 위 프로
그램을 실제로 수행해 보면 x = 10, y = 20으로 전혀 바뀌지 않았음을
알 수 있는데 이유는 바로 C의 인자 전달 방법 때문이다. C에서는 값에
의한 호출(call by value) 방법으로 인자를 전달하고 있으며 철저하게
값만 인자로 전달된다. 이 얘기는 main에서 swap(x, y);로 x와 y를 실인
자로 제공하고 있지만 swap(x, y)의 x, y에 전달되는 것은 main의 x, y
의 값, 즉 10, 20이 전달된다. 따라서 위의 swap 호출은 swap(10, 20);
과 똑같은 의미를 갖게 된다. 그러므로 당연히 swap에서 아무리 x, y의
값을 바꾸어 보았자 main의 x, y의 값은 바뀌지 않는 것이다(swap의 x,
y와 main의 x, y는 이름만 같지 전혀 다른 변수이다). 값에 의한 호출이
란 실인자를 전달할 때 항상 그 값만을 전달해 준다는 뜻으로 매개변
수가 전달되는 과정을 보다 깊숙이 살펴보면 어떤 함수가 호출되기
전에 매개변수의 값들은 stack이라는 컴퓨터 내부 기억장소에 저장된
후 호출된 함수에서는 다시 그 값을 꺼내 사용하는 방식을 취하고 있
다. IBM-PC에서는 내부 스택이 정해져있어 주로 함수의 호출 및 매
개변수 전달에 쓰이고 있다. 이러한 스택은 이른바 LIFO(Last In
First Out)의 구조를 가지고 있어 가장 최근에 저장된 값이 바로 꺼내
질 수 있도록 되어 있다
152
함수 #1
#include <stdio.h>
#define PI 3.14159
void main()
{
float r;
printf("Enter radius : ");
scanf("%f", &r);
printf("Area of a circl with radius %f is %.2f\n", r, circle_are
a(r));
printf("Surface of a ball with radius %f is %.2f\n", r, ball_sur
face(r));
153
printf("Volume of a ball with radius %f is %.2f\n", r,
ball_volume(r));
}
float circle_area(float r)
{
return PI*r*r;
}
float ball_surface(float r)
{
return 4.0f*r*r*PI;
}
float ball_volume(float r)
{
return 4*PI*r*r*r/3;
}
154
함수 #2
#include <stdio.h>
#include <conio.h>
long forth(long val)
{
long ret;
ret = first(val+1);
printf("%d ", ret);
return ret;
}
long third(long fire)
{
return forth(fire);
}
155
long third(long a, int b)
{
return 0;
}
char second(int var)
{
return third(var);
}
int first(int i)
{
return second(i);
}
void main()
{
first(1);
}
156
함수 #3
long factorial(int n)
{
/* long형을 되돌리는 함수 */
int i;
long product = 1l;
for (i = 2; i <= n; i++)
product *= i;
return product;
}
main()
{
int num;
long fact;
for (num = 1; num <= 10; num++) {
fact = factorial(num);
/* factorial 함수 호출뒤 fact에 대입 */
printf("%2d! = %8ld\n",num,fact);
}
}
157
Static 변수
void test()
{
static int s_count; /* static 메모리 유형은 초기화시키지 않았을 경우 */
int a_count = 0;
/* 0의 값을 가진다 */
s_count++;
a_count++;
printf("static count = %2d\tauto count = %d\n",s_count,a_count);
}
main()
{
int i;
for (i = 0; i < 10; i++)
test();
}
158
함수(재귀호출)
Recursion
재귀 ( recursion )라는 것은 함수가 직접 또는 간접적으로 자기
자신을 다시 호출하는 것을 말한다.
재귀 호출(recursive call)은 메모리를 많이 소모하게 되며, 처리
속도 또한 상대적으로 느리다.
작성하고자 하는 프로그램이 대단히 간결해지며, 그 프로그램을
이해하는 것도 쉬워진다.
Quick sort, Tower of Hanoi, Fractal curve 등의 알고리즘
재귀 호출 작성방법 :
1.
종료조건을 명시
2.
자신을 호출할 것
159
함수(재귀호출)
void main()
{
printf(“%g\n”, fibonacci(4)); fibonacci(4
)
}
fibonacci(3
)
fibonacci(2
)
fibonacci(1
)
fibonacci(1
)
fibonacci(2
)
fibonacci(1
)
fibonacci(0
)
fibonacci(0
)
160
재귀호출
#include <stdio.h>
void print_back()
{
int ch;
if ((ch = getchar()) != '\n') /* 한글자를 입력받고 줄바꿈 문자인지 확인 */
print_back();
/* 줄바꿈 문자가 아닌경우 되부름 */
putchar(ch);
/* 입력받은 문자 표시 */
}
main()
{
printf("Enter a line -> ");
print_back();
}
161
오늘의 해결과제(1)

연속된 숫자의 합을 구하는 함수를 만들고 이를 이용하여 합을
구하라.
- Sum from 1 to 10 is 55

배열내의 원소들의 합을 구하는 함수를 만들고 이를 이용하여
배열 안에 들어있는 값들의 합을 구하시오.
{ 1, 2, 3, 4, 10, 6, 7, 8, 9, 10 }
Sum of array is 60

Swap 함수를 작성해서 a 와 b의 값을 바꾸는 프로그램을 작성
하시오.

하나의 문장을 입력받아 거꾸로 출력해주는 reverse란 이름의
함수를 작성하고 이 함수를 사용해서 프로그램을 완성하시오.
162
#define
* 목적
전처리기 부분만 바꾸며 소스 전체를 바꾸는 효과가
있다.
* #define [대표문자] [바뀌는문자]
기억하기 힘든 수치나 데이타를 알아 보기 쉽게 하기
위해서도 사용한다.
* #undef [define 되었던 대표 문자]
define를 해제한다.
163
매크로 함수
#define SQ(x) ((x)*(x))
SQ는 매크로 함수명이고 (x)는 형식 매개 변수이며 괄호로 묶인
다는 것에 주의하자!
#Include
#include <파일이름>
#include "파일이름"
<>는 include 디렉토리에서 파일을 찾고 ""는 현재 디렉토리에
서 파일을 찾는다.
"" 안에 풀패스를 적을 때 '\\' 두개를 적어서는 안되고 '\'하
나만 적어야한다.
164
기타 전처리기
• #error 에러메세지
#error문을 만나면 즉시 컴파일을 중단하고
"Error:파일이름.c 라인번호 : Error directive : 에
러 메세지"라고 출력한다.
#line문과 널 지시자
#line 라인넘버 "파일이름"
#line 라인넘버
165
Typedef문
typedef [자료형] [대표하는 문자열];
ex) typedef unsigned char byte;
typedef int array[10]
byte ch; ⇔ unsigned char ch
array x; ⇔int x[10]
166
기정의 매크로 상수
* 기정의 매크로 상수란 상황에 따라 변하는 상수를 말한다.
* '_'에서 시작해서 '_'로 끝난다.
* _LINE_
헤더를 포함한 현재의 라인 넘버를 나타내며 int 값을 가진
다.
* _FILE_
현재 컴파일 되고 있는 파일 이름을 문자열 상수 값으로 갖
는다.
• _DATE_,_TIME_
전처리기가 처리하고 있는 파일의 처리 시작 날짜와 시간을
문자열 상수 값으로 갖는다.
• _TINY_,_SMALL_,_MEDIUM_,_COMPACT_,_LARGE_,_HUGE_
메모리 모델에 해당하는 상수만 1로 정의되며 1이 아니면 정의 되
지도 않는다.
167
enum 문
• enum {열거형상수1,열거형상수2,...} 열거형변수1 열거형변수2
enum문으로 선언된 변수는 차례로 1,2,3,4...의 값을 갖는 enum문
멤버를 사용할수 있다.
• enum 열거택 {열거형상수1,열거형상수2,...};
열거택을 이용해서 enum문을 정의하면 프로그램 어디에서나
"enum 열거택 열거형변수1,열거형변수2,..."와 같은 방법으로 열거
형 변수를 선언 할 수 있다.
•
typedef enum {열거형상수1,열거형상수2,...} 대표문자열
typedef문을 이용하면 "대표문자열 열거형변수1,열거형변수2,..."
와 같은 방법으로 열거형 변수를 선언 할 수 있다
168
프로그램 속에서 이해하기
#include <stdio.h>
#include <conio.h>
#define ESC 27
#define ENTER 13
#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
void main(void) {
char ch;
int old_x, old_y, x, y;
old_x = x = 40;
old_y = y = 12;
clrscr();
169
while (1)
{
ch = getch();
if (!ch) {
ch = getch();
old_x = x;
old_y = y;
switch (ch) {
case UP : y = (y <= 1) ? 23 : y - 1;
break;
case DOWN : y = (y >= 23) ? 1 : y + 1;
break;
case LEFT : x = (x <= 1) ? 78 : x - 1;
break;
case RIGHT: x = (x >= 78) ? 1 : x + 1;
break;
}
170
gotoxy(x,y);
putchar('*');
gotoxy(old_x,old_y);
putchar(' ');
}
else
switch (ch)
{
case ESC :
case ENTER:
return;
}
}
}
171
위 프로그램의 실행 결과는 아래 설명과 같다.
UP key : * 를 위로 진행시킨다.
DOWN key : '*'를 아래로 진행시킨다.
LEFT key : '*'를 왼쪽으로 진행시킨다.
RIGHT key : '*'를 오른쪽으로 진행시킨다.
ESC, ENTER : 프로그램을 중단한다.
매크로 함수를 사용함으로써 생기는 이점은 샐행속도가 빨라진다는 것이
이유는, 일반 함수의경우 함수를 호출할 때 시간이 걸리는데 반해 매크로
함수는 사실 함수가 아니기 때문에 함수 호출 시간이 소모되지 않는다
(매크로 함수는 함수처럼 보일 뿐이지 사실은 연속적인 프로그램일 뿐이다).
172
※ SWAP 함수
SWAP이란 바꾼다는 뜻으로 두 개의 변수 값을 바꿀 때 사용하는 함수의
이름으로 많이 쓰인다. 두 변수의 값을 바꿀때는 보통 함수안에 다음과
같이 일시적 변수를 만들어 한 변수의 값이 없어지지 않도록 보관한다.
void swap(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
위 함수는 두 개의 정수 포인터를 받아 그 값을 바꾸어 주는 함수이다.
이 함수의 단점은 지역변수 temp를 사용한다는 점과 단지 두 개의 변수값
을 바꾸기 위해 함수 호출을 해야한다는 것인데, 이것을 비트연산인 XOR
를 이용하여 매크로 함수로 만들면 다음과 같다.
#define swap(a,b) { a ^= b; b ^= a; a ^= b; }
173
오늘의 해결과제
"my.h" 란 이름으로 파일을 하나 만들어 보자.
그리고 아래와 같이 저장을 하자.
1.
my.h 라는 파일을 하나 만들자. 이 파일은 텍스트 파일이어야 하므
로, 아 래 한글로 만들경우 "아스키 타입"으로 저장하기로 한자.
내용은 아 래와 같이 한줄만 포함한다.
#define MAX 100
2. c:\xxx> 밑에 my.h를 넣어 두자 ( 아무 디렉토리에 넣으라는 뜻임)
3. 이제 역시 똑같은 이름 "my.h"로 다른 헤더 파일을 만들자.
이것도 역시 텍스트 파일이어야 한다. 그리고 이번에는 아래와
같이 값이 123 이다.
#define MAX 123
174
4. 이제 c:\tc\include> 밑에 my.h를 넣어 두자.
(자기 시스템의 "헤더 파일"들 있는 곳에 저장하라는 뜻임)
그리고 프로그램을 다음과 같이 짜 보자.
#include
<-- (요기)
main()
{
printf("max = %d", MAX);
}
이 프로그램은 아주 간단하게도 MAX를 찍어 보라는 것인데,
위에서 (요기) my.h를 include 한 것을 보라. 우리는 my.h 라는
파일을 두 개 만들었기 때문에 내가 문제를 낼 수 있다.
위의 결과는 100 인가 ? 아니면 123 인가 ?
175
문자열

Character arrays & Character pointers
• "I am a string"
176
문자열 배열/포인터


char
char
amessage [] = "Hello, world";
*pmessage = "Hello, world";
177
문자열 배열/포인터
char string [][20] = {
"Im Chan sik",
"Im So young",
"Im Sun young",
};
178
문자열 배열/포인터
char *string [] = {
"Im Chan sik",
"Im So young",
"Im Sun young",
};
179
문자열 예제 #1
#include <stdio.h>
void main()
{
char *p[3] = {"c","Algorithm","Datastructure"};
/* char
p[3][14] = {"c","Algorithm","Datastructure"};
*/
int i;
printf("\n p
=> %p\n",p);
for(i=0;i<3;i++)
printf("\n p[%d] (address %p) => %s",i,p[i],p[i]);
}
180
문자열 #2
void main()
{
char *p;
char str[256];
int len;
strcpy(str,"World Cup 2002 Korea!");
p = str;
len = 0;
181
while(*p)
{
p++;
len++;
}
printf("\n%s, 문자열의 길이 = %d\n",str, len);
}
182
문자열 #3
#include <stdio.h>
int strlen(char* str)
{
int ret;
if(str)
ret = slen(str+1);
else
ret = 0;
return ret;
}
183
void main()
{
int len;
char* test = "Bitcamp";
printf("문자열의 길이 = %d", strlen(test));
}
184
오늘의 해결과제
1.
대문자를 소문자로 바꾸어주는 char tolower(char)
함수를 만드시오
2.
소문자를 대문자로 바꾸어주는 char toupper(char)
함수를 만드시오
185
문자열 #4
#include <ctype.h>
int htoi(char* s);
void main()
{
char* test = "ff";
printf("0x%s = %d", test, htoi(test));
}
186
/* htoi : convert hex number to dec number */
int htoi(char* s)
{
int hex, result = 0;
char* p;
while(!*p)
{
char ch = *p;
if(isalpha(*p))
hex = tolower(*p);
else if(isalnum(*p))
hex = *p;
187
else
return -1;
// error
result = result * 16 + hex;
p++;
}
return result;
}
188
문자열 #5
int isalpha(int ch)
{
if(ch <= 'z' && 'a’ <= ch)
return 1;
else
if(ch <= 'Z' && 'A‘ <= ch)
return 1;
else
return 0;
}
189
void main()
{
int ch;
while(ch = getchar())
{
if(isalpha(ch))
printf("Alphabet");
else
printf("Non-alpha");
printf("\n");
}
}
190
문자열 예제 #6
#include <stdio.h>
#include <string.h>
void main()
{
char *p[10];
char *str = "문자열의 메모리 w/o malloc";
int i;
for(i=0; i<10; i++) /* p[i]가 가리키는 곳 */
{
/*
w/ malloc
*/
printf("\n p[%d] = %p",i,p[i]);
191
strcpy(p[i],str);
printf("\n");
}
for(i=0; i<10; i+=2)
출력 */
printf("\n p[%d] => %s",i,p[i]);
/* 문 자 열 p[0],p[2],p[4] 를
}

/*
w/ malloc
p[i]=(char *)malloc(strlen(str));
*/
192
오늘의 해결과제
1.
문자열 s안에서 찾고자 하는 문자 스트링 t의 위치를
나타내는 함수를 작성하시오. 이때 찾고자하는 문자
열 t가 없을 때에는 –1을 리턴한다.
char* strfind(char* s, char* t);
2. 문자열 s를 거꾸로 하는 함수 reverse(s)를 작성하시
오
void reverse(char* s);
193
구조체 선언 형식
• struct 구조체택 {...} 변수리수트;
• struct 구조체택 {...};
struct 구조체택 변수리스트;
• typedef struct 구초체택 {...} 대표문자열;
대표문자열 변수리스트;
• 구초체 포인터 변수도 2byte만 차지하며 구초체의 크기에 따라
번지 띄기가 결정 된다.
• 구조체 멤버도 구조체가 들어 갈수 있다.
멤버 : 구조체 안의 변수 요소들을 말한다.
194
구조체의 연산
• 멤버 연산자-구조체 내의 멤버를 가르킬 때 사용한다.
구조체이름.멤버이름
• 구조체 멤버 포인터
(*pa).name == pa->name
• 구조체 대입
구조체이름 = 구조체이름
b.kor = a.eng /*구조체 멤버 대입*/
a = b /*구조체 대입*/
195
구조체의 초기화
• struct {
struct a { int x,y,z; };
/* 구 조 체
멤버로
구조체도
포함
할
수
있다*/
struct b {int w,x,y; };
} test = { {3,4,5}, {6,7,8} };
196
구조체를 매개 변수로 갖는 함수
• 구초체를 매개 변수로...
되돌림형 func (struct 구조체태그 구조체매개변수)
• 구초체 포인터를 매개 변수로...
되돌림형 func (struc 구조체태그 *구조체매개변수)
197
공용체
• 선언 형식은 공용체와 같고 단지,멤버들이 메모리를 공유 한다는
차이가 있다. 메모리에는 가장 큰 멤버의 크기 만큼 공용체가
들어갈 자리가 만들어 진다.
• union exunion {
int i;
char j;
float k;
} a;
라고 선언 했다면 메모리에는 가장 많은 메모리를 차지 하는 float형
변수 4byte만큼 자리가 만들어 진다.
198
비트 필드
• 비트 필드는 구조체 멤버를 비트 단위로 나눌수 있다.자료형은
Int,unsigned를 사용 할 수 있다.
• struct 구조체태그 { 데이타형 비트필드멤버이름 : 비트수;} 구조체
변수;
비트수는 왼쪽에 쓰여 있는 멤버가 차지하는 비트수로써 1~16 가능
하다.
199
구조체 #1
struct man
{
char c;
int k;
float e;
double m;
};
void main(void)
{
struct man a;
printf(" Address of a = %u, Sizeof(a) = %d\n",&a,sizeof(a));
printf("Address of a.c = %u, Sizeof(a.c) = %d\n",&a.c,sizeof(a.c));
printf("Address of a.k = %u, Sizeof(a.k) = %d\n",&a.k,sizeof(a.k));
printf("Address of a.e = %u, Sizeof(a.e) = %d\n",&a.e,sizeof(a.e));
printf("Address of a.m = %u, Sizeof(a.m) = %d\n",&a.m,sizeof(a.m));
}
200
구조체 #2
struct da
{
int x;
int y;
};
void main(void)
{
struct da val = { 10, 30 };
int sum = 0;
sum = total(val);
printf(" Sum = %d\n",sum);
}
201
구조체 #3
#include <stdio.h>
struct
{
char initial;
int age;
int grade;
} student[2];
/* last name initial
*/
/* childs age
*/
/* childs grade in school */
202
void main()
{
student[0].initial = 'H';
student[0].age = 25;
student[0].grade = 4;
student[1].age = student[0].age - 1; /* this student is one
year younger */
student[1].grade = 3;
student[1].initial = 'K';
printf("%c\' age is %d years old.\n%c\'s grade is %d\n",
student[1].initial, student[1].age, stude
nt[1].grade);
printf("%c\' age is %d years old.\n%c\'s grade is %d\n",
student[0].initial, student[0].age, stu
dent[0].grade);
}
203
구조체 #4
struct
{
char initial;
int age;
int grade;
} student[12];
void main()
{
204
int i;
for (i = 0 ; i < 12 ; i++)
{
student[i].initial = 'A' + i;
student[i].age = 16 + i;
student[i].grade = 84 + i;
}
student[3].age = student[5].age = 20;
// assignment
student[11] = student[0];
205
for (i = 0 ; i < 12 ; i++)
printf("%c\' age is %d years old. %c\'s grad
e is %d\n", student[i].initial, student[i].age, stud
ent[i].initial, student[i].grade);
}
206
구조체와 포인터 #1
#include <string.h>
struct man {
char name[30];
int kor;
int eng;
int math;
int total;
float ave;
};
207
구조체와 포인터 #2
void main(void)
{
struct man a, *pa;
pa = &a;
strcpy(pa->name,"Gunman");
pa->kor = 87;
pa->eng = 90;
pa->math = 75;
pa->total = pa->kor + pa->eng + pa->math;
pa->ave = pa->total / 3.0f;
printf(" Name : %s\n",pa->name);
printf(" Korean = %d\n",pa->kor);
printf("English = %d\n",pa->eng);
printf(" Math = %d\n",pa->math);
printf(" Total = %d\n",pa->total);
printf("Average = %.2f\n",pa->ave);
}
208
오늘의 해결과제(1)
아래와 같은 데이터가 있다고 할 때, N명의 학생에 관해
읽어서 각 학생의 평균 성적을 구한 후 평균 성적이 높은
학생에서 낮은 학생의 순으로 이름과 번호, 평균 점수를
출력하는 프로그램을 작성하시오. 단, N은 맨 처음 읽어
들이도록 하며, 학생의 수는 100명을 넘지 않는다고 가정
하고 학생의 번호는 92XXXX이며, 시험 점수는 0 에게
100점 사이이다.
(data)
4
Lee Seung Wook
923682 85 78 92 90 77
Kwon Oh Jin
923326 95 67 82 50 100
Kwon Oh Chang
922525 88 85 30 65 50
Oh Jung Pyo
925252 80 70 60 50 100
1.
209
오늘의 해결과제(2)
2.
자기 가족의 신상 명세를 구조체로 구성해 보시오.그리고 이 구조
를 이용하여 가족의 데이터를 저장하고 출력하는 프로그램에 도전
해 보시오. 이 프로그램은 C강의의 최종 프로젝트인 전화번호부
프로그램과 거의 유사합니다.
이때 필요한 멤버들은 본인 스스로 정합니다.
예를 들면,
struct family {
char name[10];
int age;
char *hobby;
.
.
. /* 필요한 부분 더 첨가 */
}
210
공용체
#include <stdio.h>
void main()
{
short i;
union
{
short val;
struct
{
char ch0;
char ch1;
211
} half;
} number;
for (i = 0 ; i < 1024 ; i += 16)
{
number.val = i;
printf("%4x %2x %2x\n",
number.val, number.half.ch0, number.half.ch1);
}
}
212
열거형 #1
void main()
{
int i;
COLOURS ch;
while( ch )
{
puts("Choose a color : ");
for(i = BLACK; i < WHITE; i++)
printf("%d) BLACK\n", i);
ch = getchar();
213
switch(ch)
{
case BLACK:
puts("Black is chosen");
break;
case BLUE:
puts("Blue is chosen");
break;
case GREEN:
puts("Gree is chosen");
break;
case RED:
puts("Red is chosen");
break;
214
case WHITE:
puts("White is chosen");
break;
}
}
}
215
열거형 #2
#include <stdio.h>
void main()
{
enum day {Monday, Tuesday, Wednesday, Thursday, Friday,
Saturday, Sunday};
for(days = Monday ; days < Sunday ; days++)
printf("The day code is %d\n", days);
}
216
오늘의 과제

1에서 12까지의 숫자를 입력받으면, 해당 월의 영문
이름과 날수를 출력하는 프로그램을 만드시오.

다음과 같이 출력하는 프로그램을 만드시오
– January : ********************
– Febrary : ********************
217
FILE I/O

파일 연산의 단계
–
–
–
–

1) stream 변수의 정의
2) 파일 open
3) read / write
4) File close
파일 입출력 함수의 종류
–
–
–
–
–
–
–
–
fopen / fclose
fgetc / fputc
fgets / fputs
fscanf / fprintf
fread / fwrite
feof / ferror
fseek
fsetpos / fgetpos
218

스트림
– 물리적 파일을 쉽게 다루기 위한 논리적 구조
– 문자의 흐름
– 일관성 있는 접근

File control structure for streams. <STDIO.H>
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
219

정의 되어진 스트림
– stdin, stdout, stderr, stdaux, stdprn ( redirection 여부에 따라 결정)

예제
#include <stdio.h>
#define MAXLINELEN 74
void main(int argc, char *argv[])
{
char buffer[MAXLINELEN +1];
int line = 1;
FILE *stream;
/* 1) stream(FILE *) 변수의 정의 */
if (arc <= 1) { puts(“Usage : list filename.ext\n”); exit(1); }
stream = fopen(argv[1], “r”); /* 2) 파일 open */
if (stream == 0) { puts(“file not found !\n”); exit(1); }
while (!eof(stream)) {
if (fgets(buffer, MAXLINELEN+1, stream) == NULL) break; /* 3)
read / write */
printf(“%3d : %s”, line++, buffer);
}
fclose(stream);
/* 4) File close */
}
220

File 복사 프로그램 (임의 파일)
/* 사용법 : filecopy filecopy.c fcopy.c */
#include <stdio.h>
void main(int argc, char *argv[])
{
int c;
/* 반드시 int type */
FILE *source, *dest;
if (argc <= 2) puts(“Usage : filecopy source dest\n”), exit(1);
if ((source = fopen(argv[1], “rb”) == NULL) perror(“Source\n”),
exit(1);
if ((dest = fopen(argv[2], “wb”) == NULL) perror(“Dest\n”),
exit(1);
while ((c = fgetc(source)) != EOF)
if (fgetc(c, dest) == EOF) break;
if (ferror(source) || ferror(dest))
perror(“Copying\n”), exit(1);
else if (fclose(dest) == EOF)
perror(“Dest\n”), exit(1);
else printf(“%s copied to %s\n”, argv[1], argv[2]), exit(0);
}
221

fprintf, fscanf 서식화 함수
/* 개인의 이름과 신장 체중파일을 만드는 프로그램 */
#include <stdio.h>
void main(int argc, char *argv[])
{
char name[128]; /* 이름 */
int
height; /* 신장 */
float weight; /* 몸무게 */
FILE *fp;
if (argc < 2) puts(“Usage : filename datafile\n”), exit(1);
if((fp=fopen(argv[1], "w"))==NULL)
puts("화일을 쓸 수 없습니
다!"), exit(1);
scanf("%s%d%f", name, &height, &weight);
while (strcmp(name,"end")) {
fprintf(fp,"%10s %3d %4.1f\n", name, height, weight),
scanf("%s %d %f", name, &height, &weight);
}
fclose(fp);
/* END OF ffp */
222
if ((fp = fopen(argv[1], "r"))==NULL) puts("화일을 읽을 수 없습니다!"),
exit(1);
clrscr();
while (!feof(fp))
/*주의 ! 화일의 끝을 검사하기 위해 feof함수를 쓴
다.*/
{
fscanf(fp,"%s%d%f",name,&height,&weight),
printf("%10s %3d %4.1f\n",name,height,weight);
}
fclose(fp);
/* END OF ffp */
}
223
random access 파일의 입출력
fread, fwrite 함수
#include <stdio.h>
typedef struct rec { char name[20]; int num; } REC;

#define NUM 3
void main()
{
int i, j;
FILE *fp;
REC stud[NUM];
if ((fp=fopen(”name.lst", "wb"))==NULL)
{
224
puts("화일을 개방할 수 없습니다 !");
exit(1);
}
for ( i = 0; i < NUM; i++)
{
scanf(“%s %d”, stud[i].name, &stud[i].num);
fwrite(stud[i]. name, sizeof(stud[i]. name), 1, fp);
fwrite(stud[i]. num, sizeof(stud[i]. num), 1, fp);
}
fclose(fp);
if ((fp=fopen("name.lst","rb"))==NULL){
puts("화일을 개방할 수 없습니다 !");
exit(1);
}
225
for(j = 0; j < i; j ++)
{
if (fread (stud[j]. name, sizeof(stud[j]. name), 1, fp) != 1)
break;
if (fread (stud[j]. num, sizeof(stud[j]. num), 1, fp) != 1)
break;
puts(stud[j]. name), printf(“%12d\n”, stud[j]. num);
}
fclose(fp);
}
226

int fseek(FILE *stream, long offset, int whence)
whence
SEEK_SET
SEEK_CUR
SEEK_END
상수
0
1
2
기준점
파일 처음
현재 레코드 위치
파일 마지막+1
offset
0L 이상
임의
0L이하
fp
파일
처음
fseek(fp, 0, SEEK_SET)
파일 마지막+1
fseek(fp, 0, SEEK_END)
fseek(fp, 5*REC_SIZE, SEEK_SET)
fseek(fp, -3*REC_SIZE, SEEK_END)
fseek(fp, 2*REC_SIZE, SEEK_CUR)
227

long ftell(FILE *stream)
#include <stdio.h>
long filesize(FILE *stream)
{
long curpos, filesize;
printf(“curpos = %ld\n”, curpos = ftell(stream));
fseek(stream, 0L, SEEK_END);
printf(“curpos = %ld\n”, filesize = ftell(stream));
fseek(stream, curpos, SEEK_SET);
printf(“curpos = %ld\n”, ftell(stream));
return filesize;
}

getchar();
getchar 함수는 매크로 함수이며 stdio.h 안에 다음과 같이 선언되어
있다.
– #define getchar() getc( stdin )



getchar 함수는 버퍼형 함수이기 때문에 getchar 함수가 호출되면
먼저 버퍼를검사한다. 이때, 버퍼가 비어있으면 키보드 입력을 받
게되는데, 이때의 입력은 버퍼로 들어가고 ^Z 후 엔터키(^D:UNIX)
를 누르면 버퍼로 들어가는 작업을 마치면서 버퍼에서 한 글자를
꺼내어 리턴하게 된다. 만일 버퍼를 검사할 때, 버퍼가 비어있지 않
으면 키보드 입력을 받지 않고 그냥 버퍼에서 글자를 가져온다.
getch() 함수와 getche() 함수는 직접 키보드에서 입력을 받는 함수
이다. 두 함수 모두 입력받은 키의 아스키 값을 리턴한다.
getch() : 키보드 입력을 받으면서 화면에 아무것도 나타나지 않는
다.
getche() : 입력받은 문자가 화면에 나타난다.
229
File I/O #1
#include <stdio.h>
int main()
{
FILE *in, *out;
in = fopen("data.dat",’r’);
if (in == NULL)
{
puts("\nUnable to open file data.dat for reading");
return 1;
}
230
out = fopen("data.bak",’w’);
if (out == NULL)
{
puts("\nUnable to create file data.bak");
return 1;
}
while(feof(in))
{
char ch = fgetc(in);
fputc(ch,out);
}
fclose(in);
fclose(out);
}
231
File I/O #2
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp;
char str[256];
int i;
fp = fopen("output.txt", "w");
strcpy(str, "The output text");
232
for (i = 1 ; i <= 7 ; i++)
fprintf("%s Text #%d\n", str, i);
fclose(fp);
return 0;
}
233
File I/O #3
#include <stdio.h>
int main(void)
{
FILE *fp;
char str[256];
fp = fopen("output.txt", "r");
while (feof(fp))
{
fgets(str, 256, fp);
234
printf(str);
}
fclose(fp);
return 0;
}
235
오늘의 해결과제
1.
첫 예제에서 파일로 출력된 결과를 즉시 화면에 출력
하도록 수정하시오.
2.
앞의 성적을 입력받아서 출력하는 예제를 수정하여
파일에 저장하고 파일로부터 읽을 수 있도록 만드시
오 (구조체 문제).
236
File I/O #4
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *in, *printer;
int c;
in = fopen("output.txt", "r");
if (in == NULL)
{
printf("입력 파일을 열수 없읍니다.\n");
getchar();
exit (EXIT_FAILURE);
237
}
printer = fopen("PRN", "w");
if (printer == NULL)
{
printf("프린터를 열수 없읍니다.\n");
getchar();
exit (EXIT_FAILURE);
}
c = getc(in);
while (c != EOF)
{
putchar(c);
putc(c, printer);
c = getc(in);
238
}
fclose(in);
fclose(printer);
return EXIT_SUCCESS;
}
239
File I/O #5
struct record {
int i;
long l;
char str[10];
};
int main(void)
{
int i;
char *name = "박찬호";
struct record rec[10];
FILE *out;
char* p;
240
for(i=0; i<10; i++)
{
rec[i].i = i;
rec[i].l = i*1000;
p = name;
while(*p)
{
*(rec[i].str + (p - name)) = *p;
p += 1;
}
*(rec[i].str + (p - name)) = *p;
}
out = fopen("output.dat", "w");
if (out == NULL)
241
{
printf("출럭 파일을 열수 없읍니다.\n");
exit (EXIT_FAILURE);
}
for(i=0; i<10; i++)
{
fwrite(&rec[i], sizeof(struct record), 1, out);
}
fclose(out);
return EXIT_SUCCESS;
}
242
오늘의 해결과제

fread라는 함수를 사용하여 앞의 예제에서 저장된 데
이터를 읽어들이고, 출력하는 프로그램을 만드시오.
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
#include <stdio.h>
243
Standard Functions #1






int getchar( void );
int putchar( int c );
int scanf( const char *format [,argument]... );
int getc( FILE *stream );
int putc( int c, FILE *stream );
int fscanf( FILE *stream, const char *format [, argu
ment ]... );
244
getchar
int main(void)
{
int ch;
printf("문자를 입력하세요 : ");
ch = getchar();
printf("당신이 입력한 문자는 다음과 같습니다. : %c", ch);
return 0;
}
245
putchar
int main(void)
{
int ch;
while(1)
{
printf("문자를 입력하세요 : ");
ch = getchar(); getchar();
printf("당신이 입력한 문자는 다음과 같습니다. : ");
putchar(ch);
printf("\n");
}
return 0;
}
246
scanf
#include<stdio.h>
int main(void)
{
int base;
float tmp, ratio, total;
printf("What is the base? ");
scanf("%d", &base);
printf("What is the interested ratio? ");
scanf("%f", &ratio);
247
tmp = base * ratio / 100;
printf("Calculated interest is %f \n", tmp);
total = tmp + base;
printf("The total is %f\n", total);
return 0;
}
248
getc
void main( void )
{
char buffer[81];
int i, ch;
printf( "Enter a line: \n" );
for( i = 0; i < 80; i++ ) {
ch = getc(stdin);
if( (ch == EOF) || (ch == '\n') ) break;
buffer[i] = (char)ch;
}
buffer[i] = '\0';
printf( "%s\n", buffer );
}
249
putc
void main( void )
{
int ch = 0;
FILE *stream = stdout;
char *p;
char *str = “2002 World Cup Korea\n";
for( p = str; (ch != EOF) && (*p != '\0'); p++ )
ch = putc( *p, stream );
}
250
fscanf
FILE *stream;
void main( void )
{
long l;
float fp;
char s[81];
char c;
stream = fopen( "fscanf.out", "w+" );
if( stream == NULL )
printf( "The file fscanf.out was not opened\n" );
else
{
251
fprintf( stream, "%s %ld %f %c", "Leonardo Dicaprio",
250000000L, 3.14159f, 'q' );
fseek( stream, 0L, SEEK_SET );
fscanf( stream, "%s", s );
fscanf( stream, "%ld", &l );
fscanf( stream, "%f", &fp );
fscanf( stream, "%c", &c );
printf( "%s\n", s );
printf( "%ld\n", l );
printf( "%f\n", fp );
printf( "%c\n", c );
fclose( stream );
}
}
252
오늘의 해결과제

File에 저장된 내용을 16진수로 출력하는 프로그램을
만드시오.
(출력예)
What is the name you want to dump?
test.dat
test.dat:
23 69 6E 63 6C 75 64 65 20 3C 73 74 64 69 6F 2E
68 3E 0D 0A 0D 0A 2F 2A 0D 0A 2F 2F 20 50 72 65
70 72 6F 63 65 73 73 6F 72 20 23 31 0D 0A 23 64
65 66 69 6E 65 20 42 45 47 49 4E 20 09 31 20 20
20 20 20 20 20 0D 0A 23 64 65 66 69 6E 65 20 45
253
Standard Functions #2
char *fgets( char *string, int n, FILE *stream );
 int fputs( const char *string, FILE *stream );
 size_t fread( void *buffer, size_t size, size_t count,
FILE *stream );
 size_t fwrite( const void *buffer, size_t size, size_t
count, FILE *stream );
 int feof( FILE *stream );
 int ferror( FILE *stream );

254
fgets
void main( void )
{
FILE *file;
char buffer[256];
if( (file = fopen( "stdfunc.c", "r" )) != NULL )
{
if( fgets( buffer, 256) == NULL)
printf( "fgets error\n" );
else
printf( "%s", line);
fclose( file );
}
}
255
fputs
void main( void )
{
FILE *file;
if( (file = fopen( "stdfunc.out", “r" )) != NULL )
{
if( fputs( "Hello world from fputs.\n" ) = EOF)
printf( "fputs error\n" );
fclose( file );
}
}
256
fread & fwrite
void main( void )
{
int i, nread, nwritten;
FILE *file;
char buf[30];
// There should be 2 badly coded statements.
if( (file = fopen( "stdfunc.out", "w+" )) != NULL )
{
for ( i = 0; i < 10; i++ )
buf[i] = 'A' + i;
nwritten = fwrite( buf, sizeof( char ), 10, file );
printf( "Wrote %d items\n", nwritten );
}
257
else
printf( "Problem opening the file\n" );
fclose( file );
if( (file == fopen( "stdfunc.out", "r+" )) != NULL )
{
nread = fread( buf, sizeof( char ), 10, file );
buf[10] = 0;
printf( "Number of items read = %d\n", nread );
printf( "Contents of buffer = %.20s\n", buf );
}
else
printf( "File could not be opened\n" );
fclose( file );
}
258
feof & ferror
void main( void )
{
int count, total_bytes = 0;
char buffer[256];
FILE *file;
if( file = fopen( "stdfunc.c", "r" ) )
{
while( feof( file ) )
{
count = fread( buffer, sizeof( char ), file );
259
if( !ferror( file ) ) {
perror( "Read error" );
break;
}
total_bytes += count;
}
printf( “Bytes read : %d\n", total_bytes );
fclose( file );
}
}
260
오늘의 해결과제

이름과 주소를 10개 입력받아서 파일에 저장하시오.
(예) 홍길동 XX도 XX시 XX구 XX동 XXX-XXX호

저장된 10개의 주소를 파일로부터 읽어서 출력하시
오.
261
Standard Functions #3




char *strcat( char *strDestination, const char *strS
ource );
int strcmp( const char *string1, const char *string2
);
char *strcpy( char *strDestination, const char *strS
ource );
size_t strlen( const char *string );
262
strcat
void main(void)
{
char str1[100] = "This is ";
char *str2 = "string concatenation test.";
char *str3;
str3 = strcat(str1, str2);
printf("%s\n", str3);
}
263
strcmp
void main()
{
char* str1 = "This is a string comparison example.";
char* str2 = "This is a string to be compared.";
if(strcmp(str1, str2) > 0)
puts("str1 is greater.");
else if (strcmp(str1, str2) == 0)
puts("Two string is same.");
else
puts("str2 is greater.");
}
264
strcpy
void main()
{
char tgtstr[100];
char* srcstr = "This is source string.";
char* p;
strcpy(tgtstr, srcstr);
p = strstr(tgtstr, "source");
strcpy(p, "target string.");
puts(tgtstr);
}
265
오늘의 해결과제
1.
파일을 읽어서 단어의(word) 갯수를 출력하는 프로
그램을 만드시오.
2.
파일을 읽어서 알파벳 별로 빈도수를 출력하는 프로
그램을 만드시오.
266
Dynamic memory #1
#include <stdio.h>
#include <stdlib.h>
main()
{
int *x;
int n;
x = malloc(1000 * sizeof(int));
if (x = NULL)
{
printf(“메모리 할당 실패”); exit(0);
}
267
for(n = 0; n <= 1000; n++)
{
*x = n;
x++;
}
x = 1000;
for(n = 0; n <= 1000; n++){
printf("\nx[%d] = %d", n,*x);
x++;
}
free(x);
}
268
Dynamic memory #2
#include <stdio.h>
#include <stdlib.h>
void main()
{
int *p;
int n;
p = malloc(1000 * sizeof(int));
if (p == NULL)
{
printf("메모리 할당 실패"); exit(0);
}
269
for(n = 0; n <= 1000; n++)
{
p+n = n;
}
for(n = 0; n <= 1000; n++){
printf("p[%d] = %d ", n, p+n);
}
free(p);
}
270
Dynamic memory #3
#include <stdio.h>
#include <stdlib.h>
void main()
{
#define MAXX
#define MAXY
16
10
int i, j;
int* p;
p = malloc(MAXX*MAXY);
271
for(i = 0; i < MAX; i++)
{
for(j = 0; j < MAXY; j++)
{
p+i*MAXX+j = MAXX*i+j;
printf("%4d ", p+i*MAXX+j);
}
}
}
272
오늘의 해결과제

동적 메모리를 할당하여 배열로 해결한 소수(prime
number) 구하기 프로그램을 만드시오.

malloc을 사용하여 매개변수로 전달된 메모리의 내용
을 복사하여 리턴하는 함수를 만드시오.
int a[] = { 1, 2, 3, 4 };
b = mcopy(a, sizeof(a));
free(b);
273
Dynamic memory #4
void main()
{
#define MAXX 16
#define MAXY 16
int i, j;
int* p;
int** q;
p = malloc(MAXX*MAXY*sizeof(int));
q = malloc(MAXY*sizeof(int*));
274
for(i = 0; i < MAXY; i++)
*(q+i) = p+MAXX*i;
for(i = 0; i < MAXY; i++)
{
for(j = 0; j < MAXX; j++)
{
*(*(q+i)+j) = i * MAXX + j;
printf("%4d ", *(*(q+i)+j));
}
printf("\n");
}
}
275
Dynamic memory #5
void main()
{
#define MAXX 16
#define MAXY 16
#define MAXZ 2
int
int
int
int
i, j, k;
*p;
**q;
***r;
p = malloc(MAXX*MAXY*MAXZ*sizeof(int));
276
for(i = 0; i < MAXZ; i++)
*(r+i) = q+MAXY*i;
for(j = 0; j < MAXY; j++)
*(q+j) = p+MAXX*MAXZ*j;
for(i = 0; i < MAXZ; i++)
{
for(j = 0; j < MAXY; i++)
{
for(k = 0; k < MAXY; k++)
{
*(*(r+i)+j)+k) = i * MAXY + j * MAXX + k;
printf("%3d ", *(*(r+i)+j)+k) );
}
printf("\n");
}
printf("\n");
}
}
277
Proprocessor #1
#include <stdio.h>
#define
#define
#define
#define
BEGIN
END
MIN(A,B)
MAX(A,B)
1
10
(A)>(B)?(B):(A)
(A)>(B)?(A):(B)
int main()
{
int i, min, max;
int count = 5;
278
for (i = BEGIN ; i <= END ; i++)
{
max = MAX(i, count);
min = MIN(i, count);
printf("Max is %d and min is %d\n", max, min);
}
return 0;
}
279
Proprocessor #2
#define BEGIN
#define END
1
7
#define WRONG(A)
#define SQUARE(A)
#define CUBE(A)
A*A*A
(A)*(A)
(A)*(A)*(A)
#define ADD_WRONG(A)
#define ADD_RIGHT(A)
(A)+(A)
((A)+(A))
int main()
{
280
int i, base = 5;
for (i = BEGIN ; i <= END ; i++)
{
printf("False addition = %6d, right addition = %6d\n",
5*ADD_WRONG(i), 5*ADD_RIGHT(i));
}
for (i = BEGIN ; i <= END ; i++)
{
printf("%3d's square = %4d, its cube = %6d\n",
i+base, SQUARE(i+base), CUBE(i+base));
printf("Invalid cube of %3d is %6d\n",
i+base, WRONG(i+base));
}
return 0;
}
281
Proprocessor #3
#define MY_DEFINE
#ifdef MY_DEFINE
int count = 17;
#endif
int main()
{
int i;
for (i = 0 ; i < 10 ; i++)
{
282
printf("i = %d", i);
#ifdef MY_DEFINE
printf(" count = %d", count++);
#endif
printf("\n");
}
return 0;
}
#undef MY_DEFINE
283
Proprocessor #4
#define MY_DEFINE
#ifndef MY_DEFINE
int count = 5;
#endif
int main()
{
int i;
#ifndef PRINT_DATA
printf("No results will be printed with this version of program
\n");
284
#endif
for (i = 0 ; i < 6 ; i++)
{
#ifdef PRINT_DATA
printf("i = %d", i);
#ifndef MY_DEFINE
printf(" count = %d", count);
#endif
printf("\n");
#endif
}
return 0;
}
285
Proprocessor #5
#include <stdio.h>
#define DEBUG
int main()
{
int i, cnt;
for (i = 0 ; i < 6 ; i++)
{
printf("i is now %d", i);
printf(" and we can process the data");
printf("\n");
286
#ifdef DEBUG
puts(“<<<<<<< The process is not implement
ed yet! >>>>>>>");
#else
for (cnt = 1 ; cnt < i ; cnt++)
{
value = // see the documentation
limit = // ask somebody about this limit
printf("Some right data\n");
}
#endif
}
return 0;
}
287
자료구조

순차리스트
연속적으로 저장되는 고정된 갯수의 데이터 item
 index에 의해 접근 가능
– 배열(array)
– 스택(stack)
– 큐(Queue)

연결리스트(linked list]
 동적으로 item을 삽입하거나 삭제하는 것이 가능
 각item들을 효율적으로 재배치하는 것이 가능
– 단순 연결리스트
– 원형 연결리스트
– 이중 연결리스트
– 복합 연결리스트
288
Stack
스택의 정의
– 여러 개의 데이타 항목들이 일정한 순서로 나열된 자료 구조
– 한쪽 끝에서만 새로운 항목을 삽입하거나 기존 항목을 삭제할 수 있도
록 고안된 것이다.
스택의 원리
– 스택은 동전을 넣고 뺄 수 있도록 되어 있는 동전 케이스와 같은 작동
원리
스택의 성격
– 후입 선출 리스트(Last- In-First-Out List) : 스택에 저장된 데이타 항목
들 중에 먼저 삽입된 것은 나중에 삭제되고, 나중에 삽입된 것이 먼저
삭제된다.
289
Stack (계속)

스택의 구조 (그림 6)
– 스택은 base로부터 데이타 항목들을 차례로 쌓아올린 모양을 가진다.
– 삽입과 삭제는 현재 저장된 최상위 항목이 위치한 top 에서만 일어난
다.
– top 위치는 "스택 포인터"라는 지시자가 가리킨다.
– 스택 포인터는 스택 기저에서 시작하여 항목이 삽입되면 하나 증가하
고, 삭제되면 하나 감소한다.
– 스택에는 한계가 있어서 그 한계를 초과하도록 삽입할 수 없다.
290
Stack (계속)

스택의 동작
삽입(push)
삭제(pop)
Full 검사
Empty 검사
– 스택에 데이타 항목 삽입 (push)
데이타 항목을 삽입하려면 스택 포인터를 하나만큼 증가시켜 주고 스택의
top 에
데이타 항목을 저장한다. 데이타 항목을 삽입하기 전에 새로운 항목을 저
장할 빈
공간이 있는지 검사(full 검사)해야 한다. stack[++top] = 데이터;
– 스택에서 데이타 항목 삭제 (pop)
데이타 항목을 삭제하려면 스택의 top 에 있는 데이타 항목을 제거하고
스택 포인터를 하나만큼 감소시켜 준다. 데이타 항목을 삭제하기 전에
스택이 비어있는지를 검사(empty 검사 )해야 한다.
return
stack[top--];
291
Stack (계속)
292
Stack (예제)
/* STACK : array version
*/
#include <stdio.h>
#define MAX 5
int stack[MAX];
int top;
void init_stack(void)
{
top = -1;
}
293
int push(int t)
{
if (top >= MAX-1)
{
printf("Stack overflow.\n");
return -1;
}
stack[++top] = t;
return t;
}
int pop(void)
{
294
if (top < 0)
{
printf("Stack underflow.\n");
return -1;
}
return stack[top--];
}
void print_stack(void)
{
int i;
printf("Stack contents : Top ----> Bottom\n");
if(top == -1) printf("[Stack empty]\n");
295
for (i = top; i >= 0; i--)
{
printf("%d ", stack[i]);
}
printf("\n");
}
void main()
{
int i;
init_stack();
printf("\nPush 3, 2, 5, 7, 2\n");
push(3); push(2); push(5); push(7); push(2);
296
print_stack();
printf("\nNow stack is full, push 3\n");
push(3);
print_stack();
printf("\nInitialize stack\n");
init_stack();
print_stack();
printf("\nNow stack is empty, pop\n");
i = pop();
printf("popping value is %d\n", i);
print_stack();
}
297
/* STACK : Linked list version
*/
#include <stdio.h>
#include <alloc.h>
typedef struct _node
{
char key;
struct _node *next;
} node;
node *head, *tail;
298
void init_stack(void)
{
head = (node*)malloc(sizeof(node));
tail = (node*)malloc(sizeof(node));
head->next = tail;
tail->next = tail;
}
void clear_stack(void)
{
node *t, *s;
t = head->next;
while (t != tail)
299
{
s = t;
t = t->next;
free(s);
}
head->next = tail;
}
int push(char k)
{
node *t;
if ((t = (node*)malloc(sizeof(node))) == NULL)
{
300
printf("\n Out of memory...");
return -1;
}
t->key = k;
t->next = head->next;
head->next = t;
return k;
}
char pop(void)
{
node *t;
char i;
301
if (head->next == tail) /* if empty */
{
printf("\n Stack underflow.");
return -1;
}
t = head->next;
i = t->key;
head->next = t->next;
free(t);
return i;
}
302
void print_stack(void)
{
node *t;
t = head->next;
printf("\n Stack contents : Top ----> Bottom\n");
while (t != tail)
{
printf("%-6d", t->key);
t = t->next;
}
}
303
void main(void)
{
int i;
init_stack();
printf("\nPush 5, 4, 7, 8, 2, 1");
push(5);
push(4);
push(7);
push(1);
print_stack();
push(8);
push(2);
printf("\nPop");
i = pop();
print_stack();
printf("\n popping value is %d", i);
304
printf("\nPush 3, 2, 5, 7, 2");
push(3); push(2); push(5);
print_stack();
printf("\nPush 3");
push(3);
print_stack();
push(7);
push(2);
printf("\nInitialize stack");
clear_stack();
print_stack();
printf("\nNow stack is empty, pop");
i = pop();
305
print_stack();
printf("\n popping value is %d", i);
}
306
Queue

큐의 정의
– 여러 개의 데이타 항목들이 일정한 순서로 나열된 자료 구조
– 한쪽 끝에서 삽입, 삭제할 수 있도록 되어 있다.

큐의 원리
– 큐는 매표소에서 표를 사기 위해 기다리는 대기자 열과 같은 원리
– 대기자 열에는 먼저 온 사람부터 차례로 대기자들이 늘어서 있다.
앞쪽 끝에서는 기다리던 사람이 표를 사서 빠져나가고 (삭제), 뒤쪽
끝에서는 새로운 사람들이 대기자 열로 들어온다(삽입).

큐의 성격
– 선입 선출 리스트 (First-In-First-Out:FIFO) : 큐에 저장된 데이타 항
목들 중에 먼저 삽입된 것은 먼저 삭제되고, 나중에 삽입된 것은 나
중에 삭제된다.

큐의 종류
– 선형 큐(linear queue) : 한 방향으로 데이타 항목들이 삽입/삭제
– 원형 큐(circular queue) : 시작점과 끝점이 서로 연결
307
Queue (계속)

선형 큐
– 선형 큐의 구조 (Queue1)
• rear : 새로운 데이터 항목의 삽입
• front : 기존 데이터 항목의 삭제
– front 포인터와 rear 포인터는 초기에 하한에서 시작하여 삽입과 삭제
가 반복됨에 따라 상한쪽으로 이동한다

선형 큐의 동작
– 선형 큐에 데이타 항목 삽입 (full 검사 : front 포인터 = rear 포인터)
• rear 포인터를 하나만큼 증가시켜 주고 그 위치에 데이타 항목을 저장한다.
– 선형 큐에서 데이타 항목 삭제 (empty 검사 : front 포인터 = rear 포인
터)
• 큐의 front 포인터를 하나만큼 증가시키고 그 위치에 있는 데이타 항목을 삭
제한다.
308
Queue (계속)

큐의 삽입과 삭제
309
Queue (계속)

원형 큐
– 원형 큐의 구조
• 원형 큐는 선형 큐의 문제점을 보완하기 위해 만들어진 자료구조
– 원형 큐의 동작
• 삽입과 삭제 동작은 선형 큐와 일치
포인터가 큐의 끝점에 있을 때 삽입이나 삭제가 일어나면 포인터가 reset 되
어 다시 시작점을 가리킨다.
문제점 : empty, full 두 경우다 front 포인터=rear 포인터
310
Queue (계속)

개선된 원형 큐
– 데이타 항목 삭제(삽입) :
front 포인터를 하나만큼 증가시키고, 그 위치에 있는 데이타 항목을 제
거
rear 포인터를 하나만큼 증가시키고, 그 위치에 새로운 데이터 항목을
삽입
하나의 여유 공간을 두고 그 공간은 사용하지 못하도록 한다.
– empty 검사 (rear pointer = front pointer)
– full 검사 (rear pointer + 1 = front pointer)
311
Queue (예제)
/* QUEUE : array Version
*/
#include <stdio.h>
#define MAX 10
int queue[MAX];
int front, rear;
void init_queue(void)
{
front = rear = 0;
}
312
/* QUEUE : array Version
*/
#include <stdio.h>
#define MAX 10
int queue[MAX];
int front, rear;
void init_queue(void)
{
front = rear = 0;
}
313
void clear_queue(void)
{
front = rear;
}
int put(int k)
{
if ((rear + 1) % MAX == front) /* queue is full */
{
printf("\n Queue overflow.");
return -1;
}
queue[rear] = k;
314
rear = ++rear % MAX;
return k;
}
int get(void)
{
int i;
if (front == rear) /* queue is empty */
{
printf("\n Queue underflow.");
return -1;
}
i = queue[front];
315
front = ++front % MAX;
return i;
}
void print_queue(void)
{
int i;
printf("\n Queue contents : Front ----> Rear\n");
for (i = front; i != rear; i = ++i % MAX) /* caution */
printf("%-6d", queue[i]);
}
316
void main(void)
{
int i;
init_queue();
printf("\nPut 5, 4, 7, 8, 2, 1");
put(5); put(4); put(7); put(8);
print_queue();
put(2);
put(1);
printf("\nGet");
i = get();
print_queue();
printf("\n getting value is %d", i);
317
printf("\nPut 3, 2, 5, 7");
put(3); put(2); put(5);
print_queue();
put(7);
printf("\nNow queue is full, put 3");
put(3);
print_queue();
printf("\nInitialize queue");
clear_queue();
print_queue();
printf("\nNow queue is empty, get");
318
i = get();
print_queue();
printf("\n getting value is %d", i);
}
319