배열, 포인터 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원 E304호, hwlee@inje.ac.kr
다음주 준비 12장 읽어 올 것 숙제 제출할 것
쉽게 풀어쓴 C언어 Express 제10장 배열 C Express
배열을 사용하면 한 번에 여러 개의 값을 저장할 수 있는 공간을 할당받을 수 있다. 이번 장에서 학습할 내용 배열을 사용하면 한 번에 여러 개의 값을 저장할 수 있는 공간을 할당받을 수 있다. 반복의 개념 이해 배열의 개념 배열의 선언과 초기화 일차원 배열 다차원 배열
배열의 필요성 학생이 10명이 있고 이들의 평균 성적을 계산한다고 가정하자. 방법 #1 : 개별 변수 사용 int s0; 개별변수를 사용하는 방법은 학생수가 많아지면 번거로워집니다. 방법 #1 : 개별 변수 사용 int s0; int s1; … int s9; 방법 #1 : 배열 사용 int s[10];
배열이란? 배열(array): 동일한 타입의 데이터가 여러 개 저장되어 있는 데이터 저장 장소 배열 안에 들어있는 각각의 데이터들은 정수로 되어 있는 번호(첨자)에 의하여 접 근 배열을 이용하면 여러 개의 값을 하나의 이름으로 처리할 수 있다.
배열 원소와 인덱스 인덱스(index): 배열 원소의 번호 첨자 또는 인덱스
배열의 선언 자료형: 배열 원소들이 int형라는 것을 의미 배열 이름: 배열을 사용할 때 사용하는 이름이 grade 배열 크기: 배열 원소의 개수가 10개 인덱스(배열 번호)는 항상 0부터 시작한다.
배열 선언의 예 // 60개의 int형 값을 가지는 배열 grade int score[60]; // 12개의 float형 값을 가지는 배열 cost float cost[12]; char name[50]; // 50개의 char형 값을 가지는 배열 name
배열 원소 접근 grade[5] = 80 grade[5] = 80; grade[1] = grade[0]; grade[0] grade[1] grade[2] grade[3] grade[4] grade[5] grade[6] grade[7] grade[8] grade[9] grade[5] = 80 인덱스 grade[5] = 80; grade[1] = grade[0]; grade[i] = 100; // i는 정수 변수 grade[i+2] = 100; // 수식이 인덱스가 된다. grade[index[3]] = 100; // index[]는 정수 배열
배열 선언 예제 #include <stdio.h> int main(void) grade[0]=10 { int i; int grade[5]; grade[0] = 10; grade[1] = 20; grade[2] = 30; grade[3] = 40; grade[4] = 50; for(i=0;i < 5; i++) printf("grade[%d]=%d\n",i, grade[i]); return 0; } grade[0]=10 grade[1]=20 grade[2]=30 grade[3]=40 grade[4]=50
배열과 반복문 배열의 가장 큰 장점은 반복문을 사용하여서 배열의 원소를 간편하게 처리 할 수 있다는 점 배열의 가장 큰 장점은 반복문을 사용하여서 배열의 원소를 간편하게 처리 할 수 있다는 점 grade[0] = 0; grade[1] = 0; grade[2] = 0; grade[3] = 0; grade[4] = 0; #define SIZE 5 ... for(i=0 ; i<SIZE ; i++) grade[i] = 0;
배열 선언 예제 #include <stdio.h> #include <stdlib.h> #define SIZE 5 int main(void) { int i; int grade[SIZE]; for(i = 0; i < SIZE; i++) grade[i] = rand() % 100; printf("grade[%d]=%d\n", i, grade[i]); return 0; } grade[0]=41 grade[1]=67 grade[2]=34 grade[3]=0 grade[4]=69
배열 선언 예제 #include <stdio.h> #include <stdlib.h> #define SIZE 5 int main(void) { int i; int grade[SIZE]; printf("5명의 점수를 입력하시오\n"); for(i = 0; i < SIZE; i++) scanf("%d", &grade[i]); printf("grade[%d]=%d\n", i, grade[i]); return 0; } 5명의 점수를 입력하시오 23 35 67 45 21 grade[0]=23 grade[1]=35 grade[2]=67 grade[3]=45 grade[4]=21
배열 선언 예제 #include <stdio.h> #define STUDENTS 5 int main(void) { int grade[STUDENTS]; int sum = 0; int i, average; for(i = 0; i < STUDENTS; i++) printf("학생들의 성적을 입력하시오: "); scanf("%d", &grade[i]); } sum += grade[i]; average = sum / STUDENTS; printf("성적 평균= %d\n", average); return 0; 학생들의 성적을 입력하시오: 10 학생들의 성적을 입력하시오: 20 학생들의 성적을 입력하시오: 30 학생들의 성적을 입력하시오: 40 학생들의 성적을 입력하시오: 50 성적 평균 = 30
잘못된 인덱스 문제 인덱스가 배열의 크기를 벗어나게 되면 프로그램에 치명적인 오류를 발생 시킨다. 인덱스가 배열의 크기를 벗어나게 되면 프로그램에 치명적인 오류를 발생 시킨다. C에서는 프로그래머가 인덱스가 범위를 벗어나지 않았는지를 확인하고 책 임을 져야 한다. int grade[5]; … grade[5] = 60; // 치명적인 오류!
잘못된 인덱스 예제 #include <stdio.h> int main(void) { int grade[5]; int i; grade[0]=10; grade[1]=20; grade[2]=30; grade[3]=40; grade[4]=50; grade[5]=60; for(i = 0; i <= 5; i++) printf("grade[%d]=%d\n", i, grade[i]); return 0; } 시스템에 심각한 오류가 발생할 수도 있다.
중간 점검 독립적인 여러 개의 변수 대신에 배열을 사용하는 이유는 무엇인가? n개의 원소를 가지는 배열의 경우, 첫 번째 원소의 번호는 무엇인가? n개의 원소를 가지는 배열의 경우, 마지막 원소의 번호는 무엇인가? 배열 원소의 번호 혹은 위치를 무엇이라고 하는가? 배열의 크기보다 더 큰 인덱스를 사용하면 어떻게 되는가? 배열의 크기를 나타낼 때 변수를 사용할 수 있는가?
배열의 초기화 10 20 30 40 50 10 20 30 int grade[5] = { 10,20,30,40,50 }; grade[0] grade[1] grade[2] grade[3] grade[4] 초기값을 일부만 주면 나머지 원소들은 0으로 초기화됩니다. int grade[5] = { 10 , 20 , 30 }; grade[0] grade[1] grade[2] grade[3] grade[4]
배열의 초기화 배열의 크기가 주어지지 않으면 자동적으로 초기값의 개수만큼이 배열 의 크기로 잡힌다. 6 int grade[ ] = { 10 , 20 , 30 , 40 , 50 , 60 }; grade[0] grade[1] grade[2] grade[3] grade[4] grade[5]
배열 초기화 예제 #include <stdio.h> int main(void) { int grade[5] = { 31, 63, 62, 87, 14 }; int i; for(i = 0; i < 5; i++) printf("grade[%d] = %d\n", i, grade[i]); return 0; } grade[0] = 31 grade[1] = 63 grade[2] = 62 grade[3] = 87 grade[4] = 14
배열 초기화 예제 #include <stdio.h> int main(void) { int grade[5] = { 31, 63 }; int i; for(i = 0; i < 5; i++) printf("grade[%d] = %d\n", i, grade[i]); return 0; } grade[0] = 31 grade[1] = 63 grade[2] = 0 grade[3] = 0 grade[4] = 0
배열 초기화 예제 #include <stdio.h> int main(void) { int grade[5] ; int i; for(i = 0; i < 5; i++) printf("grade[%d] = %d\n", i, grade[i]); return 0; } grade[0]=4206620 grade[1]=0 grade[2]=4206636 grade[3]=2018779649 grade[4]=1
배열 초기화 예제 #include <stdio.h> int main(void) { int grade[5] ; int i; for(i = 0; i < 5; i++) printf("grade[%d] = %d\n", i, grade[i]); return 0; } grade[0]=4206620 grade[1]=0 grade[2]=4206636 grade[3]=2018779649 grade[4]=1
배열 원소의 개수 계산 int grade[] = { 1, 2, 3, 4, 5, 6 }; int i, size; size = sizeof(grade) / sizeof(grade[0]); for(i = 0; i < size ; i++) printf("%d ", grade[i]); 배열 원소 개수 자동 계산
배열의 복사 int grade[SIZE]; int score[SIZE]; 잘못된 방법 score = grade; // 컴파일 오류! 잘못된 방법 int grade[SIZE]; int score[SIZE]; int i; for(i = 0; i < SIZE; i++) score[i] = grade[i]; 원소를 일일이 복사한다 올바른 방법
배열의 비교 #include <stdio.h> #define SIZE 5 int main(void) { int i; int a[SIZE] = { 1, 2, 3, 4, 5 }; int b[SIZE] = { 1, 2, 3, 4, 5 }; if( a == b ) // ① 올바르지 않은 배열 비교 printf("잘못된 결과입니다.\n"); else
배열의 비교 for(i = 0; i < SIZE ; i++) // ② 올바른 배열 비교 원소를 하나씩 비교한다 { 원소를 하나씩 비교한다 for(i = 0; i < SIZE ; i++) // ② 올바른 배열 비교 { if ( a[i] != b[i] ) { printf("a[]와 b[]는 같지 않습니다.\n"); return 0; } } printf("a[]와 b[]는 같습니다.\n"); return 0; }
중간 점검 배열 a[6]의 원소를 1, 2, 3, 4, 5, 6으로 초기화하는 문장을 작성하라. 배열의 초기화에서 초기값이 개수가 배열 원소의 개수보다 적은 경우에는 어떻게 되는가? 또 반대로 많은 경우에는 어떻게 되는가? 배열의 크기를 주지 않고 초기값의 개수로 배열의 크기를 결정할 수 있는 가? 배열 a, b를 if(a==b)와 같이 비교할 수 있는가? 배열 a에 배열 b를 a=b;와 같이 대입할 수 있는가?
실습: 극장 예약 시스템 배열을 이용하여 간단한 극장 예약 시스템을 작성 좌석은 10개 먼저 좌석 배치표를 보여준다. 예약이 끝난 좌석은 1로, 예약이 안 된 좌석은 0으로 나타낸다.
실행 결과 좌석을 예약하시겠습니까?(y 또는 n) y ------------------------------- 1 2 3 4 5 6 7 8 9 10 0 0 0 0 0 0 0 0 0 0 몇번째 좌석을 예약하시겠습니까?1 예약되었습니다. 1 0 0 0 0 0 0 0 0 0 이미 예약된 자리입니다. 다른 좌석을 선택하세요 좌석을 예약하시겠습니까?(y 또는 n) n
알고리즘 다음을 무한히 반복한다 사용자로부터 예약 여부(y 또는 n)를 입력받는다. 만약에 입력 == 'y‘ 이면 현재의 좌석 배치표 seats[]를 출력한다. 좌석 번호 i를 사용자로부터 입력받는다. 만약에 좌석번호가 올바르면 seats[i]=1 아니면 에러 메시지를 출력한다. 종료한다.
알고리즘 while(1) 사용자로부터 예약 여부(y 또는 n)를 입력받는다. if 입력 == 'y' 현재의 좌석 배치표 seats[]를 출력한다. 좌석 번호 i를 사용자로부터 입력받는다. if 좌석번호가 올바르면 seats[i]=1 else 에러 메시지를 출력한다. 종료한다.
실습: 극장 좌석 예약 #include <stdio.h> #define SIZE 10 int main(void) { char ans1; int ans2, i; int seats[SIZE] = {0}; while(1) printf("좌석을 예약하시겠습니까?(y 또는n) "); scanf(" %c",&ans1);
실습: 극장 좌석 예약 if(ans1 == 'y') { printf("-------------------------------\n"); printf(" 1 2 3 4 5 6 7 8 9 10\n"); for(i = 0; i < SIZE; i++) printf(" %d", seats[i]); printf("\n"); printf("몇번째 좌석을 예약하시겠습니까); scanf("%d",&ans2); 현재 좌석 예약 상태 출력
실습: 극장 좌석 예약 if(ans2 <= 0 || ans2 > SIZE) { printf("1부터 10사이의 숫자를 입력하세요\n"); continue; } if(seats[ans2-1] == 0) { // 예약되지 않았으면 seats[ans2-1] = 1; printf("예약되었습니다.\n"); else // 이미 예약되었으면 printf("이미 예약된 자리입니다.\n"); else if(ans1 == 'n') return 0; 예약 성공
도전문제 위의 프로그램에서는 한명만 예약할 수 있다. 하지만 극장에 혼자서 가는 경우는 드물다. 따라서 한번에 2명을 예약할 수 있도록 위의 프로그램을 변경하여 보자.
실습: 최소값 찾기 우리는 인터넷에서 상품을 살 때, 가격 비교 사이트를 통하여 가장 싼 곳을 검색한다. 우리는 인터넷에서 상품을 살 때, 가격 비교 사이트를 통하여 가장 싼 곳을 검색한다. 일반적으로 배열에 들어 있는 정수 중에서 최소값을 찾는 문제와 같다.
실행 결과 --------------------------------------- 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 28 81 60 83 67 10 66 97 37 94 최소값은 10입니다.
알고리즘 배열 prices[]의 원소를 난수로 초기화한다. 일단 첫 번째 원소를 최소값 minium이라고 가정한다. 만약에 ( prices[i] < minimum ) 이면 minimum = prices[i] 반복이 종료되면 minimum에 최소값이 저장된다.
알고리즘 배열 prices[]의 원소를 난수로 초기화한다. 일단 첫 번째 원소를 최소값 minium이라고 가정한다. for(i=1; i<배열의 크기; i++) if ( prices[i] < minimum ) minimum = prices[i] 반복이 종료되면 minimum에 최소값이 저장된다.
실습: 최소값 찾기 #include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 10 int main(void) { int prices[SIZE] = { 0 }; int i, minimum; printf("---------------------------------------\n"); printf("1 2 3 4 5 6 7 8 9 10\n"); srand( (unsigned)time( NULL ) ); for(i = 0; i < SIZE; i++){ prices[i] = (rand()%100)+1; printf("%-3d ",prices[i]); } printf("\n\n"); 물건의 가격 출력
실습: 최소값 찾기 < < < < > > > > > minimum = prices[0]; for(i = 1; i < SIZE; i++) { if( prices[i] < minimum ) minimum = prices[i]; } printf("최소값은 %d입니다.\n", minimum); return 0; 첫 번째 배열 원소를 최소값으로 가정 현재의 최소값보다 배열 원소가 작으면, 배열 원소를 최소값으로 복사한다. grade[0] grade[1] grade[2] grade[3] grade[4] grade[5] grade[6] grade[7] grade[8] grade[9] 50 50 40 40 30 30 20 20 10 10 20 30 40 60 70 < < < < > > > > > 40 10 50 20 30 min
도전문제 위의 프로그램에서는 최소값을 계산하였다. 이번에는 배열의 원소 중에서 최대값을 찾도록 변경하여 보자. 변수 이름도 적절하게 변경하라.
실습: 투표 집계하기 투표 결과를 컴퓨터를 이용하여서 집계한다고 가정하자. 데이터의 빈도(frequency)를 계산하는 것과 동일 배열의 개념을 이용하면 손쉽게 구현할 수 있다.
실행 결과 몇번 후보자를 선택하시겠습니까?(종료 -1): 1 몇번 후보자를 선택하시겠습니까?(종료 -1): -1 값 득표결과 값 득표결과 1 2 2 0 3 0 4 0 ... 9 0 10 0
알고리즘 배열 freq[]의 원소를 0으로 초기화한다. 다음을 무한히 반복한다 freq 배열의 내용을 출력한다. 사용자로부터 후보자를 입력받아 candidate 에 저장한다. freq[candidate]++; freq 배열의 내용을 출력한다. +1 1 freq[0] freq[1] . . . . . freq[10] SIZE = 11 10 candidate
알고리즘 배열 freq[]의 원소를 0으로 초기화한다. while(1) 사용자로부터 후보자를 입력받는다. freq[candidate]++; freq 배열의 내용을 출력한다. +1 1 freq[0] freq[1] . . . . . freq[10] SIZE = 11 10 candidate
소스 #include <stdio.h> #define SIZE 11 int main(void) { int freq[SIZE] = { 0 }; // 빈도를 나타내는 배열 int i, candidate; while(1) { printf("몇번 후보자를 선택하시겠습니까?(종료-1): "); scanf("%d", &candidate); if (candidate < 0) break; //음수이면 반복종료 freq[candidate]++; } printf("값 득표결과\n"); for(i = 1; i < SIZE; i++) printf("%3d %3d \n", i, freq[i]); return 0; 해당되는 점수의 빈도를 증가한다.
도전문제 C에서는 배열의 인덱스가 항상 0부터 시작한다. 하지만 일상 생활에서는 번호가 1부터 시작한다. 여기서 발생되는 문제가 상당히 있다. 위의 프로그 램에서도 만약 배열의 크기를 10으로 한다면 어떻게 변경하여야 하는가?
배열 원소 역순 출력 (알고리즘 ) i를 0부터 SIZE-1 까지 1씩 증가 시키면서 다음을 반복한다. 사용자로부터 정수를 받아서 data[i] 에 저장한다. i를 SIZE-1 부터 0 까지 1씩 감소시키면서 다음을 반복한다. data[i] 를 출력한다.
배열 원소 역순 출력 정수를 입력하시오:10 정수를 입력하시오:20 정수를 입력하시오:30 정수를 입력하시오:40 #include <stdio.h> #define SIZE 5 int main(void) { int data[SIZE]; int i; for(i = 0; i < SIZE; i++) // 정수를 입력받는 루프 { printf("정수를 입력하시오:"); scanf("%d", &data[i]); } for(i = SIZE - 1;i >= 0; i--) // 역순으로 출력하는 루프 printf("%d\n", data[i]); return 0; } 정수를 입력하시오:10 정수를 입력하시오:20 정수를 입력하시오:30 정수를 입력하시오:40 정수를 입력하시오:50 50 40 30 20 10
성적에 비례하는 만큼 *표를 가로로 출력하는 프로그램 막대그래프 (알고리즘 ) 성적에 비례하는 만큼 *표를 가로로 출력하는 프로그램 출력할 자료 배열 grade를 초기화 한다. i를 0부터 SIZE-1 까지 1씩 증가 하면서 다음을 반복한다. i값을 출력한다. j 값을 0부터 grade[i] -1 까지 1씩 증가 하면서 다음을 반복한다. *표를 출력한다. 줄넘김을 출력한다.
막대 그래프 예제 번호 0: ****************************** #include <stdio.h> #define STUDENTS 5 int main(void) { int grade[STUDENTS] = { 30, 20, 10, 40, 50 }; int i, s; for(i = 0; i < STUDENTS; i++) { printf("번호 %d: ", i); for(s = 0; s < grade[i]; s++) printf("*"); printf("\n"); } return 0; } 번호 0: ****************************** 번호 1: ******************** 번호 2: ********** 번호 3: **************************************** 번호 4: **************************************************
사용자가 -1을 입력할 때 까지 점수를 받아들여서 각 점수의 빈도를 계산하여 출력하는 프로그램 빈도계산 (알고리즘 ) 사용자가 -1을 입력할 때 까지 점수를 받아들여서 각 점수의 빈도를 계산하여 출력하는 프로그램 빈도를 저장할 배열 freq를 초기화 한다. 다음을 무한히 반복한다. 점수를 입력 받아 score에 저장한다. score 가 -1 이면 반복을 종료한다. 아니면 freq[score] 의 값을 1 증가 시킨다. i를 0부터 SIZE-1 까지 1씩 증가하면서 다음을 반복한다. i 와 freq[i] 값을 출력한다.
빈도 계산 #include <stdio.h> #define SIZE 101 int main(void) { int freq[SIZE]; int i, score; for(i = 0; i < SIZE; i++) freq[i] = 0; while(1) { printf("숫자를 입력하시오(종료-1): "); scanf("%d", &score); if (score < 0) break; freq[score]++; }
빈도 계산 printf("값 빈도\n"); for(i = 0; i < SIZE; i++) printf("%3d %3d \n", i, freq[i]); return 0; } 숫자를 입력하시오(종료 -1): 0 숫자를 입력하시오(종료 -1): 1 숫자를 입력하시오(종료 -1): 99 숫자를 입력하시오(종료 -1): 100 숫자를 입력하시오(종료 -1): -1 값 빈도 0 1 1 1 2 0 ... 98 0 99 1 100 2
배열과 함수 배열의 경우에는 사본 이 아닌 원본이 전달 된다. int main(void) { ... 배열의 경우에는 사본 이 아닌 원본이 전달 된다. int main(void) { ... get_average( , int n); } int get_average(int score[], int n) sum += score[i]; 배열 매개 변수의 경우, 원본이 직접 참조됩니다.
배열과 함수 #include <stdio.h> #define STUDENTS 5 int get_average(int score[], int n); // ① int main(void) { int grade[STUDENTS] = { 1, 2, 3, 4, 5 }; int avg; avg = get_average(grade, STUDENTS); printf("평균은 %d입니다.\n", avg); return 0; } int get_average(int score[], int n) // ② int i; int sum = 0; for(i = 0; i < n; i++) sum += score[i]; return sum / n; 배열이 인수인 경우, 참조에 의한 호출 배열의 원본이 score[]로 전달
배열이 함수의 인수인 경우 1/2 #include <stdio.h> #define SIZE 7 void square_array(int a[], int size); void print_array(int a[], int size); int main(void) { int list[SIZE] = { 1, 2, 3, 4, 5, 6, 7 } ; print_array(list, SIZE); square_array(list, SIZE); print_array(list, SIZE); return 0; } 배열은 원본이 전달된다. (인수 : 배열)
배열이 함수의 인수인 경우 2/2 void square_array(int a[], int size) { int i; for(i = 0; i < size; i++) a[i] = a[i] * a[i]; } void print_array(int a[], int size) printf("%3d ", a[i]); printf("\n"); 배열의 원본이 a[]로 전달 1 2 3 4 5 6 7 1 4 9 16 25 36 49
원본 배열의 변경을 금지하는 방법 void print_array(const int a[], int size) { ... } 함수 안에서 a[]는 변경할 수 없다. const 키워드는 변경이 불가능하다는 것을 의미하겠죠?
중간 점검 배열을 함수로 전달하면 원본이 전달되는가? 아니면 복사본이 전달되는가? 함수가 전달받은 배열을 변경하지 못하게 하려면 어떻게 하여야 하는가?
정렬이란? 정렬은 물건을 크기순으로 오름차순이나 내림차순으로 나열하는 것 정렬은 컴퓨터 공학분야에서 가장 기본적이고 중요한 알고리즘중의 하 나
정렬이란? 정렬은 자료 탐색에 있어서 필수적이다. (예) 만약 사전에서 단어들이 정렬이 안되어 있다면?
선택정렬(selection sort) 선택정렬(selection sort): 정렬이 안된 숫자들중에서 최소값을 선택하여 배열의 첫번째 요소와 교환
선택정렬(selection sort) 선택정렬(selection sort): 정렬이 안된 숫자들중에서 최소값을 선택하여 배열의 첫번째 요소와 교환 몇 개의 단계만 살펴보자. 5 3 8 1 2 7
선택 정렬 #include <stdio.h> #define SIZE 10 int main(void) { int list[SIZE] = { 3, 2, 9, 7, 1, 4, 8, 0, 6, 5 }; int i, j, temp, least; for(i = 0; i < SIZE-1; i++) least = i; for(j = i + 1; j < SIZE; j++) if(list[j] < list[least]) least = j; temp = list[i]; list[i] = list[least]; list[least] = temp; } 내부 for 루프로서 (i+1)번째 원소부터 배열의 마지막 원소 중에서 최소값을 찾는다. 현재의 최소값과 비교하여 더 작은 정수가 발견되면 그 정수가 들어 있는 인덱스를 least에 저장한다. list[i]와 list[least]를 서로 교환
선택 정렬 for(i = 0;i < SIZE; i++) printf("%d ", list[i]); printf("\n"); return 0; } 원래의 배열 3 2 9 7 1 4 8 0 6 5 정렬된 배열 0 1 2 3 4 5 6 7 8 9
변수의 값을 서로 교환할 때 다음과 같이 하면 안됨 올바른 방법 grade[i] = grade[least]; // grade[i]의 기존값은 파괴된다! grade[least] = grade[i]; 올바른 방법 temp = list[i]; list[i] = list[least]; list[least] = temp;
순차탐색 순차 탐색은 배열의 원소를 순서대로 하나씩 꺼내서 탐색키와 비교하여 원 하는 값을 찾아가는 방법 50 10 20 30 순차 탐색은 배열의 원소를 순서대로 하나씩 꺼내서 탐색키와 비교하여 원 하는 값을 찾아가는 방법 50 성공 비교 10 20 30 40 50 10 grade[0] grade[1] grade[2] grade[3] grade[4] grade[5]
순차 탐색 #include <stdio.h> #define SIZE 10 int main(void) { int key, i; int list[SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; printf("탐색할 값을 입력하시오:"); scanf("%d", &key); for(i = 0; i < SIZE; i++) if(list[i] == key) printf("탐색 성공 인덱스= %d\n", i); printf("탐색 종료\n"); return 0; } for 루프를 이용하여 list[i]와 key를 비교하는 연산을 배열의 크기만큼 반복한다. 만약 list[i]와 key가 같으면 탐색은 성공되고 키값이 발견된 배열의 인덱스를 출력한다. 탐색할 값을 입력하시오:7 탐색 성공 인덱스 = 6 탐색 종료
이진 탐색 이진 탐색(binary search): 정렬된 배열의 중앙에 위치한 원소와 비교 되풀이
이진 탐색 #include <stdio.h> #define SIZE 16 int binary_search(int list[], int n, int key); int main(void) { int key; int grade[SIZE] = { 2,6,11,13,18,20,22,27,29,30,34,38,41,42,45,47 }; printf("탐색할 값을 입력하시오:"); scanf("%d", &key); printf("탐색 결과= %d\n", binary_search(grade, SIZE, key)); return 0; }
이진 탐색 int binary_search(int list[], int n, int key) { int low, high, middle; low = 0; high = n-1; while( low <= high ){ // 아직 숫자들이 남아있으면 printf("[%d %d]\n", low, high); // 하한과 상한을 출력한다. middle = (low + high)/2; // 중간 위치를 계산한다. if( key == list[middle] ) // 일치하면 탐색 성공 return middle; else if( key > list[middle] )// 중간 원소보다 크다면 low = middle + 1; // 새로운 값으로 low 설정 else high = middle - 1; // 새로운 값으로 high 설정 } return -1;
실행 결과 탐색할 값을 입력하시오:34 [0 15] [8 15] [8 10] [10 10] 탐색 결과= 10
2차원 배열 int s[10]; // 1차원 배열 int s[3][10]; // 2차원 배열
2차원 배열의 구현 2차원 배열은 1차원적으로 구현된다.
2차원 배열의 활용 1 2 … #include <stdio.h> int main(void) { int s[3][5]; // 2차원 배열 선언 int i, j; // 2개의 인덱스 변수 int value = 0; // 배열 원소에 저장되는 값 for(i=0;i<3;i++) for(j=0;j<5;j++) s[i][j] = value++; printf("%d\n", s[i][j]); return 0; } 1 2 …
2차원 배열의 초기화 int s[3][5] = { { 0, 1, 2, 3, 4 }, // 첫 번째 행의 원소들의 초기값 { 0, 1, 2, 3, 4 }, // 첫 번째 행의 원소들의 초기값 { 10, 11, 12, 13, 14 }, // 두 번째 행의 원소들의 초기값 { 20, 21, 22, 23, 24 } // 세 번째 행의 원소들의 초기값 };
2차원 배열의 초기화 int s[ ][5] = { { 0, 1, 2, 3, 4 }, // 첫 번째 행의 원소들의 초기값 { 0, 1, 2, 3, 4 }, // 첫 번째 행의 원소들의 초기값 { 10, 11, 12, 13, 14 }, // 두 번째 행의 원소들의 초기값 { 20, 21, 22, 23, 24 }, // 세 번째 행의 원소들의 초기값 };
2차원 배열의 초기화 int s[ ][5] = { { 0, 1, 2 }, // 첫 번째 행의 원소들의 초기값 { 0, 1, 2 }, // 첫 번째 행의 원소들의 초기값 { 10, 11, 12 }, // 두 번째 행의 원소들의 초기값 { 20, 21, 22 } // 세 번째 행의 원소들의 초기값 };
2차원 배열의 초기화 int s[ ][5] = { 0, 1, 2, 3, 4, // 첫 번째 행의 원소들의 초기값 0, 1, 2, 3, 4, // 첫 번째 행의 원소들의 초기값 5, 6, 7, 8, 9, // 두 번째 행의 원소들의 초기값 };
3차원 배열 #include <stdio.h> int main(void) { int s[3][3][3]; // 3차원 배열 선언 int x, y, z; // 3개의 인덱스 변수 int i = 1; // 배열 원소에 저장되는 값 for(z=0;z<3;z++) for(y=0;y<3;y++) for(x=0;x<3;x++) s[z][y][x] = i++; return 0; }
다차원 배열 인수 #include <stdio.h> #define YEARS 3 #define PRODUCTS 5 int sum(int grade[][PRODUCTS]); int main(void) { int sales[YEARS][PRODUCTS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; int total_sale; total_sale = sum(sales); printf("총매출은 %d입니다.\n", total_sale); return 0; }
다차원 배열 인수 int sum(int grade[][PRODUCTS]) { int y, p; int total = 0; 첫번째 인덱스의 크기는 적지 않아도 된다. int sum(int grade[][PRODUCTS]) { int y, p; int total = 0; for(y = 0; y < YEARS; y++) for(p = 0; p < PRODUCTS; p++) total += grade[y][p]; return total; } 총매출은 45입니다.
다차원 배열 예제 #include <stdio.h> #define CLASSES 3 #define STUDENTS 5 int main(void) { int s[CLASSES][STUDENTS] = { { 0, 1, 2, 3, 4 }, // 첫번째 행의 원소들의 초기값 { 10, 11, 12, 13, 14 }, // 두번째 행의 원소들의 초기값 { 20, 21, 22, 23, 24 }, // 세번째 행의 원소들의 초기값 };
다차원 배열 예제 int clas, student, total, subtotal; total = 0; for(clas = 0; clas < CLASSES; clas++) { subtotal = 0; for(student = 0; student < STUDENTS; student++) subtotal += s[clas][student]; printf("학급 %d의 평균 성적= %d\n", clas, subtotal / STUDENTS); total += subtotal; } printf("전체 학생들의 평균 성적= %d\n", total/(CLASSES * STUDENTS)); return 0; } 학급 0의 평균 성적 = 2 학급 1의 평균 성적 = 12 학급 2의 평균 성적 = 22 전체 학생들의 평균 성적 = 12
행렬 행렬(matrix)는 자연과학에서 많은 문제를 해결하는데 사용
다차원 배열을 이용한 행렬의 표현 #include <stdio.h> #define ROWS 3 #define COLS 3 int main(void) { int A[ROWS][COLS] = { { 2,3,0 }, { 8,9,1 }, { 7,0,5 } }; int B[ROWS][COLS] = { { 1,0,0 }, { 1,0,0 }, { 1,0,0 } }; int C[ROWS][COLS];
다차원 배열을 이용한 행렬의 표현 int r,c; // 두개의 행렬을 더한다. // 두개의 행렬을 더한다. for(r = 0;r < ROWS; r++) for(c = 0;c < COLS; c++) C[r][c] = A[r][c] + B[r][c]; // 행렬을 출력한다. { printf("%d ", C[r][c]); printf("\n"); } return 0; } 중첩 for 루프를 이용하여 행렬 A의 각 원소들과 행렬의 B의 각 원소들을 서로 더하여 행렬 C에 대입한다. 3 3 0 9 9 1 8 0 5
중간 점검 다차원 배열 int a[3][2][10]에는 몇개의 원소가 존재하는가?
실습: tic-tac-toe tic-tac-toe 게임은 2명의 경기자가 오른쪽과 같은 보드를 이용하여서 번갈 아가며 O와 X를 놓는 게임이다. 같은 글자가 가로, 세로, 혹은 대각선 상에 놓이면 이기게 된다.
실행 결과 (x, y) 좌표(종료 -1, -1): 0 0 ---|---|--- X | | | | | | (x, y) 좌표(종료 -1, -1): 1 1 | O | ...
알고리즘 보드를 초기화한다. 다음을 무한히 반복한다. 보드를 화면에 출력한다. 사용자로부터 좌표 x, y를 받는다. 반복을 종료한다. 만약에 board[x][y]가 비어 있으면 만약에 현재 경기자가 ‘X’이면 board[x][y] = ‘X’ 아니면 board[x][y] = ‘O’ 오류 메시지를 출력한다 반복을 종료한다
알고리즘 보드를 초기화한다. while(1) 보드를 화면에 출력한다. 사용자로부터 좌표 x, y를 받는다. if (board[x][y]가 비어 있으면) if( 현재 경기자가 ‘X’이면 ) board[x][y] = ‘X’ else board[x][y] = ‘O’ 오류 메시지를 출력한다
소스 #include <stdio.h> #include <stdlib.h> void init_board(char board[][3]); int get_player_move(int palyer, char board[][3]); void disp_board(char board[][3]); int main(void) { char board[3][3]; int quit=0; init_board(board); do { disp_board(board); quit = get_player_move(0, board); quit = get_player_move(1, board); } while(quit == 0); return 0; }
소스 void init_board(char board[][3]) { int x, y; for(x=0; x<3; x++) for(y=0; y<3; y++) board[x][y] = ' '; } void disp_board(char board[3][3]) { int i; for(i=0; i<3; i++){ printf("---|---|---\n"); printf(" %c | %c | %c \n",board[i][0], board[i][1], board [i][2]);
소스 int get_player_move(int player, char board[3][3]) { int x, y, done = 0; while(done != 1) { printf("(x, y) 좌표(종료-1, -1): "); scanf("%d %d", &x, &y); if( x == -1 && y == -1 ) return 1; if(board[x][y]== ' ') break; else printf("잘못된 위치입니다.\n"); } } if( player == 0 ) board[x][y] = 'X'; else board[x][y] = 'O'; return 0;
실행 결과 (x, y) 좌표(종료 -1, -1): 0 0 ---|---|--- X | | | | | | (x, y) 좌표(종료 -1, -1): 1 1 | O | ...
도전문제 보드를 분석하여서 게임이 종료되었는지를 검사하는 함수를 추가하라. 컴퓨터가 다음 수를 결정하도록 프로그램을 변경하라. 가장 간단한 알고리 즘을 사용한다. 예를 들면 비어 있는 첫 번째 좌표에 놓는다.
Q & A
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express
이번 장에서 학습할 내용 이번 장에서는 포인터의 기초적인 지식을 학습한다. 포인터이란? 변수의 주소 포인터의 선언 간접 참조 연산자 포인터 연산 포인터와 배열 포인터와 함수
포인터란? 포인터(pointer): 주소를 가지고 있는 변수 1004 1005 1003 1006 1002 1001 1007 영화관 1003 1006 1002 1001 포인터(pointer) 1007
메모리의 구조 변수는 메모리에 저장된다. 메모리는 바이트 단위로 액세스된다. 첫번째 바이트의 주소는 0, 두번째 바이트는 1,…
변수와 메모리 변수의 크기에 따라서 차지하는 메모리 공간이 달라진다. char형 변수: 1바이트, int형 변수: 4바이트,… int main(void) { int i = 10; char c = 69; float f = 12.3; }
변수의 주소 변수의 주소를 계산하는 연산자: & 변수 i의 주소: &i
변수의 주소 int main(void) { int i = 10; char c = 69; float f = 12.3; printf("i의 주소: %u\n", &i); // 변수 i의 주소 출력 printf("c의 주소: %u\n", &c); // 변수 c의 주소 출력 printf("f의 주소: %u\n", &f); // 변수 f의 주소 출력 return 0; } i의 주소: 1245024 c의 주소: 1245015 f의 주소: 1245000
포인터의 선언 포인터: 변수의 주소를 가지고 있는 변수 *p가 가리키는 내용은 정수가 된다.
포인터와 변수의 연결 int i = 10; // 정수형 변수 i 선언 int *p; // 포인터 변수 p 선언 p = &i; // 변수 i의 주소가 포인터 p로 대입
다양한 포인터의 선언 char c = 'A'; // 문자형 변수 c float f = 36.5; // 실수형 변수 f double d = 3.141592; // 실수형 변수 d char *pc = &c; // 문자를 가리키는 포인터 pc float *pf = &f; // 실수를 가리키는 포인터 pf double *pd = &d; // 실수를 가리키는 포인터 pd
간접 참조 연산자 간접 참조 연산자 *: 포인터가 가리키는 값을 가져오는 연산자 int i=10; int *p; p =&i; printf(“%d”, *p):
간접 참조 연산자의 해석 간접 참조 연산자: 지정된 위치에서 포인터의 타입에 따라 값을 읽어 들인 다. 간접 참조 연산자: 지정된 위치에서 포인터의 타입에 따라 값을 읽어 들인 다. int *p = 8; // 위치 8에서 정수를 읽는다. char *pc = 8; // 위치 8에서 문자를 읽는다. double *pd = 8; // 위치 8에서 실수를 읽는다.
& 연산자와 * 연산자 & 연산자: 변수의 주소를 반환한다 * 연산자: 포인터가 가리키는 곳의 내용을 반환한다.
i 포인터 예제 #1 p #include <stdio.h> int main(void) 3000 { int i = 3000; int *p = &i; // 변수와 포인터 연결 printf("&i = %u\n", &i); // 변수의 주소 출력 printf("i = %d\n", i); // 변수의 값 출력 printf("*p = %d\n", *p); // 포인터를 통한 간접 참조 값 출력 printf("p = %u\n", p); // 포인터의 값 출력 return 0; } 3000 i p &i = 1245024 i = 3000 *p = 3000 p = 1245024
포인터 예제 #2 x y p #include <stdio.h> int main(void) { int x=10, y=20; int *p; p = &x; printf("p = %d\n", p); printf("*p = %d\n\n", *p); p = &y; printf("*p = %d\n", *p); return 0; } 20 y p 10 x p = 1245052 *p = 10 p = 1245048 *p = 20
포인터 예제 #3 i p 포인터를 통하여 변수의 값을 변경한다. #include <stdio.h> int main(void) { int i=10; int *p; p = &i; printf("i = %d\n", i); *p = 20; return 0; } p 10 i 포인터를 통하여 변수의 값을 변경한다. i = 10 i = 20
중간 점검 메모리는 어떤 단위를 기준으로 주소가 매겨지는가? 다음의 각 자료형이 차지하는 메모리 공간의 크기를 쓰시오. (a) char (b) short (c) int (d) long (e) float (f) double 포인터도 변수인가? 변수의 주소를 추출하는데 사용되는 연산자는 무엇인가? 변수 x의 주소를 추출하여 변수 p에 대입하는 문장을 쓰시오. 정수형 포인터 p가 가리키는 위치에 25를 저장하는 문장을 쓰시오.
p 포인터 사용시 주의점 초기화가 안된 포인터를 사용하면 안된다. int main(void) { int *p; // 포인터 p는 초기화가 안되어 있음 *p = 100; // 위험한 코드 return 0; } 주소가 잘못된것 같은데… p
포인터 사용시 주의점 포인터가 아무것도 가리키고 있지 않는 경우에는 NULL로 초기화 포인터의 유효성 여부 판단이 쉽다.
포인터 사용시 주의점 포인터의 타입과 변수의 타입은 일치하여야 한다. #include <stdio.h> int main(void) { int i; double *pd; pd = &i; // 오류! double형 포인터에 int형 변수의 주소를 대입 *pd = 36.5; return 0; }
중간 점검 초기값이 결정되지 않은 포인터에는 어떤 값을 넣어두는 것이 안전한가? char형 변수에 double형 포인터로 값을 저장한다면 어떤 문제가 발생하는 가?
p++ 포인터 연산 가능한 연산: 증가, 감소, 덧셈, 뺄셈 연산 증가 연산의 경우 증가되는 값은 포인터가 가리키는 객체의 크기 포인터 타입 ++연산후 증가되는값 char 1 short 2 int 4 float double 8 포인터의 증가는 일반 변수와는 약간 다릅니다. 가리키는 객체의 크기만큼 증가합니다. p++
증가 연산 예제 #include <stdio.h> int main(void) { char *pc; int *pi; double *pd; pc = (char *)10000; pi = (int *)10000; pd = (double *)10000; printf("증가 전 pc = %d, pi = %d, pd = %d\n", pc, pi, pd); pc++; pi++; pd++; printf("증가 후 pc = %d, pi = %d, pd = %d\n", pc, pi, pd); return 0; } 증가 전 pc = 10000, pi = 10000, pd = 10000 증가 후 pc = 10001, pi = 10004, pd = 10008
포인터의 증감 연산
간접 참조 연산자와 증감 연산자 *p++; (*p)++; p가 가리키는 위치에서 값을 가져온 후에 p를 증가한다. 수식 의미 v = *p++ p가 가리키는 값을 v에 대입한 후에 p를 증가한다. v = (*p)++ p가 가리키는 값을 v에 대입한 후에 가리키는 값을 증가한다. v = *++p p를 증가시킨 후에 p가 가리키는 값을 v에 대입한다. v = ++*p p가 가리키는 값을 가져온 후에 그 값을 증가하여 v에 대입한다.
간접 참조 연산자와 증감 연산자 #include <stdio.h> int main(void) { int i = 10; int *pi = &i; printf("i = %d, pi = %p\n", i, pi); (*pi)++; *pi++; return 0; } pi가 가리키는 위치의 값을 증가한다. pi가 가리키는 위치에서 값을 가져온 후에 pi를 증가한다. i = 10, pi = 0012FF60 i = 11, pi = 0012FF60 i = 11, pi = 0012FF64
포인터의 형변환 C언어에서는 꼭 필요한 경우에, 명시적으로 포인터의 타입을 변경할수 있 다. double *pd = &f; int *pi; pi = (int *)pd;
간접 참조 연산자와 증감 연산자 3.140000 123 456 #include <stdio.h> int main(void) { char buffer[8]; double *pd; int *pi; pd = (double *)buffer; *pd = 3.14; printf("%f\n", *pd); pi = (int *)buffer; *pi = 123; *(pi+1) = 456; printf("%d %d\n", *pi, *(pi+1)); return 0; } char형 포인터를 double형 포인터로 변환, 배열의 이름은 char형 포인터이다. char형 포인터를 int형 포인터로 변환 3.140000 123 456
중간 점검 포인터에 대하여 적용할 수 있는 연산에는 어떤 것들이 있는가? int형 포인터 p가 80번지를 가리키고 있었다면 (p+1)은 몇 번지를 가리키 는가? p가 포인터라고 하면 *p++와 (*p)++의 차이점은 무엇인가? p가 포인터라고 하면 *(p+3)의 의미는 무엇인가?
포인터와 배열 배열과 포인터는 아주 밀접한 관계를 가지고 있다. 배열 이름이 바로 포인터이다. 포인터는 배열처럼 사용이 가능하다. a 배열 [0] [1] [2] [3] [4] [5] [6] [7] [8] 배열 포인터 p 포인터
포인터와 배열 // 포인터와 배열의 관계 #include <stdio.h> int main(void) { int a[] = { 10, 20, 30, 40, 50 }; printf("&a[0] = %u\n", &a[0]); printf("&a[1] = %u\n", &a[1]); printf("&a[2] = %u\n", &a[2]); printf("a = %u\n", a); return 0; } &a[0] = 1245008 &a[1] = 1245012 &a[2] = 1245016 a = 1245008
포인터와 배열 // 포인터와 배열의 관계 #include <stdio.h> int main(void) { int a[] = { 10, 20, 30, 40, 50 }; printf("a = %u\n", a); printf("a + 1 = %u\n", a + 1); printf("*a = %d\n", *a); printf("*(a+1) = %d\n", *(a+1)); return 0; } a = 1245008 a + 1 = 1245012 *a = 10 *(a+1) = 20
포인터와 배열 포인터는 배열처럼 사용할 수 있다. 인덱스 표기법을 포인터에 사용할 수 있다.
포인터를 배열처럼 사용 #include <stdio.h> int main(void) { int a[] = { 10, 20, 30, 40, 50 }; int *p; p = a; printf("a[0]=%d a[1]=%d a[2]=%d \n", a[0], a[1], a[2]); printf("p[0]=%d p[1]=%d p[2]=%d \n\n", p[0], p[1], p[2]); p[0] = 60; p[1] = 70; p[2] = 80; printf("p[0]=%d p[1]=%d p[2]=%d \n", p[0], p[1], p[2]); return 0; } 배열은 결국 포인터로 구현된다는 것을 알 수 있다. 포인터을 통하여 배열원소를 변경할 수 있다. a[0]=10 a[1]=20 a[2]=30 p[0]=10 p[1]=20 p[2]=30 a[0]=60 a[1]=70 a[2]=80 p[0]=60 p[1]=70 p[2]=80
포인터를 사용한 방법의 장점 포인터가 인덱스 표기법보다 빠르다. 포인터 사용 인덱스 표기법 사용 Why?: 인덱스를 주소로 변환할 필요가 없다. int get_sum1(int a[], int n) { int i; int sum = 0; for(i = 0; i < n; i++ ) sum += a[i]; return sum; } int get_sum2(int a[], int n) { int i, sum =0; int *p; p = a; for(i = 0; i < n; i++ ) sum += *p++; return sum; } 인덱스 표기법 사용 포인터 사용
실습: 영상 처리 디지털 이미지는 배열을 사용하여서 저장된다. 이미지 처리를 할 때 속도를 빠르게 하기 위하여 포인터를 사용한다. 이미지 내의 모든 픽셀의 값을 10씩 증가시켜보자.
실행 결과 010 020 030 040 050 020 030 040 050 060 모든 픽셀의 값이 10씩 증가되었다.
실습: 영상 처리 #include <stdio.h> #define SIZE 5 void print_image(int image[][SIZE]) { int r,c; for(r=0;r<SIZE;r++){ for(c=0;c<SIZE;c++){ printf("%03d ", image[r][c]); } printf("\n");
실습: 영상 처리 void brighten_image(int image[][SIZE]) { int r,c; int *p; p = &image[0][0]; for(r=0;r<SIZE;r++){ for(c=0;c<SIZE;c++){ *p += 10; p++; }
실습: 영상 처리 int main(void) { int image[5][5] = { { 10, 20, 30, 40, 50}, { 10, 20, 30, 40, 50}}; print_image(image); brighten_image(image); return 0; }
도전문제 포인터를 이용하지 않는 버전도 작성하여 보자. 즉 배열의 인덱스 표기법 으로 위의 프로그램을 변환하여 보자.
배열의 원소를 역순으로 출력 #include <stdio.h> void print_reverse(int a[], int n); int main(void) { int a[] = { 10, 20, 30, 40, 50 }; print_reverse(a, 5); return 0; } void print_reverse(int a[], int n) int *p = a + n - 1; // 마지막 노드를 가리킨다. while(p >= a) // 첫번째 노드까지 반복 printf("%d\n", *p--); // p가 가리키는 위치를 출력하고 감소 50 40 30 20 10
중간 점검 배열의 첫 번째 원소의 주소를 계산하는 2가지 방법을 설명하라. 배열 a[]에서 *a의 의미는 무엇인가? 배열의 이름에 다른 변수의 주소를 대입할 수 있는가? 포인터를 이용하여 배열의 원소들을 참조할 수 있는가? 포인터를 배열의 이름처럼 사용할 수 있는가?
인수 전달 방법 함수 호출 시에 인수 전달 방법 값에 의한 호출(call by value) 참조에 의한 호출(call by reference) C에서는 포인터를 이용하여 흉내 낼 수 있다.
값에 의한 호출 함수 호출시에 변수의 값을 함수에 전달
참조에 의한 호출 함수 호출시에 변수의 주소를 함수의 매개 변수로 전달
swap() 함수 #1 100 100 200 100 200 200 100 <main> <swap> 변수 2개의 값을 바꾸는 작업을 함수로 작성 #include <stdio.h> void swap(int x, int y); int main(void) { int a = 100, b = 200; swap(a, b); return 0; } void swap(int x, int y) { int tmp; tmp = x; x = y; y = tmp; } 함수 호출시에 값만 복사된다. 100 100 200 a x 100 tmp 200 200 100 b y <main> <swap>
swap() 함수 #2 100 200 &a 100 100 &b 200 <main> <swap> 포인터를 이용 #include <stdio.h> void swap(int x, int y); int main(void) { int a = 100, b = 200; swap(&a, &b); return 0; } void swap(int *px, int *py) { int tmp; tmp = *px; *px = *py; *py = tmp; } 함수 호출시에 주소가 복사된다. 100 200 &a a px 100 tmp 100 &b 200 b py <main> <swap>
scanf() 함수 변수에 값을 저장하기 위하여 변수의 주소를 받는다.
2개 이상의 결과를 반환 #include <stdio.h> // 기울기와 y절편을계산 int get_line_parameter(int x1, int y1, int x2, int y2, float *slope, float *yintercept) { if( x1 == x2 ) return -1; else { *slope = (float)(y2 - y1)/(float)(x2 - x1); *yintercept = y1 - (*slope)*x1; return 0; } int main(void) float s, y; if( get_line_parameter(3,3,6,6,&s,&y) == -1 ) printf("에러\n"); else printf("기울기는 %f, y절편은 %f\n", s, y); 기울기와 Y절편을 인수로 전달 기울기는 1.000000, y절편은 0.000000
배열 매개 변수 일반 매개 변수 vs 배열 매개 변수 Why? -> 배열을 함수로 복사하려면 많은 시간 소모 // 매개 변수 x에 기억 장소가 할당 void sub(int x) { ... } // b에 기억 장소가 할당되지 않는다. void sub( int b[] ) { ... }
배열 매개 변수
4 1 5 2 3 6 예제 #include <stdio.h> void sub(int b[], int n); int main(void) { int a[3] = { 1,2,3 }; printf("%d %d %d\n", a[0], a[1], a[2]); sub(a, 3); return 0; } void sub(int b[], int n) b[0] = 4; b[1] = 5; b[2] = 6; 4 1 5 2 3 6 a[0] a[1] a[2] 1 2 3 4 5 6
포인터를 반환할 때 주의점 함수가 종료되더라도 남아 있는 변수의 주소를 반환하여야 한다. 지역 변수의 주소를 반환하면 , 함수가 종료되면 사라지기 때문에 오류 int *add(int x, int y) { int result; result = x + y; return &result; } 지역변수 result는 함수가 종료되면 소멸되므로 그 주소를 반환하면 안된다!
중간 점검 함수에 매개 변수로 변수의 복사본이 전달되는 것을 ____________라고 한다. 함수에 매개 변수로 변수의 원본이 전달되는 것을 ____________라고 한다. 배열을 함수의 매개 변수로 지정하는 경우, 배열의 복사가 일어나는가?
포인터 사용의 장점 연결 리스트나 이진 트리 등의 향상된 자료 구조를 만들 수 있다. 참조에 의한 호출 동적 메모리 할당 포인터를 매개 변수로 이용하여 함수 외부의 변수의 값을 변경할 수 있다. 동적 메모리 할당 17장에서 다룬다.
Q & A