280 likes | 489 Views
10.5 포인터와 함수 p.475. 함수 간 인수 전달과 포인터 값에 의한 호출 함수는 자신을 호출한 함수의 변수를 참조하여 수정할 수 없다 . 주소에 의한 호출 포인터를 이용 자신을 호출한 함수의 변수를 간접적으로 참조하여 수정 가능 → 포인터의 필요성 , 유용성 , 강력함 ‘ 주소에 의한 호출 ’ 인수 전달 방식 호출 함수 : 인수의 주소를 전달 피호출 함수 : 전달된 주소를 포인터 매개변수에 저장 → 포인터를 통해 인수를 간접적으로 참조하여 수정 가능.
E N D
10.5 포인터와 함수 p.475 • 함수 간 인수 전달과 포인터 • 값에 의한 호출 함수는 자신을 호출한 함수의 변수를 참조하여 수정할 수 없다. • 주소에 의한 호출 포인터를 이용 자신을 호출한 함수의 변수를 간접적으로 참조하여 수정 가능→포인터의 필요성, 유용성, 강력함 • ‘주소에 의한 호출’ 인수 전달 방식 • 호출 함수: 인수의 주소를 전달 • 피호출 함수: 전달된 주소를 포인터 매개변수에 저장→ 포인터를 통해 인수를 간접적으로 참조하여 수정 가능
10.5.1 포인터를 이용한 주소에 의한 호출 p.475 • 주소에 의한 호출 인수 전달 형식 함수 호출 • 함수명 ( &인수명 ); 함수 정의 인수의 주소가 전달되어 저장됨 → 포인터는 자신을 호출한 함수의 인수를 가리키게 됨 • 반환값형함수명(자료형*포인터변수명) • { ‘*포인터변수명’으로 인수를 참조 }
10-7 값에 의한 호출과 주소에 의한 호출 비교 p.476 6 int main() 7 { 8 int x = 100, y = 200; 9 12 swap_value(x, y); // 값에 의한 호출: x와 y의 값을 전달 13 printf("In main: x=%d, y=%d (swap_value(x, y) 호출 후)\n\n", x, y); : 19 } • 22 void swap_value(int x, int y) • 23 { • 24 int temp; • 25 • 26 temp = x; • 27 x = y; • 28 y = temp; • 29 printf("In swap_value: x=%d, y=%d \n", x, y); • 30 }
10-7 값에 의한 호출과 주소에 의한 호출 비교 p.476 4 void swap_address(int *x, int *y); // 주소에 의한 호출 방식 6 int main() 7 { 8 int x = 100, y = 200; 15 swap_address(&x, &y); // 주소에 의한 호출: x와 y의 주소를 전달 16 printf("In main: x=%d, y=%d (swap_address(&x, &y) 호출 후)\n\n", x, y); 17 19 } • 33 void swap_address(int *x, int *y) // x, y를 포인터 변수로 선언 • 34 { • 35 int temp; // 임시 대피 장소 • 37 temp = *x; // x가 가리키는 곳의 값을 temp에 대입 • 38 *x = *y; // y가 가리키는 곳의 값을 x가 가리키는 곳에 대입 • 39 *y = temp; // temp의 값을 y가 가리키는 곳에 대입 • 40 printf("In swap_address: *x=%d, *y=%d \n", *x, *y); • 41 }
10.5.2 배열을 함수의 매개변수로 사용하는 경우 p.479 • 함수간 배열 전달: 포인터 이용 • 함수 정의시 배열을 선언하는 방법은 p.349 8.11.2에서 소개 • 포인터를 이용하는 방법: 배열 원소 자료형에 맞는 포인터 매개변수 선언 함수 호출 • 함수명 ( 배열명); 함수 정의 • 반환값형함수명(자료형*포인터변수명) • { • ‘*(포인터변수명+첨자)’ 또는 ‘포인터변수명[첨자]’로 배열원소 참조 } 배열의 시작 주소가 전달되어 저장됨 → 포인터는 자신을 호출한 함수의 배열 시작 위치를 가리키게 됨
10.5.2 배열을 함수의 매개변수로 사용하는 경우 p.479 • [프로그램 8-15] 인기도조사 결과를 백분율로 변경하기→[프로그램 10-8] 포인터를 사용해 변경하기 1 #include <stdio.h> 2 #define N 4 3 4 void print_arr(int *arr); // void print_arr(intarr[N]); 5 void percentage(int *arr); // void percentage(intarr[N]); 6
10-8 배열을 포인터로 전달받아 처리하기 p.489 7 int main() 8 { 9 intcount[N] = {42, 37, 83, 33}; 10 11 printf("인원수: "); 12 print_arr(count); 13 14 percentage(count); : 19 return 0; 20 } int main() void print_arr(int *arr) arr count 1310576 42 37 83 33 • 22 void print_arr( int*arr) • 23 { • 24 inti; • 26 for (i=0; i<N; i++) • 27 printf("%3d", *(arr + i)); • 28 }
10.6.1 다양한 정렬 알고리즘 p.483 • 정렬(sort 혹은 sorting) • 순서 없이 나열된 값들을 특정 순서대로 나열하는 것 • 오름차순 정렬 / 내림차순 정렬
10.6.1 다양한 정렬 알고리즘: 교환 정렬 p.484 첫 원소에 정렬 완료 상태의 값이 오게 함 → 나머지 모든 원소에 대해서도 차례대로 정렬 완료 상태의 값이 오게 함 ① a[0]과 a[1]을정렬 • 교환 발생 ② a[0]과 a[2]를정렬 • 교환 발생 ③ a[0]과 a[3]를 정렬 • 교환 발생 ④a[0]과 a[4]를 정렬 • → [그림 10-18]과 같은 방식으로a[i]와 ~ a[i+1]~a[SIZE-1]을 비교하여 정렬하는 과정을 i가 0일 때부터 3까지 반복하면 정렬이 완료됨 a[0]에 제일 작은 값 저장
10.6.1 다양한 정렬 알고리즘: 선택 정렬 p.485 교환 정렬과 비슷하나 두 원소 간의 교환 횟수를 줄이기 위해 a[i] 자리에 와야 할 원소(a[index])를 선택(selection)한 후 a[i]와 a[index]를 교환 • a[i]에 i+1번째로 작은 값을 선택하여 저장하는 과정 선택정렬 알고리즘 for (i=0; i<SIZE-1; i++) { index ←a[i]~a[SIZE-1] 중최솟값의 배열 첨자 a[i]와 a[index]를교환하기 } i가 0일 때: a[0]과 a[0]~a[4] 중최솟값과 교환 • 교환 발생 i가 1일 때: a[1]과 a[1]~a[4] 중최솟값과 교환 • 교환 발생 i가 2일 때: a[2]와 a[2]~a[4] 중최솟값과 교환 • 교환 발생 a[3]과a[3]~a[4] 중최솟값과 교환 i가 3일 때: • 교환 발생
10.6.1 다양한 정렬 알고리즘: 삽입 정렬 p.486 • 삽입 정렬 배열을 정렬 부분과 미정렬부분으로 나눈 후미정렬 부분의 첫 원소를 정렬된 부분 중 정확한 자리에 삽입하는 과정을 반복 • for (i=1; i<SIZE; i++) • 정렬된 a[0]~a[i-1] 중 a[i]가 삽입될 정확한 자리를 찾아서 삽입; 정렬되지 않은 부분 정렬된 부분 i가 1 → 정렬된 a[0]~a[0] 중 a[1]이 들어갈 자리를 찾아서 삽입 i가 2 → 정렬된 a[0]~a[1] 중 a[2]가 들어갈 자리를 찾아서 삽입 i가 3 → 정렬된 a[0]~a[2] 중 a[3]이 들어갈 자리를 찾아서 삽입 i가 4 → 정렬된 a[0]~a[3] 중 a[4]가 들어갈 자리를 찾아서 삽입 a[4]를 a[2]자리에삽입 → 정렬
그림 10-20 삽입 정렬 과정 p.487 진한테두리 부분은 정렬된 부분 ② a[1]을 a[0] 자리에 끼워넣기 i가 1일 때: a[1]을 a[0] 앞에 넣어야 오름차순이 되므로 a[1]이 삽입될 자리는 a[0]이다. a[0]의 5를 a[1] 자리로 이동하고(①) 대피해 둔 a[1]의 4는 a[0]에 저장한다(②). ① 한 칸 뒤로 밀기 i가 2일 때: a[2]가 정렬된 a[0]~a[1] 중에 들어갈 자리는 a[0]이므로 a[0] 자리에 삽입한다. 이때 a[0]~a[1]은 한 칸씩 뒤로 밀어서 먼저 이동해야 한다. ② a[2]를 a[0] 자리에 끼워넣기 ① 한 칸 뒤로 밀기 i가 3일 때: a[3]가 정렬된 a[0]~a[2] 중에 들어갈 자리는 a[0]이므로 a[0] 자리에 삽입한다. 이때 a[0]~a[2]는 한 칸씩 뒤로 밀어서 먼저 이동해야 한다. ② a[3]을a[0] 자리에 끼워넣기 ① 한 칸 뒤로 밀기 a[4]가 정렬된 a[0]~a[3] 중에 들어갈 자리는 a[2]이므로 a[2] 자리에 삽입한다. 이때 a[2]~a[3]은 한 칸씩 뒤로 밀어서 먼저 이동해야 한다. i가 4일 때: ② a[4]를 a[2] 자리에 끼워넣기 ① 뒤로 밀기
10.7 포인터와 문자열 p.491 • char형 포인터를 이용한 문자열 처리 • char형 포인터 변수에 문자열의 시작 주소를 저장하여 포인터가 문자열을 가리키게 함 포인터를 이용한 다양한 처리가 가능 char str1[10] = "language“; 문자열 바로 뒤에 문자열 끝을 나타내는 널문자가 저장 배열명str1 포인터 변수 str2 char *str2 = "language“; • (문자열 길이 + 1)개의 문자를 저장할 수 있는 공간이 할당 • 문자열 끝을 나타내는 널문자가 저장됨 • str2에 문자열 시작 주소가 저장됨 문자열 시작주소
10.7 포인터와 문자열 p.492 • 표 10-3 char형 배열과 포인터를 이용한 문자열 처리의 비교 『주의』
10.7 포인터와 문자열 p.492 • [표 10-3]에서의 『주의』 • char형 포인터는 문자열 저장용 기억공간을 동적으로 할당(11.7절 소개)받지 않은 채 문자열 입력을 시도하면 프로그램 실행이 중단됨 • str1은 배열 시작 주소인 포인터 상수→ str1=“program”으로 수정 불가 • 비교) str2는 포인터 변수이므로 주소 대입이 가능 • str2 = str1; • str2 = “언어”; ㈜ str2가 가리키는 문자열 “language”를 직접 “언어”로 수정하는 것이 아니라 새 문자열 “언어”의 시작 주소가 str2에 대입됨 “language” str2 “언어”
10.7 포인터와 문자열 p.493 • 표 10-4 문자열과 관련된 대표적인 함수(strcmp, strcpy가 중요)
10.7 포인터와 문자열 p.493 • char형 포인터 교환 vs. char형 배열 내용의 직접 교환 • [프로그램 10-10] : char형 포인터의 교환으로 두 문자열을 교환 • [프로그램 10-11]: char형 배열의 내용을 직접 교환하여 두 문자열을 교환 • 두 문자열의 길이가 길수록 문자열 복사로 인한 낭비 문자열을 임시로 대피하는 데 필요한 저장소 낭비 포인터 교환이 효율적
10-10 포인터 변수의 교환으로 두 문자열을 교환하기 p.494 1 #include <stdio.h> 2 3 int main() 4 { 5 char *first = "GilDong", *last = "Hong"; // 이름과 성 6 char *temp; // 문자열 주소를 임시로 저장할 포인터 변수 7 8 printf("Name: %s %s\n", first, last);
10-10 포인터 변수의 교환으로 두 문자열을 교환하기 p.494 10 // 포인터 변수에 저장된 두 주소를 교환해 두 포인터가 가리키는 문자열 교환하기 11 temp = first; 12 first = last; 13 last = temp; 14 15 printf("Name: %s %s\n", first, last); 16 17 return 0; 18 }
10-11 char형 배열을 이용한 두 문자열의 교환 p.495 1 #include <stdio.h> 2 #include <string.h> // strcpy 함수를 위한 헤더 파일 3 4 int main() 5 { 6 char first[10] = "GilDong", last[10] = "Hong"; // 이름과 성 7 char temp[10]; // 문자열을 임시로 저장할 배열 8 9 printf("Name: %s %s\n", first, last); first last temp
10-11 char형 배열을 이용한 두 문자열의 교환 p.495 11 // 배열의 내용을 직접 교환하여 두 문자열을 교환하기 12 strcpy(temp, first); // first 배열의 문자열을 temp 배열에 복사하기 13 strcpy(first, last); // last 배열의 문자열을 first 배열에 복사하기 14 strcpy(last, temp); // temp 배열의 문자열을 last 배열에 복사하기 15 16 printf("Name: %s %s\n", first, last); 17 18 return 0; 19 } first last temp
10.8.2 char형 포인터 배열을 이용한 문자열 처리 배열 원소가 char형 포인터임을 의미 • char형 2차원 배열을 이용한 여러 문자열 처리의 문제점 char flower[5][10] = {"rose", "sunflower", "lily", "lavender", "cosmos"}; • [그림 10-27] char형 포인터 배열을 이용한 여러 문자열 처리 char * flower[5] = {"rose", "sunflower", "lily", "lavender", "cosmos"}; flower 10.7 슬라이드 외 내용 ~10.8까지생략 r o s e \0 s u n f l o w e r \0 l i l y \0 l a v e n d e r \0 • for (i=0; i<5; i++) • printf("%s\n", flower[i]); // *(flower+i)와동일 c o s m o s \0 flower[0] flower[1] flower[2] flower[3] flower[4]
10 → 123의 10진수를 문자열로 변환 2 → 123의 2진수를 문자열로 변환 10.9.1 프로그램 변수명과 값을 포함한 파일명 만들기 p.502 보관용 • [프로그램 10-16] for문에서 사용된 칼슘(Ca)의 양과 나트륨(Na)의 양을 파일명에 직접 포함하는 문자열 f_name을 만들기 → 파일명 문자열을 만드는 데 응용 가능 • itoa함수 • 정수를 문자열로 변환하여 string에 저장하는 함수 • #include <stdlib.h>가 필요 • strcat함수 • strcat(s1, s2): s1 문자열 뒤에 s2 문자열을 붙인 후 s1의 시작 주소를 반환 • strcat(s1, s2)→ s1은“start”, s2는 “end”라면 s1이 “startend"가 됨 문자열로 변환할 정수 첫 인수 123을 “123” 문자열로 변환한 결과를 저장할 곳 itoa( 123, string, 10 )
10-14 변수명과 변수의 값을 포함한 문자열 만들기 p.503 1 #include <stdio.h> 2 #include <string.h> // strcmp, strcpy함수를 위한 헤더 파일 3 #include <stdlib.h> // itoa함수를 위한 헤더 파일 4 5 int main() 6 { 7 char f_name[20], temp[10]; // 파일명을 저장할 배열, 임시 문자열 배열 8 intCa, Na; 9 10 for (Ca=10; Ca<=20; Ca+=10) 11 for (Na=1; Na<=3; Na++) 12 { 13 strcpy(f_name, "file"); // 파일명에 "file"을 저장 14 15 strcat(f_name, "_Ca_"); // 파일명에 "_Ca_"를 연결 16 strcat(f_name, itoa(Ca, temp, 10)); // 파일명에 Ca의 값을 연결 17 18 strcat(f_name, "_Na_"); // 파일명에 "_Na_"를 연결 19 strcat(f_name, itoa(Na, temp, 10)); // 파일명에 Na의 값을 연결 20 21 printf("Ca=%d, Na=%d일 때 파일명 : %s \n", Ca, Na, f_name); 22 } 23 24 return 0; 25 }
10.9.1 프로그램 변수명과 값을 포함한 파일명 만들기 p.504 Ca가 10, Na가 1 일 때 char f_name[20] strcpy(f_name, "file"); “file” strcat(f_name, "_Ca_"); “file_Ca_” char temp[10] strcat(f_name, itoa(Ca, temp, 10)); itoa(Ca, temp, 10) 결과 “file_Ca_10” “10” strcat(f_name, "_Na_"); “file_Ca_10_Na_” itoa(Na, temp, 10) 결과 “1” strcat(f_name, itoa(Na, temp, 10)); “file_Ca_10_Na_1” • 프로그램 설명 처음 13~19행 실행 결과
10.9.2 문자열 정렬 p.504 • char형 2차원 배열과 char형 포인터 배열의 차이 이해하기 • 문제: 5명의 이름을 가나다순으로 정렬하기 • [프로그램 10-15] • 5명의 은메달리스트 이름을 char형 2차원 배열에 저장 • [프로그램 10-16] • 5명의 금메달리스트 이름을 char형 포인터 배열을 이용 저장 char silver[5][10] ={"나태희", "유빈", "나원빈", "문건영", "소지법"}; 배열명[행첨자]은 해당 행 시작 주소 char *gold[] = {"한빛", "성춘향", "이몽룡", "사공민국", "황해”};
10-15 char형 2차원 배열을 이용한 문자열 저장 및 정렬 p.504 보관용 1 #include <stdio.h> 2 #include <string.h> // strcmp, strcpy함수를 위한 헤더 파일 3 #define SIZE 5 // 배열의 원소수 4 5 int main() 6 { 7 char silver[SIZE][10] = {"나태희", "유빈", "나원빈", "문건영", "소지법"}; 8 char temp[10]; // 문자열 한 개를 임시로 저장할 배열 9 intpass, i; 10 11 printf("** 은메달 리스트 : "); 12 for (i=0; i<SIZE; i++) // 정렬 전 배열 내용 출력하기 13 printf("%s, ", silver[i]); 14 printf("\b\b **\n\n"); // \b를 이용하여 마지막 이름 뒤의 , 지우기
10-15 char형 2차원 배열을 이용한 문자열 저장 및 정렬 p.504 16 // 버블 정렬을 이용하여 이름을 가나다순으로 정렬하기 17 for (pass=1; pass<SIZE; pass++) 18 for (i=0; i<SIZE-pass; i++) 19 if (strcmp(silver[i], silver[i+1]) > 0) 20 { 21 strcpy(temp, silver[i]); 22 strcpy(silver[i], silver[i+1]); 23 strcpy(silver[i+1], temp); 24 } 25 26 printf("** 정렬한 리스트 : "); 27 for (i=0; i<SIZE; i++) // 정렬 후 배열 내용 출력하기 28 printf("%s, ", silver[i]); 29 printf("\b\b **\n"); // \b를 이용하여 마지막 이름 뒤의 , 지우기 30 31 return 0; 32 }