티스토리 뷰
2021.02.25.목
이 전의 #7일 차 정리에서는 문자열 관련 함수의 사용 예제를 위주로 살펴보았다면 이번에는 함수의 원형, 즉 함수의 선언부를 살펴보려 한다. 아래의 함수는 모두 <string.h> 헤더 파일에 속해 있으므로 반드시 전처리가 필요하다.
strcpy() 함수
✔ char 배열은 문자열을 저장하는 변수의 역할
✔ 다른 문자열로 바꾸어야 할 때에는 변경하고자 하는 문자열의 문자를 요소마다 다시 저장해야 하는 번거로움이 있다.
✔ 첫 번째 인자로 저장할 공간의 주소(포인터)를 받고, 두번째 인자로는 수정할 문자열을 받는다.
char * strcpy(char * dest, const char * src) ;
✔ 첫번째 인자(dest)로 받을 수 있는 값은 char 배열과 배열명을 저장한 포인터만 가능.
✔ 문자열 상수는 값을 바꿀 수 없으므로, 프로그램 실행 시 에러가 발생한다.
✔ 문자열 상수의 주소를 저장한 포인터를 통해 접근하여 값을 수정하는 것은 문법상으로는 가능하나 사용해서는 안된다.
✔ 두 번째 인자(src)로 받는 값은 수정한 문자열로, 여러 가지 형태를 받아온다.
✔ 문자열 상수를 직접 입력해도 되는 이유는 문자열 상수의 첫 번째 문자의 위치를 전달하기 때문.
strncpy() 함수
char * strncpy(char * dest, const char * src, size_t n) ;
✔ 문자열을 복사할 공간(dest)에 문자열(src)을 n 만큼 복사해 저장하는 함수
✔ 문자를 n만큼만 복사해 저장하기 때문에 null을 자동으로 저장하지 않으므로 별도로 저장해야 한다.
✔ strcpy()는 복사할 문자열의 길이가 저장할 공간보다 크다면 버퍼 오버플로우가 발생.
strcpy()와 strncpy()의 차이점
✔ 이에 대한 대응책이 strncpy()이며, 이는 string new copy의 약자이다.
✔ 그러므로 복사할 문자열의 크기를 지정하여 가져오는, 비교적 방어적인 strncpy()를 사용하는 것을 추천.
✔ 하지만 strncpy() 또한 버퍼 오버플로우에서 완벽히 자유로운 것은 아니므로, 주의가 필요하다.
strcat() 함수
char* strcat(char* dest, const char* origin);
char str1[10] = "apple";
char str2[10] = "jam";
printf("%s\n",strcat(str1,str2)); //applejam
printf("%s\n",str1); //applejam
✔ 함수의 원형은 위와 같으며 매개변수로는 붙여 넣을 문자열 주소(dest)와 이어 붙일 문자열의 주소(origin)를 받는다.
✔ 먼저 붙여 넣을 문자열에서 null 문자의 위치를 찾아 그 이후에 문자열을 복사해 이어 붙이도록 구현되어있다.
✔ 이어 붙인 뒤에는 null문자를 저장하며 마무리한다.
✔ 문자열을 덧붙이는 함수이므로, 붙여 넣을 공간이 부족한 경우 다른 메모리 영역을 침범할 수 있으니 주의하자.
✔ strcat() 함수로 붙여 넣기 전에 반드시 붙여 넣을 공간인 배열이 초기화되어있어야 한다.
✔ 배열의 초기화 방법은 아래를 참고하자.
char str[80] = {'\0'}; // 명시적으로 널 문자를 초기화
char str[80] = {0}; // 널 문자의 아스키 코드 값으로 초기화
char str[80] = ""; // 큰따옴표 안에 아무것도 없으므로 널 문자만 초기화
str[0] = '\0'; // 첫 번째 배열 요소만 별도로 초기화
strncat() 함수
char* strcat(char* dest, const char* origin, size_t n) ;
char str1[10] = "apple ";
char str2[10] = "mango";
printf("%s\n",strcat(str1,str2)); //apple mango
printf("%s\n",strncat(str1,str2,1)); //apple mangom
✔ 함수의 원형은 위와 같으며, strcat() 함수와 달리 몇 개의 문자를 이어 붙일 지에 대해 n 이라는 매개변수를 추가로 받는다.
✔ 이어붙일 문자의 개수가 정해져 있으므로, 이어 붙인 후에 null문자를 저장해 문자열을 완성한다.
strlen()함수
size_t strlen(const char* s);
char str1[10] = "apple";
char str2[10] = "jam";
printf("%lu\n",strlen(str1)); //5
printf("%lu\n",strlen(str2)); //3
✔ 일반적으로 문자열을 저장하는 char형 배열은 다양한 길이의 문자열을 저장할 수 있도록 충분히 크게 크기를 선언한다.
✔ 실제로 char형 배열에 저장된 문자열의 길이를 알고 싶다면 strlen()함수를 사용하자.
문자열의 끝을 알리는 null문자를 제외한 문자열의 길이를 반환 (공백 포함)
✔ strlen()함수의 원형을 살펴보면 반환 값의 자료형이 size_t라는 것을 알 수 있다.
✔ size_t는 부호 없는 정수형(unsigned integer)이라는 의미.
✔ sizeof, alignof, offsetof의 반환 값이 이에 속하며, 형식 지정자는 %lu를 사용한다.
strcmp() 함수
int strcmp(const char *string1, const char *string2);
✔ strcmp() 함수는 두 문자열의 순서를 아스키코드를 기준으로 판단하여 숫자로 결과를 반환한다.
✔ 문자열의 첫 번째 문자부터 비교하며, 같은 문자라면 그다음 문자를 차례로 비교하여 판단한다.
char str1[10] = "aaa";
char str2[10] = "bbb";
char str3[10] = "bbb";
printf("%d\n", strcmp(str1, str2)); // aaa와 bbb를 비교했을 때, aaa가 더 빠르므로 -1
printf("%d\n", strcmp(str2, str1)); // bbb와 aaa를 비교했을 때, bbb가 더 빠르므로 1
printf("%d\n", strcmp(str2, str3)); // bbb와 bbb는 동일하므로 0
✔ 아스키코드가 첫 번째 인자보다 두 번째 인자가 나중에 나오면 음수를 반환한다. (a=97, b=98)
✔ 아스키 코드가 첫번째 인자보다 두번째 인자가 먼저 나오면 양수를 반환한다.
✔ 아스키 코드가 첫번째 인자보다 두번째 인자가 동일하면 0을 반환한다.
char str1[10] = "pear";
char str2[10] = "peach";
// 1. pear VS peach
printf("%d\n", strcmp(str1, str2));
// 최초로 다른 문자는 r과 h
// r-h = 81-71 = 10
// 위와 같은 이유로 10 반환
// 2. peach VS pear
printf("%d\n", strcmp(str1, str2));
// 최초로 다른 문자는 h와 r
// h-r = 71-81 = -10
// 위와 같은 이유로 -10 반환
✔ 반환되는 값이 양수인지 음수인지는 사전 순서에 따라 결정되지만 반환되는 값은 어떻게 결정되는 걸까
✔ 최초로 동일하지 않은 문자의 아스키코드를 구해 빼주면 어떤 값이 반환되는지 알 수 있다.
strncmp() 함수
int strcmp(const char *string1, const char *string2);
✔ 함수의 원형은 위와 같으며, strcmp() 함수와 달리 몇 개의 문자를 비교할 지에 대해 n이라는 매개변수를 추가로 받는다.
연산 함수의 직접 구현 (strcpy함수)
char * strcpy(char * dest, const char * src) ;
char* my_strcpy(char* str1, char* str2){
char *ch = str1;
if(str1[0] == 0) return str1;
for(int i=0; i<80; i++){
if(str2[i] == 0) break;
str1[i]=str2[i];
}
return str1;
}
✔ 함수의 원형을 살펴보며 strcpy() 함수를 직접 구현해보자.
✔ 매개변수로 복사받을 곳과 복사할 값의 포인터를 전달받는다.
✔ 함수가 종료했을 때, 복사받을 곳의 첫 주소로 초기화된 char형 포인터 변수를 반환한다.
✔ 복사할 값이 null이 아니라면 대입하고, 주소 위치를 1씩 증가하며 값을 저장한다. (for문 사용)
✔ 복사할 값이 null문자라면 반복문을 종료하고, 해당 위치에 null문자를 저장한다.
✔ 복사 받을 곳의 첫 주소로 초기화된 char형 포인터 변수를 반환하며 함수를 종료한다.
[참고] 한빛미디어-혼자 공부하는 C언어 유튜브 강의 / 엘리스 트랙-혼자 공부하는 C언어 / 길벗-C언어 코딩 도장 / 위키백과
'BackEnd > C' 카테고리의 다른 글
[18일차] 2. 레지스터 변수/주소를 반환하는 함수 (0) | 2021.03.01 |
---|---|
[18일차] 1. 지역 변수와 전역 변수 (0) | 2021.03.01 |
[13-14일차] 문자/문자열 (0) | 2021.02.25 |
[13일차] 배열과 포인터 (0) | 2021.02.23 |
[12일차] 포인터 (0) | 2021.02.23 |