커맨드 프롬프트 토큰분할 : c++

Drakk·2021년 7월 22일
0

알고리즘노트

목록 보기
1/5
post-thumbnail

✨cmd 토큰 분할

🔥개요

사실 제목을 뭐라지을지 몰라서 커맨드프롬프트 토큰분할 이라고했지만,
정확히는 커맨드 프롬프트의 명령어의 토큰처럼 쪼개는 방법에 관하여 설명하겠습니다.

쉽게 말해서
"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 으로 사용하고있었습니다.

그러다가 "아! 이거는 공백을 기준으로 분할되지??"라고 생각이 들어서 급하게 만든겁니다..ㅋㅋ

profile
C++ / Assembly / Python 언어를 다루고 있습니다!

0개의 댓글