사실 제목을 뭐라지을지 몰라서 커맨드프롬프트 토큰분할 이라고했지만,
정확히는 커맨드 프롬프트의 명령어의 토큰처럼 쪼개는 방법에 관하여 설명하겠습니다.
쉽게 말해서
"cd "C:\test\program schedule" -p"와 같은 문자열을
["cd", "C:\test\program schedule", "-p"]와 같은 식으로 쪼개는 방법입니다.
사실 공백만 고려한다면 위 문장은 다음과 같이 쪼개질 수 있습니다.
["cd", "C:\test\program", "schedule", "-p"]
확실히 위 문장은 실제 cmd에서 이런식으로 공백만 고려한다면 제대로 실행되지 않을것입니다.
따라서, 이에 대한 방법을 찾아봤습니다.
#include <bits/stdc++.h>
std::vector<std::string> Tokenizer(std::string str) {
std::vector<std::string> result;
std::string temp = "";
bool flag = false;
for (int i = 0; i <= str.size(); ++i) {
if (str[i] == '\0') {
result.push_back(temp);
break;
}
else if (str[i] == '\"') {
if (!flag) {
flag = true;
temp = '\"' + temp;
}
else {
if (!temp.empty()) {
temp = temp + '\"';
result.push_back(temp);
}
flag = false;
temp.clear();
}
}
else if (str[i] == ' ') {
if (!flag) {
if (!temp.empty()) result.push_back(temp);
temp.clear();
}
else temp += str[i];
}
else {
temp += str[i];
}
}
return result;
}
int main() {
auto result = Tokenizer("cd \"c:\\program schedule\" to hi \"test\""); //cd "c:\\program schedule" to
for (auto a = result.begin(); a != result.end(); ++a) {
std::cout << *a << '\n';
}
}
std::vector<std::string> result;
std::string temp = "";
bool flag = false;
우선은 result는 분할된 토큰들이 저장된 배열입니다.
temp는 임시로 사용할 문자열입니다.
flag는 ""안에있는 문자열을 구분하기 위해 만든겁니다.
왜냐하면, ""안에있는 문자열들은 공백이있어도 상관없기 때문입니다.
for (int i = 0; i <= str.size(); ++i) {
if (str[i] == '\0') {
result.push_back(temp);
break;
}
else if (str[i] == '\"') {
if (!flag) {
flag = true;
temp = '\"' + temp;
}
else {
if (!temp.empty()) {
temp = temp + '\"';
result.push_back(temp);
}
flag = false;
temp.clear();
}
}
else if (str[i] == ' ') {
if (!flag) {
if (!temp.empty()) result.push_back(temp);
temp.clear();
}
else temp += str[i];
}
else {
temp += str[i];
}
}
우선 이게 들여쓰기가 안되있는데,
왜 안되는지는 흠......
어쨌든,...
첫번째로 필요한 조건분기는 문장의 끝인지를 확인하는것입니다.
문자의 끝이면, 임시문자열을 토큰배열에 넣고 break;
아니면 "가 나오면, flag가 꺼져있을시(첫번째"라면) flag의 값은 참이됩니다.
flag가 켜져있을시, 만약 공백이아니라면 토큰배열에 넣기.
조건분기에서 공백이면서 flag가 꺼져있다면, 토큰배열에넣기
켜져있다면, 임시문자열에 현재문자 넣기
마지막으로 그냥 문자라면 임시문자열에 현재문자 넣기
아래 그림처럼 잘 실행됩니다~~
와우~~
사실 이것을 만들려고 한 진짜이유는
최근 작업중인 프로젝트때문입니다.
cmd에서는 기본적으로 파일의 내용을 직접적으로 수정할수없고,
일부속성의 파일들을 생성할 수 없습니다.
그래서, cmd의 확장판개념으로서 위 작업들을 모두 가능하게하고,
cmd처럼 인터프리터형식으로 실행하는것말고도, 파이썬이나 배치파일처럼 스크립트텍스트를 만들어서 사용자가 실행하고싶을때 그 일련의 작업들을
실행 할 수 있도록 도와주는 프로그램을 만드는중입니다.
사실 이미 좀 프레임워크를 설계해놨는데, 그냥 단순하게 토큰분할을 std::stringstream 으로 사용하고있었습니다.
그러다가 "아! 이거는 공백을 기준으로 분할되지??"라고 생각이 들어서 급하게 만든겁니다..ㅋㅋ