티스토리 뷰

2021.02.16.화
<string.h>
✔ 문자열과 관련된 함수를 가진 헤더 파일로, 문자열 관련 함수를 사용하기 위해 반드시 전처리할 것.
✔ 아래는 문자열과 관련된 자주 사용되는 함수의 정리.
1. 문자열 복사 함수
strcpy(str1, str2) | str1에 str2의 문자열을 복사 |
strncpy(str1, str2, n) | str1에 str2의 문자열을 n만큼 복사 |
#include <stdio.h>
#include <string.h> //문자열 관련 함수를 가진 헤더파일
int main(void)
{
//strcpy 예제
char str1[10] = "apple";
printf("%s\n", str1); //apple
strcpy(str1,"banana");
printf("%s\n", str1); //banana
//strncpy 예제
char str2[20] = "hello world";
printf("%s\n", str2); //hello world
strncpy(str2,"clang", 2);
printf("%s\n", str2); //clllo world
strncpy(str2,"hello", 5);
printf("%s\n", str2); //hello world
return 0;
}
2. 문자열 비교 함수
strcmp(str1, str2) | 아스키 코드를 기준으로 str1과 str2의 순서 비교 |
strcnmp(str1, str2, n) | 아스키 코드를 기준으로 str1과 str2의 순서를 n만큼 비교 |
#include <stdio.h>
#include <string.h>
int main(void)
{
//strcmp 예제
char str1[10] = "apple";
char str2[10] = "banana";
printf("%d\n", strcmp(str1,str2)); //apple과 banana를 비교 → -1 (음수)
printf("%d\n", strcmp(str1,str1)); //apple과 apple을 비교 → 0
printf("%d\n", strcmp(str2,str1)); //banana와 apple을 비교 → 1 (양수)
return 0;
}
✔ str1이 str2보다 아스키코드를 기준으로 앞에 있다면 음의 정수를 반환.
✔ str1에 저장된 문자열과 str2에 저장된 문자열이 동일하다면 0 을 반환.
✔ str1이 str2보다 아스키코드를 기준으로 뒤에 있다면 양의 정수를 반환.
✔ 비교 대상이 동일해도 인자 입력 순서에 따라 비교의 기준이 다르기 때문에 다른 값을 반환받을 수도 있다.
#include <stdio.h>
#include <string.h>
int main(void)
{
//strncmp 예제
char str1[20] = "applejuice";
char str2[20] = "applejam";
printf("%d\n", strncmp(str1,str2,5)); //str1의 apple과 str2의 apple을 비교 → 0
printf("%d\n", strncmp(str1,str2,7)); //str1의 appleju와 str2의 appleja을 비교 → 20 (양수)
printf("%d\n", strncmp(str2,str1,7)); //str2의 appleja와 str1의 appleju을 비교 → -20(음수)
return 0;
}
✔ str1과 str2에 저장된 문자열을 n개 비교. 반환 값의 원리는 strcmp()와 동일하다.
3. 문자열 검색 함수
strstr(str1, str2) | str1에서 str2과 일치하는 문자열이 있는지 확인하고 포인터 반환 |
strchr(str, c) | str의 내부에 문자 c가 존재하는지 확인하고 포인터 반환 (앞에서부터 확인) |
strrchr(str, c) | str의 내부에 문자 c가 존재하는지 확인하고 포인터 반환 (뒤에서부터 확인) |
#include <stdio.h>
#include <string.h>
int main(void)
{
//strstr 예제1
char* str1 = "applejam";
char* p1 = strstr(str1,"jam");
if(p1!=0) {
printf("%s 에는 jam이 포함되어 있습니다\n",str1);
printf("p1이 가리키는 주소 \t: %p\n",p1); //0x4006dd
printf("str1이 가리키는 주소 \t: %p\n",str1); //0x4006d8
}else{
printf("%s 에는 jam이 포함되어 있지 않습니다\n",str1);
}
//strstr 예제2
char* str2 = "applejam";
char* p2 = strstr(str2,"juice");
if(p2!=0) {
printf("%s 에는 juice가 포함되어 있습니다\n",str2);
}else{
printf("%s 에는 juice가 포함되어 있지 않습니다\n",str2);
}
return 0;
}
✔ strstr() 함수는 두 번째 인자의 값이 첫 번째 인자 내부에 없다면 null을 반환하므로 if문을 사용해 확인하는 과정이 필요하다.
✔ 동일한 문자열을 가지고 있다면 해당 문자열의 포인터를 반환한다.
✔ 예제 1에서 p1에 저장된 주소가 0x4006dd 인 것은 jam이 저장된 문자열의 주소, 즉 j가 저장된 주소를 반환했기 때문이다.
a | p | p | l | e | j | a | m |
0x4006d8 | 0x4006d9 | 0x4006da | 0x4006db | 0x4006dc | 0x4006dd | 0x4006de | 0x4006df |
✔ 위 개념을 이해하기 어렵다면 우측 게시글 확인을 추천 [참고 링크] [CS50 5주차] 3-5. 문자열
4. 문자열을 이어 붙이는 함수
strcat(str1, str2) | str1의 뒤에 str2를 이어붙이고 str1에 저장 |
strncat(str1, str2, n) | str1의 뒤에 str2의 문자 n개를 이어붙이고 str1에 저장 |
#include <stdio.h>
#include <string.h>
int main(void)
{
//strcat 예제
char str1[10] = "apple";
char str2[10] = "jam";
printf("%s\n",strcat(str1,str2)); //applejam
printf("%s\n",str1); //applejam
//strncat 예제
char str3[20] = "apple";
char str4[20] = "juicecup";
printf("%s\n",strncat(str3,str4,5)); //applejuice
printf("%s\n",str3); //applejuice
return 0;
}
✔ 두 문자열을 이어 붙여서 str1에 저장하기 때문에, 두 문자열을 이어 붙였을 때의 크기가 str1보다 작아야 한다.
5. 문자열 길이 확인 함수
strlen(str) | 문자열의 길이 반환 (\0를 제외한 길이) |
#include <stdio.h>
#include <string.h>
int main(void)
{
//strlen 예제
char str1[] = "applejam";
char str2[10] = "applejam";
printf("%lu\n", strlen(str1)); //8
printf("%lu\n", strlen(str2)); //8
return 0;
}
✔ 배열의 크기를 지정하지 않고 초기화하면, 문자열의 길이만큼 자동으로 할당됨.
6. 문자열 분리 함수
strtok(str, t) | str 내부에서 t를 찾아, t를 기준으로 문자열을 분리해 해당 포인터 반환 |
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] = "Nice to Meet you";
char *p1 = strtok(str," ");
printf("%s\n",p1); //Nice
char *p2 = strtok(str," ");
printf("%s\n",p2); //Nice
return 0;
}
✔ 두 번째 인자로 받아온 토큰(공백 가능)을 기준으로 첫 번째 인자를 분리해 해당 포인터를 반환한다.
✔ 첫번째 인자의 문자열 전체를 원하는 토큰으로 분리해 출력하고 싶다면 아래 코드를 참고.
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] = "Nice-to-Meet-you";
char *p = strtok(str,"-");
while(p!=0){
printf("%s\n",p);
p = strtok(NULL,"-");
}
printf("\n%s",str);
//출력값
// Nice
// to
// Meet
// you
return 0;
}
✔ 더 이상 분리할 문자열이 없는 경우 strtok() 함수는 null을 반환하므로, while문의 종료 시점을 null을 반환받았을 때로 설정.
✔ while문 내부에서 NULL을 넣어 strtok()를 사용하는 이유는 이전에 처리한 문자열의 다음 문자부터 확인하기 위함.
N | i | c | e | - | t | o | - | M | e | e | t | - | Y | o | u | \0 |
N | i | c | e | \0 | t | o | - | M | e | e | t | - | Y | o | u | \0 |
✔ strtok(str,"-") 을 사용하면, - 를 찾아 \0 으로 변경하기 때문에 위와 같은 변화가 생긴다.
✔ \0은 곧 문자열의 끝을 의미하므로, 이후에 아무리 strtok(str,"-") 을 사용한다 하더라도 더 이상 -를 찾지 못한다.
✔ 즉, 한 번 분리를 한 후에 strtok(str,"-") 를 사용한다면 Nice만 계속 반환.
✔ 그렇기 때문에 첫 번째 분리 이후에 while문 내부에서는 strtok()함수를 사용할 때, 첫번째 인자로 NULL을 넣어주어야 한다.
✔ NULL을 넣으면 직전에 실행했던 stroke함수에서 자른 만큼 다음 문자열로 이동해 토큰을 찾아 분리를 실행한다.
N | i | c | e | \0 | t | o | - | M | e | e | t | - | Y | o | u | \0 |
N | i | c | e | \0 | t | o | \0 | M | e | e | t | - | Y | o | u | \0 |
✔ 첫 번째 실행에서 Nice를 분리했으니 두 번째 실행은 그 이후부터 토큰을 찾는다. (포인터 p에는 t의 주소가 저장)
N | i | c | e | \0 | t | o | \0 | M | e | e | t | - | Y | o | u | \0 |
N | i | c | e | \0 | t | o | \0 | M | e | e | t | \0 | Y | o | u | \0 |
✔ 두번째 실행에서 to를 분리했으니 세 번째 실행은 그 이후부터 토큰을 찾는다. (포인터 p에는 M의 주소가 저장)
N | i | c | e | \0 | t | o | \0 | M | e | e | t | \0 | Y | o | u | \0 |
N | i | c | e | \0 | t | o | \0 | M | e | e | t | \0 | Y | o | u | \0 |
✔ 세번째 실행에서 Meet을 분리했으니 네 번째 실행은 그 이후부터 토큰을 찾는다. (포인터 p에는 Y의 주소가 저장)
✔ 이후 실행에서는 더 이상 토큰을 발견할 수 없으므로 strtok() 함수는 null 반환, 포인터 p에는 null이 저장되고 while문 종료.
✔ 한 번이라도 strtok() 함수를 사용하고 str을 출력한다면, 첫 번째 분리된 문자열 뒤에 바로 null이 저장되어 있으므로
✔ 문자열의 끝으로 인식하기 때문에 더 이상 원래 저장되어 있었던 문자열 전체를 출력할 수 없다.
✔ 이처럼 strtok 함수는 저장된 문자열의 내용을 변경하므로 사용 시 주의가 필요하다.
[참고] 한빛미디어-혼자 공부하는 C언어 유튜브 강의 / 엘리스 트랙-혼자 공부하는 C언어 / 길벗-C언어 코딩도장 / 위키백과
'BackEnd > C' 카테고리의 다른 글
[10일차] 제어문 복습 (0) | 2021.02.20 |
---|---|
[8일차] 포인터의 선언과 사용 (0) | 2021.02.17 |
[7일차] 1. 문자열(char형 배열) (0) | 2021.02.16 |
[6일차] 2. 배열 (0) | 2021.02.15 |
[6일차] 1. 재귀 호출 함수 (0) | 2021.02.15 |