문자열의 단어를 어떻게 반복합니까?
질문
나는 문자열의 단어를 반복하려고 노력하고 있습니다.
문자열은 공백으로 구분 된 단어로 구성된 것으로 가정 할 수 있습니다.
C 문자열 함수 또는 그런 종류의 문자 조작 / 액세스에 관심이 없습니다.또한 귀하의 답변에서 효율성에 우위를 우아하게 제시하십시오.
내가 가진 가장 좋은 솔루션은 다음과 같습니다.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
string s = "Somewhere down the road";
istringstream iss(s);
do
{
string subs;
iss >> subs;
cout << "Substring: " << subs << endl;
} while (iss);
}
이 일을하는 더 우아한 방법이 있습니까?
답변
나는 이것을 구분 기호로 분할하기 위해 이것을 사용합니다.첫 번째는 사전 구축 된 벡터에서 결과를 두 번째로 올리면 새로운 벡터를 반환합니다.
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
template <typename Out>
void split(const std::string &s, char delim, Out result) {
std::istringstream iss(s);
std::string item;
while (std::getline(iss, item, delim)) {
*result++ = item;
}
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
이 솔루션은 빈 토큰을 건너 뛰지 않으므로 다음과 같은 4 가지 항목이 비어 있습니다.
std::vector<std::string> x = split("one:two::three", ':');
답변
그것이 가치가있는 것에 대해, 표준 도서관 시설에서만 의존하는 입력 문자열에서 토큰을 추출하는 또 다른 방법이 있습니다.그것은 STL의 디자인 뒤에있는 힘과 우아함의 예입니다.
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
int main() {
using namespace std;
string sentence = "And I feel fine...";
istringstream iss(sentence);
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
ostream_iterator<string>(cout, "\n"));
}
추출 된 토큰을 출력 스트림에 복사하는 대신 동일한 일반 복사 알고리즘을 사용하여 컨테이너에 하나를 삽입 할 수 있습니다.
vector<string> tokens;
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
back_inserter(tokens));
... 또는 벡터 직접 벡터를 만듭니다.
vector<string> tokens{istream_iterator<string>{iss},
istream_iterator<string>{}};
답변
부스트를 사용하는 가능한 솔루션은 다음과 같습니다.
#include <boost/algorithm/string.hpp>
std::vector<std::string> strs;
boost::split(strs, "string to split", boost::is_any_of("\t "));
이 접근법은 StringStream 접근 방식보다 더 빠릅니다.그리고 이것은 일반적인 템플릿 기능이므로 모든 종류의 구분 기호를 사용하여 다른 유형의 문자열 (WCHAR 등 또는 UTF-8)을 분할하는 데 사용할 수 있습니다.
자세한 내용은 설명서를 참조하십시오.
답변
#include <vector>
#include <string>
#include <sstream>
int main()
{
std::string str("Split me by whitespaces");
std::string buf; // Have a buffer string
std::stringstream ss(str); // Insert the string into a stream
std::vector<std::string> tokens; // Create vector to hold our words
while (ss >> buf)
tokens.push_back(buf);
return 0;
}
답변
코드 크기에 대한 모든 효율성을 희생시키고 우아함 유형으로 "효율적"을 볼 수있는 사람들에게는 다음과 같은 것입니다.
template < class ContainerT >
void tokenize(const std::string& str, ContainerT& tokens,
const std::string& delimiters = " ", bool trimEmpty = false)
{
std::string::size_type pos, lastPos = 0, length = str.length();
using value_type = typename ContainerT::value_type;
using size_type = typename ContainerT::size_type;
while(lastPos < length + 1)
{
pos = str.find_first_of(delimiters, lastPos);
if(pos == std::string::npos)
{
pos = length;
}
if(pos != lastPos || !trimEmpty)
tokens.push_back(value_type(str.data()+lastPos,
(size_type)pos-lastPos ));
lastPos = pos + 1;
}
}
일반적으로 STD :: Vector
이 페이지에서 가장 빠른 토큰 화하는 것보다 빠르게 두 배 이상이며 다른 사람들보다 거의 5 배 빠릅니다.또한 완벽한 매개 변수 유형을 사용하면 추가 속도가 증가하는 모든 문자열 및 목록 복사본을 제거 할 수 있습니다.
또한 (극히 비효율적 인) 결과의 반환을하지는 않지만 오히려 토큰을 참조로 전달하여 사용자가 그렇게 원한다면 여러 호출을 사용하여 토큰을 빌드 할 수 있습니다.
마지막으로 마지막 선택적 매개 변수를 통해 결과에서 빈 토큰을 트리밍할지 여부를 지정할 수 있습니다.
필요한 모든 것은 std :: string ... 나머지는 선택 사항입니다.스트림 또는 부스트 라이브러리를 사용하지 않지만 자연스럽게 이러한 외래 유형을 수락 할 수있을만큼 유연합니다.
답변
또 다른 해결책이 있습니다.컴팩트하고 합리적으로 효율적입니다.
std::vector<std::string> split(const std::string &text, char sep) {
std::vector<std::string> tokens;
std::size_t start = 0, end = 0;
while ((end = text.find(sep, start)) != std::string::npos) {
tokens.push_back(text.substr(start, end - start));
start = end + 1;
}
tokens.push_back(text.substr(start));
return tokens;
}
문자열 분리기, 넓은 문자열 등을 처리하기 위해 쉽게 템플릿을 쉽게 사용할 수 있습니다.
""단일 빈 문자열을 분할하고 분할 "(즉, SEP)은 두 개의 빈 문자열을 생성합니다.
빈 토큰을 건너 뛰도록 쉽게 확장 할 수도 있습니다.
std::vector<std::string> split(const std::string &text, char sep) {
std::vector<std::string> tokens;
std::size_t start = 0, end = 0;
while ((end = text.find(sep, start)) != std::string::npos) {
if (end != start) {
tokens.push_back(text.substr(start, end - start));
}
start = end + 1;
}
if (end != start) {
tokens.push_back(text.substr(start));
}
return tokens;
}
빈 토큰을 건너 뛰는 동안 여러 구분 기호에서 문자열을 분할하면이 버전이 사용될 수 있습니다.
std::vector<std::string> split(const std::string& text, const std::string& delims)
{
std::vector<std::string> tokens;
std::size_t start = text.find_first_not_of(delims), end = 0;
while((end = text.find_first_of(delims, start)) != std::string::npos)
{
tokens.push_back(text.substr(start, end - start));
start = text.find_first_not_of(delims, end);
}
if(start != std::string::npos)
tokens.push_back(text.substr(start));
return tokens;
}
출처:https://stackoverflow.com/questions/236129/how-do-i-iterate-over-the-words-of-a-string
최근댓글