1. strlen : 문자열의 길이 정보 반환
다음은 문자열의 길이를 계산해서 반환하는 기능의 함수이다.
이 함수는 인자로 전달된 주소값을 시작으로, 널 문자를 만날 때까지 문자의 개수를 세어 나가
는 방식으로 문자열의 길이를 계산하는데, 이 때에 널 문자는 문자열의 길이에 포함이 되지 않는
다. 그리고 이렇게 계산된 문자열의 길이 정보는 함수 호출이 완료되면서 반환된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <stdio.h> #include <string.h> int main(void) { char str1[]="1234567"; char str2[]="프로그래밍"; char str3[]="C Programming"; printf("%s: %d \n",str1, strlen(str1)); printf("배열 크기: %d \n\n", sizeof(str1)); printf("%s: %d \n",str2, strlen(str2)); printf("배열 크기: %d \n\n", sizeof(str2)); printf("%s: %d \n",str3, strlen(str3)); printf("배열 크기: %d \n\n", sizeof(str3)); return 0; } | cs |
1 2 3 4 5 6 7 8 9 | 1234567: 7 배열 크기: 8 프로그래밍: 10 배열 크기: 11 C Programming: 13 배열 크기: 14 | cs |
위 예제를 보면 한글은 한 글자당 2바이트로 표현되고, 길이도 2배임을 알수 있다.
2. strcpy, strncpy : 문자열 복사
위 두 함수 모두, 두 번째 매개변수 src에 전달된 주소의 문자열을, 첫 번째 매개변수 dest에 전달
된 주소의 메모리 공간에 복사한다. 단 strncpy 함수는 복사할 문자열의 길이가(널 문자를 포함
한 문자열의 길이) 세 번째 전달인자의 값보다 클 경우, 세 번째 전달인자의 크기만큼만 복사를
진행한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> #include <string.h> int main(void) { char str1[5]; strcpy(str1, "ABC"); printf("str1: %s \n", str1); str1[0]='C'; str1[1]='B'; printf("str1: %s \n", str1); return 0; } | cs |
1 2 | str1: ABC str1: CBC | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <stdio.h> #include <string.h> int main(void) { char src[20]="1234567890"; char dest1[20]; char dest2[20]; strcpy(dest1, src); strncpy(dest2, src, strlen(src)); printf("dest1: %s \n", dest1); printf("dest2: %s \n", dest2); return 0; } | cs |
1 2 | dest1: 1234567890 dest2: 1234567890ftf234567890 | cs |
위 예제 10행에서는 strcpy 함수의 사용 예를 보여준다. 여기서는 복사될 메모리 공간 dest1이 넉
넉하므로 문제없이 복사가 이뤄진다. 그러나 11행은 문제가 있다. strlen(src)의 반환 값이 10이므
로, 이 문장은 다음과 같은 형식으로 호출이 되어 문제가 발생한다.
strncpy(dest2, src, 10);
최대 열 개의 문자까지 복사가 되는데, 널 문자는 열 한번째 문자이다. 따라서 널 문자는 복사되지
않는다. 그러므로 dest2에 저장된 문자열은 C언어에서 말하는 문자열이 아닌 셈이다(널 문자가 삽
입되지 않았으므로). 그래서 정상이 아닌 출력결과를 보였는데, 이를 수정하기 위해서는 11행을 다
음과 같이 변경하거나 직접 널 문자를 삽입해야 한다.
strncpy (dest2, src, strlen(src) +1) ; // 널 문자까지 복사를 위해 +1
위 예제에서는 strncpy 함수의 주의사항을 보여줬는데,
다음 예제에서는 strcpy 함수의 주의사항을 보여준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <stdio.h> #include <string.h> int main(void) { char src[20]="1234567890"; char dest1[5]; char dest2[5]; strcpy(dest1, src); strncpy(dest2, src, sizeof(dest2)-1);// 널 문자 공간 위해 -1 dest2[sizeof(dest2)-1]='\0';// 널 문자 삽입 printf("dest1: %s \n", dest1); printf("dest2: %s \n", dest2); return 0; } | cs |
1 2 3 4 | 배열 크기: 4 dest1: 1234567890 dest2: 1234 | cs |
10행: 배열 src에 저장된 문자열의 길이는 배열 dest1의 길이보다 길다. 이러한 상황에서 10행의 함
수 호출을 하면 dest1에 할당된 메모리 공간을 넘어서서 복사가 진행된다.
12~13행: 반면 strncpy 함수를 사용하면 배열의 길이만큼만 딱 복사가 이뤄지도록 함수의 호출문장을 구성할 수 있다.
추가적으로 strncpy 함수를 이용하면 strcpy 함수가 할 수 있는 모든 일을 안정적으로 처리할 수 있기 때문에, 일반적으로 strncpy 함수의 사용을 추천한다.
3. strcat, strncat : 문자열 연결
두 개의 문자열을 연결하고 싶은 경우에 사용할 수 있는 함수들이다.
이 두 함수는 src로 전달된 문자열을 dest로 전달된 문자열의 뒤에 복사한다. 그리고 strcat 함수와
strncat 함수의 차이점은 길이의 제한이다.
strncat 함수의 세 번 째 전달인자는 덧붙일 문자열의 최대 길이를 제한한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> #include <string.h> int main(void) { char str1[20]="Your name is "; char str2[20]; printf("이름을 입력하세요: "); gets(str2); strcat(str1, str2); puts(str1); return 0; } | cs |
1 2 | 이름을 입력하세요: Hong Your name is Hong |
6행에 선언된 배열 str1의 길이는 20이다. 따라서 이 배열에는 널 문자를 포함해서 최대 길이가 20
을 넘지 않는 문자열만 저장할 수 있다.그리고 12행에서는 이 배열에 문자열을 덧붙이는데,
덧붙 일 문자열이 “Hong”이라면,메모리 상에서는 다음과 같은 방식으로 덧붙임이 진행된다.
strcat 함수는 문자열을 덧붙여서 새로운 문자열을 구성하니, 첫 번째 문자열에 저장된 널 문자가
삭제되는 것은 당연하다.
4. strcmp, strncmp : 두 문자열이 동일한지 확인
위 함수들은 두 문자열이 동일하면 0을 반환 한다 . 그러나 동일 하지 않고 사전 편찬 순서상 첫
번째 문자열 s1이 앞서면 0보다 작은 값을,
두 번째 문자열 s2가 앞서면 0보다 큰 값을 반환한다.
그리고 함수 strncmp는 비교하는 문자열의 길이가 세 번째 전달 인자의 값보다 크면, 세 번째 전
달인자의 길이만큼만 부분 비교를 한다.
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 32 33 34 35 36 37 38 39 40 41 42 | #include <stdio.h> #include <string.h> void LexiCmp(char * str1, char * str2); void LexiPartialCmp(char * str1, char * str2, int len); int main(void) { char str1[]="It is possible to master C"; char str2[]="It is impossible to master C"; char str3[]="It is possible to master C in a month or two"; LexiCmp(str1, str2); LexiCmp(str1, str3); LexiPartialCmp(str1, str3, 26); return 0; } void LexiCmp(char * str1, char * str2) { int ret=strcmp(str1, str2); if(ret==0) puts("두 문자열은 동일합니다."); else if(ret<0) printf("앞서는 문자열: %s \n", str1); else printf("앞서는 문자열: %s \n", str2); } void LexiPartialCmp(char * str1, char * str2, int len) { int ret=strncmp(str1, str2, len); if(ret==0) printf("%d번째 문자까지 두 문자열은 동일합니다.\n", len); else if(ret<0) printf("앞서는 문자열: %s \n", str1); else printf("앞서는 문자열: %s \n", str2); } | cs |
1 2 3 | 앞서는 문자열: It is impossible to master C 앞서는 문자열: It is possible to master C 26번째 문자까지 두 문자열은 동일합니다. | cs |
20~30행: strcmp 함수를 이용해서, 입력되는 문자열중 사전편찬 순서가 앞서는 문자열을 출력하도록 정의하였다.
32~42행: strncmp 함수를 이용해서, 입력되는 문자열을 부분적으로 비교할 수 있도록 정의하였다.
'BackEnd > C' 카테고리의 다른 글
sprintf & sscanf (0) | 2019.03.21 |
---|---|
문자열의 정보 추출 함수들 (0) | 2019.03.21 |
puts,putchar,gets,getchar 함수와 버퍼 (0) | 2019.03.19 |
함수 포인터를 인자로 요구하는 표준 함수들(atexit, qsort, bsearch) (0) | 2019.03.18 |
버블 정렬 (Bubble Sort)의 이해와 함수 포인터 기반의 함수 정의 (0) | 2019.03.18 |