제 1장 C 언어의 소개
C 언어의 개요 ANSI C POSIX 표준 기존의 K&R C에 새로운 기능을 추가한 표준 문법 함수의 선언과 정의에 인자(argument)의 데이터 형 포함 기능 구조체 지정(assignment)와 나열형(enumeration)을 표준으로 채택 단점도(single precison)의 부동 소수점 계산 지원 부호 없는 숫자의 산술 연산과 전처리기 기능 개선 POSIX 표준 Portable Operating System Interface for Computing Environments의 약자 IEEE에서 C 라이브러리의 표준 제정 C 프로그램의 이식성을 높임
First C Program #include <stdio.h> /* first C Program*/ main() { printf(“Hello World\n”) ; }
First C Program(con’d) 모든 C 프로그램은 main 함수부터 시작 #include <stdio.h> 헤더 파일을 포함 주석문은 /* 와 */로 둘러 싸임 printf는 화면에 문자열을 출력하는 함수 문자열 : a sequence of characters enclosed by double quote “Hello World\n” \n : newline 문자(escape sequence) C에서는 대소문자가 구분
변수 모든 변수는 사용되기 전에 선언한다. 변수의 선언 지정문(assignment statement) 대부분 함수의 시작부분에 위치 datatype var1, var2,...; 데이터형: char, short, int, long, float, double ex) int number, sum ; 지정문(assignment statement) 변수에 값을 지정 ex) number = 1 ;
산술 연산 사칙 연산 덧셈, 뺄셈, 곱셈, 나눗셈: +, -, *, / 나머지 연산자 (%) 수식 x%y는 x를 y로 나눈 나머지를 의미
순환문(Loop) 프로그램에서 반복되는 작업을 구현하는데 사용 C에서 제공되는 순환문 for 문 while 문 do while 문
순환문 예제(while) #include <stdio.h> main() { int n, sum = 0 ; while ( n <= 100 ) { sum = sum + n ; n = n + 1 ; } printf(“Sum = %d\n”, sum) ;
순환문 예제(for) #include <stdio.h> main() { int n, sum = 0 ; for ( n = 1 ; n <= 100 ; n = n + 1 ) sum = sum + n ; printf(“Sum = %d\n”, sum) ; }
순환문 예제(do-while) #include <stdio.h> main() { int n = 1, sum = 0 ; do { sum = sum + n ; n = n + 1 ; } while ( n <= 100 ) ; printf(“Sum = %d\n”, sum) ; }
입력과 출력 C는 자체적으로 입출력 기능 X 라이브러리 함수 이용 getchar putchar 키보드로부터 문자를 입력받아 리턴 c = getchar() ; putchar 화면에 한 문자를 출력하는 함수 putchar(c) ; printf와 scanf : 형식화된 입출력 제공 printf(“%d, %d”, i, j) ; scanf(“%d %d”, &i, &j) ;
입력과 출력(예제) #include <stdio.h> main() { int c ; c = getchar() ; while ( c != EOF ) { putchar(c) ; }
입력과 출력(con’d) #include <stdio.h> main() { char c, *s; c = 'C'; printf("%s %c %s\n",s,c,"를 배우고 있어요."); }
입력과 출력(printf)
입력과 출력(con’d) printf() 예제 #include <stdio.h> main() { printf("나이는 %u살 입니다.",25); printf("%3d - %-3d = %5d 입니다.",10,20,10-20); printf("%u시%u분%u초",10,28,45); printf("체중은 %.2f Kg입니다.",68.5); }
입력과 출력(scanf)
입력과 출력(scanf) #include <stdio.h> main() { int i; float f; char c; char s[80]; printf("Input Data"); printf("형식: 정수 실수 문자 문자열"); scanf("%d %f %c %s",&i,&f,&c,&d); printf("정수 = %d 실수 = %f 문자 = %c 문자열 = %s",i,f,c,s); }
심볼 상수(symbolic constant) #define문에 의한 심볼 상수 정의 프로그램에서 매직 넘버를 사용하는 것을 피해야 함 #define name replacement-text 전처리기가 name에 해당하는 토큰을 replacement-text로 치환 ex) #define MAXLEN 256 int length = MAXLEN;
배열 기억장소에 여러 개의 원소를 연속적인 공간에 저장하여 참조 선언 방법 배열의 첨자 type array-name[size] ; ex) int ndigit[10] ; 배열의 첨자 배열의 원소를 참조하는 데에 사용 첨자는 0부터 시작 ex) ndigit[0], ndigit[1], ...., ndigit[8], ndigit[9]
문자 배열 문자열을 저장하기 위해서 사용함 문자열 : 쌍따옴표로 둘러싸인 일련의 문자들 ‘\0’ 문자 : 문자열의 끝을 나타냄 “Hello\n”는 다음과 같이 저장 길이가 n인 문자열을 저장하려면 문자 배열의 크기는 n+1이어야 함
배열(예제) #include <stdio.h> main() { int c, i, nwhite, nother ; int ndigit[10] ; nwhite = nother = 0 ; for ( i = 0 ; i < 10 ; i++ ) ndigit[i] = 0 ;
While ( ( c = getchar() ) != EOF ) if ( c >= ‘0’ && c <= ‘9’ ) ++ndigit[c - ’0’] ; else if ( c == ‘ ‘ || c == ‘\n’ || c == ‘\t’ ) ++nwhite ; else ++nother ; printf(“digits =“) ; for ( i = 0 ; i < 10 ; i++ ) printf(“ %d”, ndigits[i]) ; printf( “, white space = %d, other = %d\n”, nwhite, nother) ; }
함수 프로그램의 기능적 분할 호출부(caller)에 내부 구현 내용이 보이지 않음 함수의 정의 방법 return-type function-name(argument declaration, if any) { declarations statements } 호출부와 피호출 함수사이의 데이터 전달 인자(argument) 전달 함수의 리턴값
함수(예제) #include <stdio.h> int power( int base, int n ) ; /* 함수의 선언 */ main() { int i ; for ( i = 0 ; i < 10 ; i++ ) printf( “%d %d %d\n”, i, power( 2, i ), power(-3, i ) ; }
형식 인자(formal argument) int power( int base, int n )/* 함수의 정의 */ { int i, p ; p = 1 ; for ( i = 1 ; i <= n ; i++ ) p = p * base ; return p ; } 형식 인자(formal argument) 함수에 전달된 인자(실질 인자)를 접근하기 위하여 사용. ex) base, n 호출부로의 값 전달 return return-value
제 2장 데이터형, 연산자, 수식
변수의 이름 변수와 심볼 상수 변수의 용도와 관련되도록 이름을 부여하는 것이 좋음 문자, 숫자, '_'(underscore)로 구성됨 반드시 첫글자는 문자 또는 '_’ 처음 31자까지만 의미가 있음 대문자와 소문자 구별(case sensitive) 변수는 주로 소문자를, 심볼 상수는 대문자를 사용 C 언어의 키워드는 변수의 이름으로 사용될 수 없음 변수의 용도와 관련되도록 이름을 부여하는 것이 좋음
변수의 선언 모든 변수는 사용되기전에 선언되어야 한다. 선언은 변수의 이름과 데이타형을 알린다. 변수의 초기화 초기값을 갖는 자동 변수: 함수가 호출될 때마다 초기화됨 초기값을 갖지 않는 자동 변수: 임의의 정해지지 않은 값을 가짐 한정사 const 값이 변경되지 않는 변수의 선언에 사용 ex) const char msg[] = "This will not be changed.";
데이터형과 크기 정수형 실수형
데이터형과 크기(con’d) 문자형 <limit.h>와 <float.h>는 지원하는 숫자의 크기를 심볼 상수로 정의
상수 정수 상수(integet constant) 부동소수점 상수(floating point constant) 십진수, 8진수, 16진수로 표현가능 ex) 1234, -1234, 1234L, 01234, 0xabcd, 0XABCD 부동소수점 상수(floating point constant) 123.4, 1.234e2, 1.234E2의 형태로 표현
상수(con’d) 문자 상수 ‘a’, ‘A’, ‘0’ 과 같이 표현(single quote 사용) escape sequence: 제어 문자 표현
상수(con’d) 문자열 상수 “DCSLAB”와 같이 double quote로 둘러싸인 일련의 문자들 “”: 빈 문자열 문자 상수 ‘a’와 문자열 상수 “a”는 구분되어야 한다.
Enumeration constant enum boolean FALSE, TRUE ; #define을 사용하는 것보다 간결함 enum형 변수를 정의할 수 있다. enum escapes { BELL = ‘\a’, BACKSPACE = ‘\b’, TAB = ‘\t’} ; enum months { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC } ; /* FEB = 2, MAR = 3, ..... */
예제 프로그램 #include <stdio.h> main() { int a, b, c, sum ; float d, e ; a = 123 ; b = 4537 ; c = 32943 ; sum = a + b + c ; printf(“%d + %d + %d = %d \n”) ; }
산술 연산자 사칙 연산과 나머지 연산(%) 이항(binary) 연산자: +. -. *, /, % *, /, % 연산은 +, -보다 연산 우선순위가 높다. % 연산은 float와 double형에는 사용될 수 없다. 단항(unary) 연산자 +와 -는 이항 연산자보다 우선순위가 높다.
관계 연산자와 논리 연산자 관계 연산자 논리 연산자
비트 연산자 char, short, int, long형의 피연산자만을 취함 비트 연산자의 종류
++, --연산자 ++연산자 -- 연산자 전위(prefix) 또는 후위(postfix)에 위치할 수 있음 변수를 1만큼 증가시킴 -- 연산자 변수를 1만큼 감소시킴 전위(prefix) 또는 후위(postfix)에 위치할 수 있음 전위에 오는 경우: 변수를 참조하기 전에 후위에 오는 경우: 변수를 참조한 후 ex) n = 0; n = 0; x = ++n; x = n++; n = 1, x = 1 n = 1, x = 0;
지정 연산자(assignment operator) i = i + 2;와 같이 왼쪽의 변수가 오른쪽에서 반복되는 경우에 사용 연산자의 사용예 i += 2; i -= 2; i *= 2; i /= 2; i %= 2; i <<= 2; or i >>= 2; i &= 2; i |= 2; i ^= 2;
조건부 수식(conditional expression) 아래와 같은 동작을 취하는 삼항(ternary) 연산자 ?: if (expr1) expr2; else expr3; => expr1 ? expr2 : expr3으로 표현 계산 과정 expr1을 계산하여 결과가 참이면 expr2가 수행되고 거짓이면 expr3을 수행 ex) max = (a > b) ? a : b;
형변환(type conversion) 연산자가 서로 다른 형의 피연산자를 가질 때 형변환이 필요 일반적으로 크기가 작은 피연산자를 큰 연산자로 형변환 규칙 Rule 1. 피연산자 중 long double이 있으면 나머지는 long double로 변환 Rule 2. 피연산자 중 double이 있으면 나머지는 double로 변환 Rule 3. 피연산자 중 float가 있으면 나머지는 float로 변환 Rule 4. 피연산자 중 char나 short는 int로 변환 Rule 5. 피연산자 중 long이 있으면 나머지는 long으로 변환
형 변환(con’d) type cast: 명시적 형 변환 (type-name) expression ex) int i ; float f = 12.34 ; i = (int) f ;
연산자 간의 우선순위
연산자 간의 우선순위(con’d)
예제 #include <stdio.h> main() { int x, y, z; x = 1, y = 2, z = 4; x = x || y && z; printf("%d\n",x); x = 1, y = 2, z = 3; x = (x > y || z ==y && x<z); x = y = z = 1; x = -y++ + ++z; printf("%d\n%d\n%d\n",x,y,z); }
제 3 장 제어흐름
문장(statement)와 블록(block) 지정문, 증감 연산( ++, -- ), 함수 호출 등의 서식 문장문 ;( semicolon)으로 끝남 블록 복합문(compound statement) brace { } 로 선언과 문장들을 모아서 복합문을 만듬 ex) function body
if-else 판단이나 결정을 나타내기 위해 사용 if (expression) statement1 else statement2 expression이 0이 아닌 값을 가지면(참이면) statement1이 수행되고 0이면(거짓이면) else 부분의 statement2가 수행된다. 모호성(ambiguity) if ( n > 0 ) if ( a > b ) z = a ; else z = b ; /* else 와 매치되는 if는 ? */
if - else(con’d) 모호성의 해결 가장 가까운 if 의 else로 취급(컴파일러) 브레이스를 사용(명시적 지정) ex) if ( n > 0 ) { if ( a > b ) z = a ; } else z = b ;
else if multi-way decision에 사용 구문 if (expression) statement else if (expression) else
switch문 switch 문은 다중 비교 분기의 특별한 경우 구문 switch (expression) { break case const-expr: statements .................... default: statements } break case는 레이블로만 사용됨 제어의 흐름을 switch문에서 벗어나게 함
switch 문 사용예 #include <stdio.h> main() { int c, i, nwhite, nother, ndigit[10] ; nwhite = nother = 0; for ( i = 0 ; i < 10 ; i++ ) ndigit[i] = 0; while (( c = getch() ) != EOF ) switch ( c ) case '0’ : case '1’ : case '2’ : case '3’ : case '4’ : case '5’ : case '6’ : case '7’ : case '8’ : case '9’ : ndigit[c - '0']++; b reak;
switch문 사용예(con’d) case ‘ ‘ : case ‘\n’ : case ‘\t’ : nwhite++ ; break ; default : nother++ ; } printf( “digits = “ ) ; for ( i = 0 ; i < 10 ; i++ ) printf( “ %d”, ndigit[i] ) ; printf( “, white space = %d, other = %d\n”, nwhite, nother ) ; return 0 ;
while 문 구문 while ( expression ) statement expression은 계산되어 만약 0이 아닌 값을 가지면 statement가 수행이 되고 expression을 다시 계산, 이러한 반복은 expression이 0이 될 때까지 계속됨 예제 int i = 0 ; while ( i <= 100 ) { .......... i++ ; }
for 문 구문 for ( expr1 ; expr2 ; expr3 ) 동작 while문의 형태로 표시하면 다음과 같다. statement 동작 while문의 형태로 표시하면 다음과 같다. expr1 ; while ( expr2 ) { statment expr3 ; }
for 문(con’d) for문의 구조 for ( ; ; ;) { /* infinite loop */ 순환문의 중단 expr1과 expr3은 일반적으로 지정문이나 함수 호출로 구성 expr2는 관계 수식(relational expression)으로 표현 세 개의 수식중 어느 하나를 생략하더라도 세미콜론(;)은 그대로 존재 expr2가 생략되면 항상 참인 조건을 의미 for ( ; ; ;) { /* infinite loop */ ....... } 순환문의 중단 break와 return 사용 순환문내에 순환문을 중첩시킬 수 있음
comma 연산자 하나의 수식에서 여러 개의 계산을 수행하는 경우에 사용 comma는 함수의 인자를 분리하는 데도 사용하고 변수의 선언에도 사용되지만 이는 comma 연산자가 아님
comma 연산자(con’d) 예제 #include <string.h> main() { int c, i, j; char *s = “Hello world”; for (i = 0, j = strlen(s) - 1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; }
do while문 for문과 while문은 순환문의 종료 조건을 순환문의 시작 위치에서 검사 구문 do statement while (expression); 동작 statement가 먼저 수행이 되고 expression이 계산됨 만약 expression이 참이면 statement는 다시 수행을 반복하게 되고 expression이 거짓이 되면 반복을 종료
do while문(con’d) 예제 #include <stdio.h> main() { int ch; do { printf("Once again? (y/n) "); ch = getchar(); } while (ch != 'n' && ch != 'y'); }
break 문 for, while, do while, switch문 바깥으로 빠져 나가는데 사용 순cc c환문이 중첩되는 경우에는 break 는 break를 둘러싸는 가장 안쪽 순환문을 빠져 나옴 for ( ... ) { ........ break ; }
break 문 예제 while ((c = getchar()) != EOF) { if (c == '') break; else putchar(c); }
continue 문 break 문에 비해 자주 사용되지는 않음 for, while, do while 문에서만 사용될 수 있음 for (i = 0; i < n; i++) { if (a[i] < 0) continue; /* skip negative value */ ......... }
/* skip negative value */ continue 문 for (i = 0; i < n; i++) { /* skip negative value */ if (a[i] < 0) continue; ......... }
goto 문과 레이블 일반적으로 goto문과 같은 무조건 분기문은 가급적 사용하지 말아야 함 불가피한 경우 프로그램이 이해하기 어려워짐 대분분의 코드는 goto문 없이 작성할 수 있음 불가피한 경우 중첩된 순환문에서 가장 안쪽 순환문에서 전체 순환문을 빠져나가는 경우
goto 문과 레이블 error: clean up the mess 레이블(label): 분기의 목적지, 콜론(:)을 수반
예제 /* 소수 추출 프로그램(C Primer Plus에서 발췌) */ #include <stdio.h> main() { int number, divisor, limit; int count = 0; printf("상한 값을 입력하라.(2보다 커야함) :"); scanf("%d",&limit); while (limit < 2) { /* 입력오류 검사 */ printf("다시 입력하라: "); }
예제(con’d) printf("1에서 %d까지의 소수들은..\n",limit); for (number=2;number<=limit;number++) { for (divisor=2;number%divisor != 0;divisor++) ; if (divisor == number) { printf("%5d ",number); count++; if (count % 10 == 0) /*한줄에 10개의 소수출력*/ printf("\n"); } getch();