stringstream은 정확히 무엇을합니까?


107

저는 어제부터 C ++를 배우려고 노력하고 있으며이 문서를 사용하고 있습니다 : http://www.cplusplus.com/files/tutorial.pdf (page 32). 문서에서 코드를 찾아 실행했습니다. 가격은 Rs 5.5, 수량은 정수로 입력했는데 출력은 0이었습니다. 5.5와 6을 입력 해 보았는데 출력이 맞았습니다.

// stringstreams
#include <iostream> 
#include <string> 
#include <sstream> 

using namespace std; 

int main () 
{ 
  string mystr; 
  float price = 0; 
  int quantity = 0; 

  cout << "Enter price: "; 
  getline (cin,mystr); 
  stringstream(mystr) >> price; 
  cout << "Enter quantity: "; 
  getline (cin,mystr); 
  stringstream(mystr) >> quantity; 
  cout << "Total price: " << price*quantity << endl; 
  return 0; 
}

질문 : mystring 명령은 정확히 무엇을합니까? 문서에서 인용 :

"이 예에서는 표준 입력에서 간접적으로 숫자 값을 얻습니다. 표준 입력에서 직접 숫자 값을 추출하는 대신 표준 입력 (cin)에서 문자열 객체 (mystr)로 줄을 가져온 다음 정수를 추출합니다. 이 문자열의 값을 int (수량) 유형의 변수로 변환합니다. "

내 인상은 함수가 문자열의 필수 부분을 취하여 입력으로 사용한다는 것입니다.

(여기에서 질문하는 방법을 정확히 모르겠습니다. 저도 프로그래밍이 처음입니다.) 감사합니다.


18
이 예는 좀 이상합니다. 저는 stringstream그런 식으로 사용한 적이 없습니다 . 나는 일반적으로 라인을로드하고 변환 한 다음 부분별로 추출합니다. 그러나 이것은 이미 입력 스트림 cin 있기 때문에 여기에는 분명히 이점이 거의 없습니다 ... 그래서 cin >> price >> quantity;훨씬 더 간단 할 것입니다. 그것은 cplusplus.com 튜토리얼을 사용 하지 않는 좋은 이유가 될 것 입니다.
Bartek Banachewicz

6
그 튜토리얼이 C ++에 대한 첫 노출이라는 사실이 재밌습니다. 돌이켜 보면 꽤 가난하고 불완전합니다. 대신 좋은 책을 제안하겠습니다 .
jrok

@BartekBanachewicz 아마도 그들은 어떻게 stringstream작동 하는지 보여주기 위해 예를 들어야했을 것 입니다. 그것은 아마도 나쁜 것조차도 기괴한 것입니다 =) 그러나 그것은 당신이 문자열을 스트림으로 취급 할 수 있음을 보여줍니다.
luk32

고급 사용에 대한 소개가 아니라면 stringstream분명히 잘못된 예입니다. 그리고 그것이 그렇더라도 그것은 다르게 작성되어야합니다.
j_kubik

1
@trojansdestroy 기반이되는 모든 프리미티브를 이해하지 않고는 stringstream을 이해할 수 없기 때문에 튜토리얼을 읽는 것이 어떻게 도움이되는지 모르겠습니다.
Bartek Banachewicz

답변:


163

때때로 stringstream을 사용하여 문자열과 다른 숫자 유형간에 변환하는 것이 매우 편리합니다. 의 사용법은의 사용법과 stringstream유사 iostream하므로 배우는 데 부담이되지 않습니다.

Stringstreams는 문자열을 읽고 데이터를 문자열에 쓰는 데 사용할 수 있습니다. 주로 문자열 버퍼로 작동하지만 실제 I / O 채널은 없습니다.

stringstream 클래스의 기본 멤버 함수는 다음과 같습니다.

  • str(), 버퍼의 내용을 문자열 유형으로 반환합니다.

  • str(string), 버퍼의 내용을 문자열 인수로 설정합니다.

다음은 문자열 스트림을 사용하는 방법의 예입니다.

ostringstream os;
os << "dec: " << 15 << " hex: " << std::hex << 15 << endl;
cout << os.str() << endl;

결과는 dec: 15 hex: f입니다.

istringstream 거의 동일하게 사용됩니다.

요약하면 stringstream은 독립적 인 I / O 장치처럼 문자열조작 하는 편리한 방법 입니다.

참고로, 클래스 간의 상속 관계는 다음과 같습니다.

문자열 스트림 클래스


19

질문에 답하기 위해. stringstream기본적으로 string객체 를로 처리하고 stream모든 stream함수와 연산자를 사용할 수 있습니다.

주로 형식화 된 출력 / 입력의 장점에 사용되는 것을 보았습니다.

한 가지 좋은 예는 c++숫자를 스트림 객체로 변환하는 구현입니다.

가능한 예 :

template <class T>
string num2str(const T& num, unsigned int prec = 12) {
    string ret;
    stringstream ss;
    ios_base::fmtflags ff = ss.flags();
    ff |= ios_base::floatfield;
    ff |= ios_base::fixed;
    ss.flags(ff);
    ss.precision(prec);
    ss << num;
    ret = ss.str();
    return ret;
};

조금 복잡 할 수도 있지만 꽤 복잡합니다. stringstream객체를 만들고 ss, 플래그를 수정하고,로 숫자를 입력하고 operator<<,을 통해 추출합니다 str(). 나는 그것이 operator>>사용될 수 있다고 생각한다 .

또한이 예에서 string버퍼는 숨겨져 있으며 명시 적으로 사용되지 않습니다. 그러나 가능한 모든 측면과 사용 사례에 대해 작성하는 것은 너무 긴 게시물입니다.

참고 : 나는 아마 누군가에게서 그것을 훔쳐서 다듬었을 것입니다. 그러나 나는 원저자가 언급하지 않았습니다.


3
참고 :의 사용 ret은 불필요하며 return ss.str();.
Matthieu M.

@MatthieuM. RVO가 그렇게 작성되면 시작 될지 또는 ss.str ()에 의해 반환 된 객체가 종료 지점에서 살아남을지 확신 할 수 없었습니다. 이렇게하면 내가 복사본을 만들고 있음을 알 수 있으며 RVO가 작동합니다. 그러나 아마도 당신이 옳을 것입니다.
luk32

실제로 RVO에는 URVO (이름이 지정되지 않은 경우 임시)와 NRVO (이름이 지정된 경우)의 두 가지 형식이 있습니다. 대부분의 컴파일러는 RVO를 구현하지만 일부는 URVO로만 제한합니다 (빌드 옵션에 따라 다름). 그러나 일반적으로 고려해야 할 다른 요소가 많이 있으므로 가능한 가장 깨끗한 코드를 작성하고 RVO가 시작 될지에 대해 너무 걱정하지 않아야합니다.
Matthieu M.

NRVO는 일반적이지만 (URVO와 마찬가지로) 생성자 이동으로 인해 문제가되지 않습니다.
Rapptz

18

에서 C ++ 프라이머 :

istringstream의 유형은 읽고 문자열을 , ostringstream이 기록 문자열을 , 그리고 이제 stringstream은 읽고 쓰는 문자열 .

stringstream 을 사용하는 것이 편리하고 간결한 경우가 있습니다 .

사례 1

그것은에서입니다 솔루션 중 하나 에 대한 이 leetcode 문제 . stringstream 의 사용 이 효율적이고 간결한 매우 적합한 경우를 보여줍니다 .

가정 ab문자열 형식으로 표현 복소수, 우리의 곱셈의 결과를 얻을 ab문자열 형식으로도. 코드는 다음과 같습니다.

string a = "1+2i", b = "1+3i";
istringstream sa(a), sb(b);
ostringstream out;

int ra, ia, rb, ib;
char buff;
// only read integer values to get the real and imaginary part of 
// of the original complex number
sa >> ra >> buff >> ia >> buff;
sb >> rb >> buff >> ib >> buff;

out << ra*rb-ia*ib << '+' << ra*ib+ia*rb << 'i';

// final result in string format
string result = out.str() 

사례 2

또한 주어진 경로 문자열을 단순화 해야하는 leetcode 문제 에서 비롯되었습니다. stringstream을 사용하는 솔루션 중 하나는 제가 본 것 중 가장 우아합니다.

string simplifyPath(string path) {
    string res, tmp;
    vector<string> stk;
    stringstream ss(path);
    while(getline(ss,tmp,'/')) {
        if (tmp == "" or tmp == ".") continue;
        if (tmp == ".." and !stk.empty()) stk.pop_back();
        else if (tmp != "..") stk.push_back(tmp);
    }
    for(auto str : stk) res += "/"+str;
    return res.empty() ? "/" : res; 
 }

stringstream을 사용하지 않으면 이러한 간결한 코드를 작성하기 어려울 것입니다.


2

영숫자 및 정수를 입력했으며 mystr.

그런 다음 첫 번째 토큰 (공백으로 구분)을 int.

첫 번째 토큰은로 변환에 실패한 RS int였으며 myprice에 0을 남겨 두었습니다. 우리는 모두 0 배가 무엇인지 알고 있습니다.

두 번째로 int 값만 입력하면 모든 것이 예상대로 작동했습니다.

코드를 실패하게 만든 것은 가짜 RS였습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.