2020. 1. 6. 16:50ㆍC,C++
출처 : http://www.soen.kr/
SoEn:소프트웨어 공학 연구소
www.soen.kr
12-1. 문자열 함수
12-1-가. 문자열 복사
str1, str2, str3가 문자형 배열일 때 다음 코드는 모두 동작하지 않는다.
str1="Korea"; // 문자열 상수를 대입할 수 없음
str1=str2; // 배열끼리도 대입할 수 없음
str3=str1+str2; // +연산자로 문자열을 연결할 수 없음
if (str1 == str2) // ==연산자로 문자열끼리 비교할 수 없음
문자열 함수들은 대부분 string.h에 선언되어 있으므로 이 헤더 파일을 인클루드해야 한다.
다음 함수는 문자 배열에 문자열을 복사하는데 문자열 함수 중에 가장 기본이 되는 함수이다.
char *strcpy(char *dest, const char *src);
dest는 복사될 목적지이고 src는 복사될 원본이므로 이 함수가 하는 동작을 간단하게 표현하면 dest=src라고 할 수 있다.
strcpy 함수는 src 문자열 전체를 널 종료 문자를 만날 때까지 dest로 복사한다. 이에 비해 다음 함수는 지정한 길이만큼만 복사한다.
char *strncpy(char *dest, const char *src, size_t count);
strcpy 함수의 원형과 유사하되 이름 중간에 개수를 지정할 수 있다는 의미의 알파벳 n이 삽입되었으며 세 번째 인수 count가 더 추가되어 있다. count는 복사할 문자 개수를 지정하는데 정확하게 이 개수만큼만 dest로 복사되며 널 종료 문자는 따로 덧붙이지 않는다.
다음은 문자열의 길이를 조사하는 strlen 함수를 알아보자. 문자열의 길이란 문자열 시작 번지에서부터 시작해서 널 종료 문자까지 들어 있는 문자의 개수를 의미한다.
size_t strlen(const char *string);
함수가 조사하는 문자열의 길이는 배열에 실제 저장된 문자의 개수이지 배열의 크기가 아니다. 배열 자체의 크기를 구할 때는 sizeof 연산자를 사용해야 한다.
12-1-나. 문자열 연결
문자열 연결이란 한 문자열 끝에 다른 문자열을 덧붙이는 것이다.
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src,size_t count);
strcat 함수는 dest 문자열 뒤에 src문자열을 덧붙인다.
strncat 함수는 문자열을 합치되 합칠 문자열의 개수를 지정할 수 있다.
12-1-다. 문자열 비교
문자열 비교 함수는 두 문자열이 같은지 다른지, 다르다면 어떤 문자열이 더 큰지를 비교한다.
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t count);
이 함수들은 인수로 주어진 두 문자열을 비교한 후 그 결과를 다음과 같이 정수값 하나로 리턴한다.
s1과 s2가 같으면 0
s1>s2 이면 양수
s1<s2 이면 음수
strncmp 함수는 가운데 n이 끼어 있는데 strncpy, strncat 함수들과 마찬가지로 지정한 개수만큼만 문자열을 비교한다.
영문에는 대소문자라는 것이 있어서 똑같은 문자열이라도 대소문자 구성에 따라 다른 문자열로 인식될 수도 있다.
다음 두 함수는 대소문자 구분없이 문자열을 비교한다.
int stricmp(const char *string1, const char *string2);
int strnicmp(const char *string1, const char *string2, size_t count);
함수명 중간에 i가 삽입되어 있는데 여기서 i는 Ignore, 즉 대소문자 구성을 무시하고 비교한다는 뜻이다.
12-1-라. 문자열 검색
문자열 검색 함수는 문자열 중 특정 문자나 부분 문자열의 위치를 찾아 주는데 다음과 같은 것들이 있다. 첫 번째 인수로 검색 대상 문자열을 주고 두 번째 인수로 검색할 문자(열)을 주며 리턴값은 모두 문자형 포인터이다.
char *strchr(const char *string, int c);
char *strrchr(const char *string, int c);
char *strstr(const char *string, const char *strSearch);
char *strpbrk(const char *string, const char *strCharSet );
char *strtok(char *strToken, const char *strDelimit);
str이 "notebook"일 때 strchr(str,'b') 함수는 다음과 같이 동작한다.
문자형 포인터를 리턴하므로 이 번지를 대입한 후 검색된 위치에 대해 어떤 작업을 할 수 있다. 다음 코드는 "notebook" 문자열에서 b 문자를 찾아 c로 바꾼다. 결국 str은 "notecook"이 될 것이다.
char str[]="notebook";
char *ptr=strchr(str,'b');
*ptr='c';
문자열중 특정 문자의 위치는 관심없고 단지 문자의 포함 여부만 알고 싶을 때는 리턴값이 NULL인지 아닌지만 비교하면 된다.
if (strchr(Name,'a')!=NULL) {
puts("이름에 a문자가 포함되어 있군요.");
}
strchr 함수는 항상 주어진 문자열의 선두에서부터 문자를 찾는다. 이에 비해 strrchr 함수는 문자열의 뒤에서부터 문자를 검색하는데 함수명에 포함된 r은 rear, 즉 뒤쪽이라는 뜻이다.
두 문자열이 정확하게 같은지 비교해서는 안되며 부분 문자열이 포함되어 있는지를 조사해야 하는데 이럴 때 바로 strstr 함수가 사용된다.
if (strstr(language,"영어") != NULL) { 영어 가능함 }
strstr 함수는 부분 문자열을 검색하므로 "영어, 일본어"는 물론이고 "일본어, 영어"와 같이 순서를 바꿔 써도 이 문자열이 포함되어 있는지 검색할 수 있다.
strpbrk 함수는 첫 번째 인수로 주어진 문자열에서 두 번째 인수로 주어진 문자열에 속해 있는 문자 중 가장 먼저 발견된 문자를 찾아 그 번지를 리턴한다.
char str[]="Four score and seven years ago";
char *ptr=strpbrk(str,"def");
str에 긴 문자열이 들어 있는데 이 문자열 중에서 d나 e나 f중 가장 먼저 발견되는 문자를 찾아 ptr에 대입한다. 이 경우 str[9]에 있는 'e'가 검색될 것이다.
strtok 함수는 문자열을 토큰으로 잘라낸다. 예를 들어 "서울/대전/대구/부산" 문자열을 "/" 구분자로 자르면 서울, 대전, 대구, 부산 4개의 문자열로 분할할 수 있다.
실행 결과는 다음과 같다.
strtok 함수는 최초 호출될 때 문자열의 첫 번째 토큰을 찾고 두 번째 토큰 위치를 NULL문자로 만든 후 토큰의 포인터를 리턴한다.
(** 다음과같이 좀더 가독성 좋게 만들 수도 있는 것 같다. **)
12-1-마. 문자열 변환
문자열 변환이란 문자열의 내용을 일정한 규칙에 따라 바꾸는 것이다. 다음 다섯 가지의 함수가 있는데 아주 쉬우므로 간략하게 설명하도록 한다.
char *strset(char *string, int c);
char *strnset(char *string, int c, size_t count);
char *strlwr(char *string);
char *strupr(char *string);
char *strrev(char *string);
strset 함수는 문자열을 c문자로 가득 채운다.
str이 "password" 문자열을 가질 때 strset(str,'*')는 이 문자열을 "********"로 바꿀 것이다.
strnset 함수는 개수를 지정할 수 있다는 것만 다르다.
strlwr 함수는 모든 문자를 소문자로 바꾸며 strupr 함수는 모든 문자를 대문자로 바꾼다.
strrev 함수는 문자열을 거꾸로 뒤집는다. 즉, 제일 처음에 있는 문자를 마지막 문자와 교환하고 두 번째 문자는 마지막 두 번째 문자와 교환하는 식이다.
12-1-바. 문자 관리 함수
다음은 문자열을 구성하는 개별 문자들을 관리하는 함수에 대해 알아보자.
이 함수들은 인수로 전달된 문자가 특정 그룹에 속하는지 조사하는데 그룹에 속하면 0이 아닌 값을 리턴하고 그렇지 않다면 0을 리턴한다.
특정 문자가 알파벳인지, 숫자인지 등을 판단하고 싶을 때 이 함수들을 호출한다.
다음 두 함수는 영문 대소문자를 변환한다.
int tolower(int c);
int toupper(int c);
만약 c가 영문자가 아니라면 아무 동작도 하지 않으며 c를 그대로 리턴한다.
12-1-사. 메모리 관리 함수
다음 함수들은 메모리 관리 함수들이다
void *memcpy(void *dest, const void *src, size_t count);
int memcmp(const void *buf1,const void *buf2,size_t count);
void *memchr(const void *buf,int c,size_t count);
void *memset(void *dest,int c,size_t count);
void *memmove(void *dest,const void *src,size_t count);
strcpy에 대응되는 memcpy, strcmp에 대응되는 memcmp 등의 함수들이 있는데 기본적인 동작 방식은 대응되는 문자열 함수와 같다고 생각하면 된다. 다만 몇 가지 점만 다른데 메모리 관리 함수들과 문자열 관리 함수들의 차이점은 다음과 같다.
1) 인수와 리턴값의 타입이 다르다. 문자열 관리 함수들은 항상 문자열을 대상으로 하므로 취하는 인수나 리턴값이 대부분 char *형이지만 메모리 조작 함수들은 임의의 값을 대상으로 하기 때문에 인수와 리턴값이 모두 void *형이다.
2) 문자열은 시작 번지만 알려 주면 널 종료 문자를 끝으로 인식하기 때문에 길이를 별도로 알려줄 필요가 없다. 하지만 메모리 관리 함수는 길이를 알려 주지 않으면 어디까지가 작업 대상인지를 알지 못한다.
int ar[10];
memset(ar,0,sizeof(ar));
배열을 선언하면서 초기화하지 않았거나 또는 실행중에 이미 값이 저장된 배열을 모두 특정 값으로 채우고자 할 때 memset 함수를 사용한다.
메모리끼리 복사할 때는 memcpy 함수를 사용한다. 복사할 원본과 대상, 그리고 복사할 길이를 인수로 전달하면 두 메모리의 내용을 완전히 똑같이 만들어 준다.
배열은 서로 대입할 수 없으며 배열의 사본을 만들려면 배열 요소끼리 개별적으로 대입해야 하는데 memcpy 함수를 사용하면 배열끼리도 한 번에 복사할 수 있다.
(** 여기서 memcpy가 값을 복사하는건지 주소를 복사하는건지 궁금했다. **)
실험을 위한 코드
실험결과 주소를 복사하는게 아니라 값을 복사한다는 걸 알게 됨.
메모리 관리 함수중에 가장 재미있고도 실용적인 함수는 memmove 함수이다. 이 함수는 메모리의 내용을 지정한 길이만큼 다른 곳으로 옮긴다.
12-2-가. 정수와 문자열
수치와 문자열은 데이터 타입이 다르며 따라서 메모리에 기억되는 모양도 상당히 다르다. 다음 두 변수를 보자.
int num=123;
char str[]="123";
두 변수 모두 123으로 초기화되었는데 정수형 변수 num은 수치값 123을 가지고 있고 문자 배열 str은 문자열 "123"을 가지고 있다. 이 두 값은 외형적인 모양이 비슷해 보이지만 내부적으로는 완전히 다른 값이다.
문자열과 수치는 내부적인 모양이 완전히 다르기 때문에 상호 대입하거나 연산할 수 없다.
콘솔 환경에서는 이런 두 형식의 차이점을 어느 정도 완충해주는 장치가 있다. 화면으로 직접 출력 가능한 형식은 문자열뿐인데 printf 함수는 %d, %f 서식에 의해 정수나 실수를 문자열로 바꾸어 출력한다.
다음 함수들은 정수를 문자열로 변환한다.
char *itoa(int value, char *string, int radix);
char *ltoa(long value, char *string, int radix);
char *ultoa(unsigned long value, char *string, int radix);
(** 그 외에도 sprintf 라는 방법도 있는 듯 하다. **)
https://dojang.io/mod/page/view.php?id=388
C 언어 코딩 도장: 46.4 정수를 문자열로 변환하기
이번에는 정수를 문자열 형태로 변환하는 방법입니다. sprintf 함수를 사용하면 정수를 문자열로 변환할 수 있습니다(stdio.h 헤더 파일에 선언되어 있습니다). sprintf(문자열, "%d", 정수); sprintf(문자열, "%x", 정수); sprintf(문자열, "%X", 정수); 다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요. integer_to_string.c #define _CRT_SECURE_NO_WARNINGS // spr
dojang.io
itoa는 c언어 표준 함수는 아니다. 표준 함수는 sprintf라 한다.
다음은 문자열을 정수로 바꾸는 함수에 대해 알아보자.
int atoi(const char *string);
long atol(const char *string);
long strtol(const char *nptr, char **endptr, int base);
unsigned long strtoul(const char *nptr, char **endptr, int base);
문자열 str에 "123"이 저장되어 있을 때 atoi(str)은 수치값 123을 리턴한다.
atoi("123"), atoi("-78") 이런 식의 문자열을 전달해야 제대로 변환된다. atoi("aaa")처럼 수치가 아닌 문자열을 전달할 경우 atoi는 변환할 수 없다는 의미로 0을 리턴한다.
만약 수치와 문자열이 섞여 있다면 atoi는 에러를 리턴하는 대신 변환 가능한 부분까지만 변환한다. 예를 들어 atoi("12month")를 호출하면 12가 리턴된다.
12-2-나. 실수와 문자열
실수는 정수에 비해 소수점 이하를 가질 뿐만 아니라 부동 소수점 표기법이 다소 복잡해서 정수보다는 변환하기가 훨씬 더 까다롭다. 다음 함수들은 실수를 문자열로 변환한다.
char *gcvt(double value, int digits, char *buffer);
char *ecvt(double value, int count, int *dec, int *sign);
char *fcvt(double value, int count, int *dec, int *sign);
다음 함수는 문자열을 실수로 변환한다. 두 함수는 기능이 거의 동일하되 strtod 함수는 변환 불가 문자를 만날 때 그 위치를 endptr로 리턴한다는 정도만 다르다. 편의성면에서는 atof가 좀 더 사용하기 쉽다.
double atof(const char *string);
double strtod(const char *nptr, char **endptr);
'C,C++' 카테고리의 다른 글
[C] C언어 공부하기 11. 배열과 포인터 (0) | 2020.01.06 |
---|---|
[C] C언어 공부하기 10. 포인터 (0) | 2020.01.06 |
[C] C언어 공부하기 9. 배열 (0) | 2020.01.02 |
[C] C언어 공부하기 8. 표준 함수 (0) | 2020.01.02 |
[C] C언어 공부하기 7.지역변수 (0) | 2020.01.02 |