728x90
[ strtok ]
- 기준 문자열에 포함된 문자를 기준으로 나눠줌
- 문자열 자체를 찾는게 아닌, 포함된 문자 하나하나가 기준이 됨
- strtok(str, "#@!")로 썼을 때, '#'이 나오거나 '@'가 나오거나 '!'가 나오면 끊어줌
- 끊고난 다음 위치를 기억하고 있다가 문자열 대신 NULL을 넘겨주면 그 위치부터 다시 시작
- NULL이 아닌 새로운 문자열을 제공해주면 리셋
- 검색된 기준 문자는 '\0'로 바꿔줌 (원본이 훼손됨)
- 시작위치부터 구분자가 연속으로 나올 경우 무시하고 지나감 (####과 같이)
- 문자열의 끝에 도달하면 NULL값 반환
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "abc#def@@#@ !g";
char* ptr = strtok(str, "#@!");
printf("%s\n", ptr); // "abc"
ptr = strtok(NULL, "#@!");
printf("%s\n", ptr); // "def"
ptr = strtok(NULL, "#@!");
printf("%s\n", ptr); // " "
ptr = strtok(NULL, "#@!");
printf("%s\n", ptr); // "g"
ptr = strtok(NULL, "#@!");
printf("%s\n", ptr); // (null)
}
구현식은 아래와 같습니다. 실제 코드는 아니고 직접 짜본 코드입니다. strtok는 한 번 실행되면 계속 마지막 기준점을 저장하고 있으므로 정적변수(static)를 사용합니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* my_strtok(char* str, char* find);
int main()
{
/* 기본 strtok */
char str[] = "abc#def@@#@ !g";
char* ptr = strtok(str, "#@!");
printf("%s\n", ptr); // "abc"
ptr = strtok(NULL, "#@!");
printf("%s\n", ptr); // "def"
ptr = strtok(NULL, "#@!");
printf("%s\n", ptr); // " "
ptr = strtok(NULL, "#@!");
printf("%s\n", ptr); // "g"
ptr = strtok(NULL, "#@!");
printf("%s\n", ptr); // (null)
printf("\n↓ 새로 만든 함수 ↓ \n");
/* 새로 만든 my_strtok */
char str2[] = "abc#def@@#@ !g";
char* ptr2 = my_strtok(str2, "#@!");
printf("%s\n", ptr2); // "abc"
ptr2 = my_strtok(NULL, "#@!");
printf("%s\n", ptr2); // "def"
ptr2 = my_strtok(NULL, "#@!");
printf("%s\n", ptr2); // " "
ptr2 = my_strtok(NULL, "#@!");
printf("%s\n", ptr2); // "g"
ptr2 = my_strtok(NULL, "#@!");
printf("%s\n", ptr2); // (null)
}
char* my_strtok(char* str, char* find)
{
static char* startPoint = NULL; // 리턴해줄 위치
static char* tokPoint = NULL; // 다음 검색 시작점 위치
// 원본 문자열 새로 들어오면 처음 위치로 초기화
if (str != NULL) {
startPoint = str;
tokPoint = str;
}
// 원본 문자열이 없을 경우 시작 위치를 이전 실행에서 저장된 tokPoint위치로 옮겨줌
else
startPoint = tokPoint;
int findNum = strlen(find);
int strNum = strlen(startPoint);
// 원본 문자열에 남아 있는 문자가 없을 때 NULL값 반환
if (strNum == 0)
return NULL;
// 찾을 문자열이 없을 때 startPoint 그대로 반환
else if (findNum == 0)
return startPoint;
// 찾을 문자열 길이로 배열 생성해서 기준 문자들을 하나씩 넣어줌
char* list;
if ((list = (char*)malloc(sizeof(char) * findNum)) == NULL)
return NULL;
for (int i = 0; i < findNum; i++)
list[i] = find[i];
// 구분자 찾기
int w = 0, status1 = 0, status2 = 0, i;
for (i = 0; startPoint[i] != '\0'; i++) {
// 한글자씩 비교
for (int j = 0; j < findNum; j++)
// 같은 값을 찾았을 경우
if (startPoint[i] == list[j]) {
status1 = 1; // 찾았음을 표시하고 break;
break;
}
// 찾았는데 처음 값부터 일치했을 경우는 무시하고 넘어감
if (status1 == 1 && status2 == 0) {
status1 = 0;
continue;
}
// 못찾고 넘어왔을 경우
else if (status1 == 0 && status2 == 0) {
status2 = 1; // 하나라도 구분자 사이에 값이 있으므로 상태값 변경
w = i; // startPoint의 위치가 바껴야 하므로 첫 값 위치 저장
continue;
}
// 사이에 값이 있으면서 구분자를 찾았을 경우 break
else if (status1 == 1 && status2 == 1) {
break;
}
}
// 문자열 마지막이라면 찾은 위치를 tokPoint로 지정 (다음번 시작 위치)
if (startPoint[i] == '\0')
tokPoint = &startPoint[i];
// 마지막이 아니라면 찾은 위치 다음을 tokPoint로 지정 (다음번 시작 위치)
else {
tokPoint = &startPoint[i + 1];
startPoint[i] = '\0'; // 찾은 문자를 '\0'로 변경
}
// 다 쓴 리스트 메모리 제거
free(list);
// 연속된 구분자를 지나왔을 수 있으므로 구분자 이후 첫 값(w)을 시작 위치로 잡아서 리턴
return startPoint = &startPoint[w];
}
728x90
'▸C언어 > 기본함수 및 구현식' 카테고리의 다른 글
string.h_strcat, strncat_문자열 합치기 (구현식 포함) (2) | 2020.01.15 |
---|---|
string.h_strlen_문자열 길이 구하기 (구현식 포함) (2) | 2020.01.15 |
stdio.h_파일제어 (fopen, fopen_s, fclose) (0) | 2019.12.05 |
string.h_strcmp, strcnmp_문자열 비교 (구현식 포함) (0) | 2019.12.05 |
댓글