-
문자열 파싱 연습하기(feat. strtok_s)개발/C·C++ 2024. 7. 4. 16:39
C 표준 함수인 strtok_s는 원본 배열에 건드리기 때문에 const char*을 인수로 받지 않는다. 구분자는 하나의 문자열에 넣어주면 되고 내부 상태값을 유지하기 위해 외부에서 선언한 포인터 변수의 주소를 전달하면 된다. 여기서 말하는 내부 상태 값은 원본 문자열을 검색할 때 다음의 시작 주소다. strtok_s과 동일한 로직을 가지고 사용법도 동일한 MyStrTok을 구현해보자.
#include <stdio.h> char* MyStrTok(char* string, const char* delimeter, char** context); bool IsDelimiter(char ch, const char* delimiter); int main() { char buffer_string[64] = { "data = x + y;\nresult = a * b;" }; const char* delimiter = " +*;\n="; char* token_ptr = nullptr; char* context = nullptr; token_ptr = MyStrTok(buffer_string, delimiter, &context); while(nullptr != token_ptr) { puts(token_ptr); token_ptr = MyStrTok(nullptr, delimiter, &context); } } bool IsDelimiter(char ch, const char* delimiter) { while (*delimiter) { if (*delimiter == ch) { return true; } ++delimiter; } return false; } /* * - context: 다음 검색을 위한 내부 상태 * - 파싱을 완료할 때마다 해당 토큰의 끝 위치 다음을 0으로 초기화 * -> 시작 주소에서부터 끝까지 문자열을 읽을 수 있다 */ char* MyStrTok(char* string, const char* delimiter, char** context) { // 두 번째 호출부터는 context를 사용한다 // 직전 작업에서 *context에는 작업할 문자열의 시작 주소가 들어가야 한다 // 즉, 더 이상 다음 작업을 할 필요 없다면 nullptr으로 초기화해야 한다 char* start = string ? string : *context; // 로직의 탈출 조건 if (nullptr == start) { return nullptr; } // 구분자를 건너뛴다 // 반복문이 끝나면 \0을 만났거나 구분자가 아닌 문자가 등장 while (*start && IsDelimiter(*start, delimiter)) { ++start; } // 문자열의 끝을 만났다면 진행하지 않는다 if ('\0' == *start) { *context = nullptr; return nullptr; } // 다음 구분자때까지 순환하기 위해 시작 주소를 저장 char* token = start; // 구분자를 만나면 반복문을 탈출한다 // find the end of the token while (*start && !IsDelimiter(*start, delimiter)) { ++start; } // 문자열의 끝을 만났다면 진행하지 않는다 if ('\0' == *start) { *context = nullptr; } else { // 현재 위치의 구분자를 '\0'으로 만든다 *start = '\0'; // 다음 작업의 시작 주소 *context = start + 1; } return token; }
'개발 > C·C++' 카테고리의 다른 글
[디스어셈블리 코드] 간단한 메서드 호출과 동작을 해석해보자 (0) 2024.07.13 메모리 정렬, 패딩 그리고 비트필드(feat. 구조체) (0) 2024.07.07 전역변수의 반환 (0) 2022.01.09 shared_ptr 사용할 때 주의 사항 (0) 2022.01.09 전달 참조(보편 참조) (0) 2022.01.08