티스토리 뷰

이차원 배열


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
 
int main() {
    // m[10][10]에서 m[0]의 의미는 무엇인가?
    int m[10][10= {
        {11,12,13,14,15,16,17,18,19,10},
        {21,22,23,24,25,26,27,28,29,20},
    };
    printf("이차원 배열의 인덱스 : %d\n", m);
    printf("이차원 배열의 첫 행 인덱스 : %d\n", m[0]);
    printf("이차원 배열의 첫 행, 첫 열의 원소 : %d\n", m[0][0]);
    // m[n]은 행에 대한 인덱스라고 할 수 있다.
 
    // m[10][10]에서 (m+1)의 의미는 무엇인가?
    printf("인덱스의 주소 : %d\n", m);
    printf("첫 행 인덱스의 주소 : %d\n", m + 1);            // 크기 40만큼 shift
    printf("2행 1열의 원소의 주소 : %d\n"&m[1][0]);
    // m은 40Bytes 크기를 가진 배열이라고 볼 수 있다.
    
    return 0;
}
 
cs



포인터


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main() {
    // double형 포인터를 가리키는 이중 포인터 dp를 선언하여 보자.
    double **dp;
 
    // 다음과 같이 정의 된 변수는 각각 무엇을 의마하는 가?
    char c;        // char형 변수 c
    char *p;    // char형을 가르키는 포인터 p
    char **dp;    // char형의 포인터를 가르키는 이중포인터 dp
    p = &c;        // p에는 c의 주소를 대입한다.
    dp = &p;    // dp에는 p의 주소를 대입한다.
 
    return 0;
}
cs



포인터 강제 형변환


1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
int main() {
    
    int target = 5;
    void *vp = &target;
 
    // void형 포인터 vp를 int형 포인터 ip로 형변환하는 문장을 작성하라.
    printf("%d\n"*(int *)vp);
 
    return 0;
}
cs



동적메모리, 빈칸 채우기


1. 프로그램의 실행 도중에 메모리를 할당받아서 사용하는 것을 ( 동적 메모리 할당 )이라고 한다.

2. 동적으로 메모리를 할당받을 때 사용하는 대표적인 함수는 ( malloc )이다.

3. 동적으로 할당된 메모리를 해제하는 함수는 ( free )이다.

4. 동적 메모리 함수의 원형은 헤더파일 ( stdlib.h )에 정의되어 있다.


1. 동적 할당 후에 메모리 블록을 초기화하여 넘겨주는 함수는 ( calloc )이다

2. 할당되었던 동적 메모리의 크기를 변경하는 함수는 ( realloc )이다.

3. 동적 메모리 할당에서의 단위는 ( Byte )이다.

4. malloc이 반환하는 자료형은 ( void * )이다.



동적메모리, 빈칸 채우기


1. 연결 리스트에서 다음 노드는 ( 포인터 )로 가리킨다.

2. 연결 리스트의 일반적인 노드는 ( 데이터 ) 필드와 ( 링크 ) 필드로 구성되어 있다.

3. 구조체의 멤버 중에 자기 자신을 가리키는 포인터가 존재하는 구조체를 ( 자기 참조 구조체 )라고 한다.

4. 배열과 연결리스트의 가장 큰 차이점은 무엇인가? ( 배열의 크기는 정적이고 연결리스트의 크기는 동적이다 ) 



배열 주의사항


1. 배열에서 초기화를 제외하고는 중괄호로 묶어 대입할 수 없다.

2. 배열의 이름(상수포인터)를 사용해 대입할 수 없다.

3. 배열의 이름으로 두 배열을 비교할 수 없다.

4. 함수의 인자로 배열의 이름을 사용 시 내용의 직접 변경이 가능해진다. const 연산자를 사용해 원본 변경을 방지할 수 있다.



포인터 주의사항


1. NULL로 초기화 하기

2. NULL 포인터로 접근을 시도하면 동작 멈춤

3. 포인터는 인덱스 표기법보다 빠르다. (인덱스 접근 시, 주소 계산이 들어가기 때문에 속도가 저하된다)

4. 지역변수의 포인터를 반환하지 않도록 주의해야한다.

5. 포인터 cast 연산의 결과로 const, volatile 특성이 상실될 수 있다.



구조체 주의사항


1. 구조체는 함수를 넣을 수 없음. 하지만 C++에서는 컴파일러가 자동으로 구조체를 클래스로 바꾸어 구조체 내에 함수를 넣을 수 있음

2. 구조체의 이름 없이 선언이 가능하다.

3. 구조체간 대입은 가능하지만 비교는 불가능하다.

4. 구조체 내부가 같더라도 구조체 이름이 다르면 대입 불가.

5. 구조체를 함수 인자로 전달 시 복사과정이 포함된다. 포인터를 사용하자.



주요 연산자


1. 간접 참조 연산자(*) : 포인터가 가르키는 값을 읽어옴

2. 멤버 연산자, 지정 연산자, 닷 연산자(.) : 구조체 멤버 접근

3. 애로우 연산자(->) : 구조체 포인터로 구조체 멤버를 참조할 때 사용




========================================================================================


주요 라이브러리 및 함수


1
2
3
4
5
6
7
8
9
#include <Windows.h>    // system(), Sleep()
#include <stdio.h>        
#include <math.h>        // 연산관련 라이브러리
#include <string.h>        // memcpy(), memcmp(), strcmp(), strncmp(), 
                        // strcat(), strtok(), strlen(), strcpy()
#include <stdlib.h>        // free(), malloc(), calloc(), ralloc(),
                        // atoi(), rand(), exit()
#include <malloc.h>        // malloc()
#include <time.h>        // 시간관련 라이브러리
cs



Selection Sort (선택정렬)


정렬이 안된 숫자들 중 최소 값을 선택하여 배열의 첫번째 요소와 교환하여 채워나가는 방식



Bubble Sort (버블정렬)


인접한 레코드를 비교하여 교환하며 전체가 정렬 될 때까지 반복하여 정렬하는 방식



Binary Search (이진 검색)


중앙의 원소(median)와 비교를 반복하여 찾아나가는 방식



포인터 연산자 우선순위


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main() {
    int target = 5;
    int *= &target;
    int **pp = &p;
    int v = 0;
                // printf("v = %d, target = %d, p = %d\n", v, target, p);
    v = *p++;        // v = *p, p++
    v = (*p)++;  // v = *p, (*p)++
    v = *++p;    // ++p, v = p(new p, p+1)
    v = ++*p;    // ++(*p), v = p(new target) 
    
    return 0;
}
cs



Union (공용체)


내부에 선언된 성분 중 가장 큰 데이터 형식의 크기를 공유한다. IP Address가 대표적인 예.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
typedef union IP {
    unsigned long linear;
    unsigned char address[4];
}IP;
 
int main() {
    
    union IP target;
    
    target.address[0= 192;        // 우측
    target.address[1= 0;
    target.address[2= 255;
    target.address[3= 255;        // 좌측
    
    printf("%x\n", target.linear);
 
    return 0;
}
cs



Ragged Array


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
int main() {
    // double형의 포인터 10개를 가지는 배열을 정의하여 보자.
    double arr[10];
 
    // Ragged 배열이 일반적인 2차원 배열보다 좋은 점은 무엇인가?
    // Ragged 배열은 행마다 사이즈가 다른 2차원 배열이다.
    char *RaggedArr[3];
    char A[] = { 'A''B''C' };
    char B[] = { 'D''E' };
    char C[] = { 'F' };
    RaggedArr[0= A;    printf("%c\n", RaggedArr[0][2]);
    RaggedArr[1= B;    printf("%c\n", RaggedArr[1][1]);
    RaggedArr[2= C;    printf("%c\n", RaggedArr[2][0]);
    // Ragged 배열을 사용하면 메모리를 낭비없이 쓸 수 있다는 장점이 있다.
}
cs



문자열 포인터 배열


문자열 리터럴 사용으로 수정이 불가하다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int main() {
    
    char *alphabet[] = {
        "abc",    // 'abc\n', alphabet[0]
        "def",    // 'def\n', alphabet[1]
        "ghi",    // 'ghi\n', alphabet[2]
        "jkl",    // 'jkl\n', alphabet[3]
        "mno"    // 'mno\n', alphabet[4]
    };
 
    return 0;
}
cs



함수 포인터


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int target(doubledouble);
 
int main() {
    // int 값을 반환하고 double 값을 인수로 받는 함수의 포인터 pf를 선언하여 보자.
    int(*pf)(doubledouble= target; // pf = target;
    // 위의 함수 포인터를 통하여 3.0을 인수로 하여 함수를 호출하는 문장을 작성하라.
    printf("%d\n", pf(3.03.0));
}
 
int target(double a, double b) {
    return a + b;
}
cs



Volatile 포인터


컴파일러의 최적화에서 제외시킨다. 즉, 컴파일러가 최적화를 위해 중간과정을 생략하는 것을 방지해 매번 메모리에서 읽어오도록 지시한다.



외부로부터 입력을 받는 main() 함수


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
// C>main arg1 arg2 arg3와 같이 실행시킬 떄 argv[0]가 가리키는 것은?
// C>main arg1 arg2 arg3와 같이 실행시킬 떄 argc가 가리키는 것은?
int main(int argc, char *argv[]) {
    // 자바의 경우, public static void main(String[] args)
    printf("%s\n", argv[0]);    // main
    printf("%s\n", argv[1]);    // arg1
    printf("%s\n", argv[2]);    // arg2
    printf("%s\n", argv[3]);    // arg3
 
    printf("%d", argc);            // 4, argv 배열의 원소 갯수
    
    return 0;
}
cs



calloc() 함수


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>        // calloc()
 
typedef struct TARGET {
    int sample;
} TARGET;
 
int main() {
    // 함수 원형, calloc(size_t elt_count, size_t elt_size)
    // elt_size 크기의 변수를 elt_count 만큼 저장할 수 있는 공간을 만듦.
    // malloc()은 할당된 공간의 값을 변경하지 않지만 calloc()은 공간의 값을 0으로 초기화
    
    TARGET *target_m = (TARGET *)malloc(sizeof(TARGET) * 3);    // void 포인터
    TARGET *target_c = calloc(3, sizeof(TARGET));                // TARGET 포인터
 
    return 0;
}
cs



realloc() 함수


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>        // realloc()
 
typedef struct TARGET {
    int sample;
} TARGET;
 
int main() {
    // 함수 원형, realloc(void *memblock, size_t size)
    // 변경하고 싶은 동적메모리 포인터를 memblock에 변경할 크기를 size에 입력한다.
    
    TARGET *target_m = (TARGET *)malloc(sizeof(TARGET) * 3);    // 3
    realloc(target_m, sizeof(TARGET) * 5);                        // 5
    return 0;
}
cs



디지털 단위


bit : bit

Nibble : 4 bit

Byte : Byte

Word : 하나의 명령어를 통해 레지스터로 옮겨 담을 수 있는 자료의 단위 (CPU의 bit)

Field : 파일 구성의 최소 단위, 데이터베이스에선 열을 나타냄

Record : 프로그램에서 처리하는 자료의 기본 단위, 파일의 구성 요소

Block : 페이지 단위의 데이터

File : 파일 단위의 데이터

Database : 파일의 집합


bit < Nibble < Byte < Word < Field < Logical Record < Physical Record < Block < File < Database



10진수 표현 : Zone 형식


10진수 한 자리를 표현하기 위해 1Byte를 사용하는 형식 1111XXXX로 표현되며 상위 4비트는 존 영역, 하위 4비트는 수치영역.

마지막 자리(하위 Byte)의 존 영역에 부호를 표시 1100(C, 양수), 1101(D, 음수)



10진수 표현 : Pack 형식


존 영역 없이 4비트를 사용하는 형식.

마지막 자리(최 하위 4bit)에 부호를 표시.



2진수 표현


부호 절대값 형식 : 최상위 1bit는 부호비트, 나머지는 이진수 표시

1의 보수 형식 : 0, 1을 바꿈

2의 보수 형식 : 1의 보수에 1을 더해준다.



2진수의 실수 표현


고정 소수점 : 소수점이 항상 최상위 비트 왼쪽 밖에 고정

부동 소수점 : 소수부와 지수부를 나누어 사용    // 4바이트(32bit) 중 MSB 부호비트, 지수부(7bit), 소수부(3Byte)



문자자료의 표현


BCD 코드 : 6bit 사용, 상위 2bit는 존 비트, 하위 4bit는 2진수 비트    // 숫자 0~9, 대문자                            // A :     01 0001

EBCDIC 코드 : 8bit 사용, 상위 4bit는 존 비트, 하위 4비트는 2진수 비트    // 숫자 0~9, 대/소문자, 특수문자     // A : 1100 0001

ASCII 코드 : 7bit 사용, 상위 3비트는 존 비트, 하위 4비트는 2진수 비트    // 숫자 0~9, 대/소문자, 특수문자     // A :   100 0001



문자열 자료의 표현


구분자를 사용하는 방법 : 메모리 이용 적다, 속도 느리다.

고정 길이로 저장하는 방법 : 메모리 이용 높다, 속도 빠르다.

포인터를 사용하는 방법 : 메모리 이용 적다, 속도 빠르다, 구현 어렵다.


사용성 : 고정 길이(배열) > 구분자 > 포인터



소프트웨어 생명주기


설계 단계 : 상 / 하향 / 객체지향 설계

구현 단계 : 구조화 / 모듈러 프로그래밍

테스트 단계 : 단위 / 통합 / 인수 테스트

유지보수 : 수정형 / 적응형 / 완전형 / 예방형 유지보수

품질평가 : 정확성 / 유지보수성 / 무결성 / 사용성


요구분석 -> 시스템 명세 -> 설계 -> 구현 -> 테스트 -> 유지보수



추상 자료형 (ADT, Abstract Data Type)


자료와 연산자의 특성을 논리적으로 추상화하여 정의한 자료형


추상화 : "무엇(What)인가?"를 논리적으로 정의    / 추상 자료형    / 알고리즘 정의

구체화 : "어떻게(How)할 것인가?"를 실제적으로 표현    / 자료형    / 프로그램 구현



알고리즘(Algorithm)


문제 해결방법을 추상화하여 절차를 논리적으로 기술해 놓은 명세서


입력(input) : 

출력(output) : 하나 이상의 결과 출력

명확성(definiteness) : 내용과 순서를 나타내는 알고리즘 명령어들은 명확해야 한다.

유한성(finiteness) : 알고리즘은 수행 뒤 반드시 종료해야 한다.

효과성(effectiveness) : 알고리즘은 기본적이고 실행 가능해야 한다.


자연어를 이용한 서술적 표현 방법

순서도를 이용한 도식화 표현 방법

프로그래밍 언어를 이용한 구체화 방법

가상코드(ADL, 알고리즘 기술언어)를 이용한 추상화 방법





댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함