Download presentation
Presentation is loading. Please wait.
1
www.msharpmath.comSeoul National University 1 / 17 컴퓨터 개론 및 실습 강의 6
2
www.msharpmath.comSeoul National University 2 / 17 포인터 (Pointer)와 문자열 (string) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ 문자열은 C언어에서 가장 많이 사용되는 배열이다. ■ 문자열 은 그 끝에 '\0' (null character)을 가지므로 실제 기억장소는 따옴표 안에 있는 문자의 갯수보다 한 개가 더 필요하다. ■ 문자열 처리함수는 교과서 p.369 를 참조한다.
3
www.msharpmath.comSeoul National University 3 / 17 ■ 문자열의 구조 문자열은 항상 '\0' (null character) 을 마지막에 가진다. 예를 들어, "hello" 는 다섯 글자로 이루어진 문자열이 아니라 와 같이 여섯 글자로 이루어진 문자열이다. ■ 표준 라이브러리 함수 strlen 문자열의 길이를 리턴하는 함수 strlen 은 '\0' 을 제외한 글자수를 리턴한다. 위의 경우 strlen("hello") 는 5 를 리턴한다. 이것은 와 같이 0 부터 5 까지의 기억장소 ( 즉 6 개의 기억장소 ) 를 사용하는 것으로 처리하는 것이 훨씬 편리하기 때문이다. hello\0 [0][1][2][3][4][5] 문자열
4
www.msharpmath.comSeoul National University 4 / 17 ■ 문자열 변수와 초기화 문자열 변수를 선언하고 초기화 (initialization) 하는 것은 char msg[] = "my message" ; // 문자열 변수 와 같이 큰 따옴표로 이루어진 상수 문자열을 이용한다. 이때 문자의 갯수는 세지 않아도 자동으로 문자열의 크기가 정해진다. 위의 경우 스페이스를 포함하여 큰 따옴표 내부의 총 문자는 10개이고, 마지막에 '\0' 으로 끝나므로 문자열 msg 의 크기는 자동으로 11이 된다. #include void main() { char msg[]="my message"; printf( "%d \n", sizeof(msg) ); } 11 계속하려면 아무 키나 누르십시오....
5
www.msharpmath.comSeoul National University 5 / 17 ■ 문자열의 초기화 (1) 문자열 변수의 크기를 사용자가 직접 지정하면서 길이가 더 긴 상수문자열로 초기화하면 다음과 같은 문제가 발생한다. char msg[5] = "my message" ; // 크기가 지정되면서 오버액션 #include void main() { char msg[5]="my message"; printf("%d \n", sizeof(msg) ); printf("%s \n", msg); }.
6
www.msharpmath.comSeoul National University 6 / 17 ■ 문자열의 초기화 (2) 문자열 변수의 크기를 사용자가 직접 지정하면서 길이가 더 길지 않은 상수문자열로 초기화하면 아무 문제없이 정상적으로 작동한다. 이때 초기화에서 채우지 못하고 남는 문자는 모두 '\0' 으로 초기화된다. char msg[5] = "this" ; // 크기가 지정되면서 길이가 정확하게 같도록 초기화 char msg2[5] = "at" ; // 크기가 지정되면서 길이가 더 짧게 초기화 #include void main() { char msg[5]="this", msg2[5]="at"; int i; printf("%d %d \n", sizeof(msg), sizeof(msg2) ); for(i=0; i<5; i++) printf("%c %c \n", msg[i], msg2[i]); }. 문자열은 하나의 배열이므로 msg[i] 와 같이 각 문자에 접근한다.
7
www.msharpmath.comSeoul National University 7 / 17 ■ 문자열 상수 숫자 127 을 정수 상수라고 부르는 것처럼 큰 따옴표 내부에 있는 문자들은 문자열 상수라고 한다. 이때 변수처럼 이름을 가지지만 더 이상 문자를 바꿀 수 없는 문자열 상수를 만들려면 명령어 const 을 붙이면 된다. char msg[] = "rewrite here" ; // 문자열 변수 const char book[] = "frozen string" ; // 문자열 상수 위에서 msg 는 문자열 변수이고, book 은 문자열 상수이다. ■ 문자열의 원소 ( 즉, 문자 ) 에의 접근 문자열은 하나의 배열이므로 msg[i], *(book+i) 와 같이 포인터를 이용하여 각 문자에 접근한다. book[0] = '1'; // error C2166: l-value specifies const object 와 같이 문자열 상수의 값을 바꾸는 것은 불가능하다. 문자열 변수와 문자열 상수
8
www.msharpmath.comSeoul National University 8 / 17 ■ 표준 라이브러리 함수 strlen /* strlen : return length of s */ int strlen(char *s) { char *p = s; // 포인터 p 를 이용하여 문자를 검색 while( *p ) ++p; // null 문자 '\0' 을 만나면 종료 return p - s; } ★ p ++p ★★★★★ \0 *p == 0 s[] p 가 이 위치에서 while 을 빠져나온다 문자열 함수 strlen (std library)
9
www.msharpmath.comSeoul National University 9 / 17 문자열의 복사는 원래의 문자열이 ' \ 0'을 만날 때까지 (즉, 거짓일 때까지) 수행된다. ■ 표준 라이브러리 함수 strcpy /* strcpy : copy t to s */ void strcpy(char *s, char *t) { while( *s++ = *t++ ) ; // 포인터 s,t 를 이용하여 문자를 복사 } // *s++ = *t++ 는 t 가 증가되기 전의 값 *t 를 먼저 *s 에 복사하고, // t와 s 를 증가시킨다. while( *s++ = *t++ ) ; while( *s = *t ) { s++; t++; } 위의 두 문장은 strcpy 의 함수의 목적에 기준해서는 같은 결과에 이르지만 포인터의 최종 주소는 서로 다르다는 점에 주의해야 한다. 문자열 함수 strcpy (std library)
10
www.msharpmath.comSeoul National University 10 / 17 (1) while 의 조건문에 ++ 가 존재할 때 while( *s++ = *t++ ) ; *t 가 ' \ 0' 일 때까지 수행된 다음, 계속해서 s++ 및 t++ 가 실행되어 ' \ 0' 의 다음 문자 를 가리킨다. (2) while 의 실행문에 ++ 가 존재할 때 while( *s = *t ) { s++; t++; } *t 가 ' \ 0' 일 때까지 수행되지만, 이 경우의 수식값은 0( 거짓 ) 이므로 실행문의 내용 { s++; t++; } 은 실행되지 않는다. 따라서, t 는 ' \ 0' 문자를 가리킨 상태 그대로 유 지된다. 다음 페이지에서 실제의 실행결과를 출력하여 차이를 살펴본다.
11
www.msharpmath.comSeoul National University 11 / 17 #include void strcpy(char *s, char *t) { printf("%p %p (start) \n", s, t); while( *s++ = *t++ ) ; // 포인터 s,t를 이용하여 문자를 복사 printf("%p %p \n", s, t); } void strcpy2(char *s, char *t) { printf("%p %p (start) \n", s, t); while( *s = *t ) { s++; t++; } // 포인터 s,t를 이용하여 문자를 복사 printf("%p %p \n", s, t); } void main() { char a[10],b[10]; int i; for(i=0; i<10; i++) a[i] = b[i] = '\0'; b[0]='a'; b[1]='b'; strcpy(a,b); strcpy2(a,b); } 실행결과 001CFA2C 001CFA18 (start) 001CFA2F 001CFA1B 001CFA2C 001CFA18 (start) 001CFA2E 001CFA1A 계속하려면 아무 키나 누르십시오 …
12
www.msharpmath.comSeoul National University 12 / 17 문자열을 이어 붙이는 표준함수 strcat을 포인터를 이용하여 작성해보자. ■ 표준 라이브러리 함수 strcat /* strcat : concatenate t to end of s; s must be big enough*/ void strcat(char *s, char *t) { s += strlen(s); while( *s++ = *t++ ) ; // 포인터 s,t 를 이용 // 실행이 끝나면 s, t 는 모두 '\0' 의 다음 문자를 가리킨다 ( 즉, 포인팅한다 ) } void main() { char s[100] = "abc"; strcat( s, "xyz" ) ; printf( "%s \n", s ); } abcxyz 문자열 함수 strcat (std library)
13
www.msharpmath.comSeoul National University 13 / 17 문자열의 비교는 각 문자열의 첫 글자부터 시작한다. 두 문자가 같으면 다음 문자로 진행하다가 다른 문자가 나타나면 문자값의 차이로부터 크거나 작은 가를 판단한다. 끝까지 문자가 서로 같으면 0을 리턴한다. ■ 표준 라이브러리 함수 strcmp /* strcmp : return 0 if s>t */ int strcmp(char *s, char *t) { for( ; *s == *t; s++, t++) // 포인터 s,t 를 이용 if( *s == ' \0 ' ) return 0; return *s - *t ; } strcmp("abc", "abx") 는 음의 정수이고, 'c' - 'x' = 99 - 120 = -21 의 값을 가진다 strcmp("abc", "abc") 는 0 strcmp("abc", "aba") 는 양의 정수이고, 'c' - 'a' = 99 - 97 = 2 의 값을 가진다 문자열 함수 strcmp (std library)
14
www.msharpmath.comSeoul National University 14 / 17 int strcmp(char *s, char *t) { for( ; *s == *t; s++, t++) // 포인터 s,t 를 이용 if( *s == ' \0 ' ) return 0; return *s - *t ; } 다음과 같이 for 문 대신에 while 문을 이용하여 작성하여도 동일한 내용일 것으로 착각할 수 있다. int strcmp2(char *s, char *t) { while( *s++ == *t++ ) // 포인터 s,t 를 이용 if( *s == ' \0 ' ) return 0; return *s - *t ; } 두 번째 함수의 경우, *s가 ' \0 ' 바로 직전의 문자이고 이때 *s == *t 는 1(참)이라고 하자. 하 지만 계속해서 while의 조건문에서 s++, t++ 가 실행되어 s는 이제 ' \0 ' 를 가리키지만 t는 어 떤 문자인지는 알 수 없다. 따라서 *t의 값에 무관하게 if( *s == ' \0 ' ) return 0 이 바로 실행된다. 특히 C언어를 처음 배우는 학생들이 가끔 실수하는 문제이다.
15
www.msharpmath.comSeoul National University 15 / 17 #include int strcmp(char *s, char *t) { printf("%p %p (start)\n", s, t); for( ; *s == *t; s++, t++) { // 포인터 s,t를 이용 printf("%p %p \n", s, t); if( *s == '\0' ) { return 0; } } printf("%p %p (end)\n", s, t); return *s - *t ; } int strcmp2(char *s, char *t) { printf("%p %p (start)\n", s, t); while( *s++ == *t++ ) { // 포인터 s,t를 이용 printf("%p %p \n", s, t); if( *s == '\0' ) { return 0; } } printf("%p %p (end)\n", s, t); return *s - *t ; } void main() { char a[]="ab",b[]="abc"; printf("%d \n", strcmp(a,b)); printf("%d \n", strcmp2(a,b)); } 실행결과 002FFAE8 002FFADC (start) 002FFAE8 002FFADC 002FFAE9 002FFADD 002FFAEA 002FFADE (end) -99 002FFAE8 002FFADC (start) 002FFAE9 002FFADD 002FFAEA 002FFADE 0 계속하려면 아무 키나 누르십시오 …
16
www.msharpmath.comSeoul National University 16 / 17 ■ 사용자 함수 strrev /* strrev : reverse string str in place */ void strrev(char *p) { char *q, c; q = p + strlen(p) -1; // last character, next is '\0' while( p < q ) { c = *p; *p = *q; *q = c; // swap *p and *q ++p; --q; // forward and backward } ★ p ++p ★★★★★ \0 q--q 문자열 함수 strrev
17
www.msharpmath.comSeoul National University 17 / 17 문자열 "365"를 정수 365로 변환하려면 atoi("365") 와 같이 표준 함수 atoi 를 이용한다. 단, #include 문장을 포함해야 한다. ■ 표준 라이브러리 함수 atoi /* atoi : convert s to integer */ int atoi(char *str) { char *p = str; int n = 0,sign; while( *p == ' ' ) { ++p; } // skip space sign = (*p == ' - ' ) ? -1 : 1 ; if( *p == ' + ' || *p == ' - ' ) ++p; // skip sign while( *p ) { n = 10*n + (*p - ' 0 ' ); ++p; } return sign*n; } 문자열 함수 atoi (std library)
18
www.msharpmath.comSeoul National University 18 / 17 문자열 "-3.14159"를 실수 -3.14159로 변환하려면 atof("-3.14159") 와 같이 표준 함수 atof 를 이용한다. 단, #include 문장을 포함해야 한다. ■ 표준 라이브러리 함수 atof /* atof : convert s to double */ double atof(char *p){ double sign,val,power; while( *p == ' ' ) ++p; // skip space sign = (*p == '-') ? -1. : 1. ; // find sign if( *p == '+' || *p == '-' ) ++p; // skip sign for(val = 0.; *p>='0' && *p<='9'; p++) val = 10.*val + (*p - '0'); if( *p == '.' ) p++; for(power = 1.; *p>='0' && *p<='9'; p++) { // for x < 1 val = 10.*val + (*p - '0'); power *= 10.; } return sign*val/power; } 문자열 함수 atof (std library)
19
www.msharpmath.comSeoul National University 19 / 17 정수(-365)를 문자열("-365")로 변환하는 것은 먼저 1의 자리부터 시작하여 마지막 자리까지 "563-"와 같이 역순으로 만들고, 문자열을 뒤집는 방법을 사용한다. ■ 사용자 함수 itoa /* itoa : convert n to characters in s */ void itoa(int n,char *p) { int sign = n; char *str = p; if( n < 0 ) n = -n; // make positive do { *p = n % 10 + ' 0 ' ; p++; // get next digit } while( (n/=10) > 0 ); // delete digit if( sign < 0 ) { *p = ' - ' ; p++; } *p = ' \0 ' ; strrev(str); } 문자열 함수 itoa
20
www.msharpmath.comSeoul National University 20 / 17 문자열에 마지막에 "공백, 탭, 줄바꿈" 등의 문자가 오지 않도록 잘라 내는 함수를 작성해보자 ■ 사용자 함수 strtrim /* strtrim : remove trailing blanks, tabs, newlines */ int strtrim(char *str) { char *p; for(p = str+strlen(str)-1; p >= str; p--) if( *p != ' ' && *p != '\t' && *p != '\n' ) break; *(++p) = '\0'; return p-str; // string length } 문자열 함수 strtrim
Similar presentations