문자열 split 처리만 잘 해주면 어려울 것 없는 문제였다
(사실 문자열만 마주치면 머리가 하얘지는 나라서.. 문자열 문제랑 친해지려고 고른 문제다)
C++에는 split이라는 함수는 없어서 적절히 조치를 취해줘야 하는데
처음에는 find와 substr을 활용해서 풀었고 코드가 좀 복잡해서
다른 방법을 찾아보니 stringstream 활용하는 방법이 있었다
🚨 사실 substr(pos, count) 가 [pos, count) 범위의 문자열을 반환하는 건 줄로 잘못 알고 있어서 삽질 좀 했다.. [pos, pos+count) 가 맞는 반환 범위다..
그런데 또 특이한 게 (?)
코드 가독성은 몰라도 효율성은 stringstream 보다 find & substr이 더 좋게 나타났다
stringstream은 일단 copy가 한 번 들어가서 그런 것 같다
find와 substr, getline 관련 내용은
👉 [C++] 유용한 라이브러리 및 함수 정리 - #include <string> 파트 이 포스트를 참고하면 될듯하다
#include <sstream>
필요// example #1
string original = "Hello World!";
stringstream ss(original);
char ch;
while (ss >> ch) {
cout << ch << " "; // H e l l o W o r l d !
}
string temp;
while (ss >> temp) {
cout << temp << endl;
}
// example #2
stringstream ss;
ss.str(original);
string str;
while (ss >> str) {
cout << str << endl;
// Hello
// World!
}
#include <string>
#include <vector>
#include <unordered_map>
using namespace std;
// Solution #1) find & substr 활용
vector<string> solution(vector<string> record) {
vector<string> answer;
int N = record.size();
vector<string> actionVec;
vector<string> uidVec;
unordered_map<string, string> uidMap;
for (int i=0; i<N; i++) {
int firstDelim = record[i].find(' ');
string action = record[i].substr(0, firstDelim);
actionVec.push_back(action);
string uid;
if (action == "Leave") {
uid = record[i].substr(firstDelim+1);
}
else {
int secondDelim = record[i].find(' ', firstDelim+1);
uid = record[i].substr(firstDelim+1, secondDelim-firstDelim-1);
string nickname = record[i].substr(secondDelim+1);
uidMap[uid] = nickname;
}
uidVec.push_back(uid);
}
for (int i=0; i<N; i++) {
string result = "";
result += uidMap[uidVec[i]];
if (actionVec[i] == "Enter") { result += "님이 들어왔습니다."; }
else if (actionVec[i] == "Leave") { result += "님이 나갔습니다."; }
else if (actionVec[i] == "Change") { continue; }
answer.push_back(result);
}
return answer;
}
#include <string>
#include <vector>
#include <unordered_map>
#include <sstream>
using namespace std;
// Solution #2) stringstream 활용
/*
split 함수도 만들어 보았으나
이 문제는 delimiter가 공백이므로
getline 없이 stringstream 만으로도 풀 수 있다
vector<string> split(string str, char delim) {
vector<string> answer;
stringstream ss(str);
string temp;
while (getline(ss, temp, delim)) {
answer.push_back(temp);
}
return answer;
}
*/
vector<string> solution(vector<string> record) {
vector<string> answer;
vector<pair<string, string>> actionIdVec; // {action, uid}
unordered_map<string, string> uidNameMap; // {uid: name}
int N = record.size();
for (int i=0; i<N; i++) {
// vector<string> splitVec = split(record[i], ' ');
vector<string> splitVec;
stringstream ss(record[i]);
string temp;
while (ss >> temp) {
splitVec.push_back(temp);
}
actionIdVec.push_back({splitVec[0], splitVec[1]});
if (splitVec[0] != "Leave") {
uidNameMap[splitVec[1]] = splitVec[2];
}
}
for (int i=0; i<N; i++) {
string result = "";
result += uidNameMap[actionIdVec[i].second];
if (actionIdVec[i].first == "Enter") { result += "님이 들어왔습니다."; }
else if (actionIdVec[i].first == "Leave") { result += "님이 나갔습니다."; }
else if (actionIdVec[i].first == "Change") { continue; }
answer.push_back(result);
}
return answer;
}