Lv 0. 문자열 계산하기

https://school.programmers.co.kr/learn/courses/30/lessons/120902

#include <string>
#include <vector>

using namespace std;

int solution(string str) {
    int answer = 0;
    int sign=1;
    vector<int> v;
    string tmp;
    for(auto c: str){
        if(c==' '){
            if(tmp!=""){
                v.emplace_back(sign*stoi(tmp));
                tmp="";    
            }  
        }
        else if(c=='-'){
            sign=-1;
        }
        else if(c=='+'){
            sign=1;
        }
        else{ //그냥 글자일때
            tmp+=c;
        }
    }
    v.emplace_back(sign*stoi(tmp));
    for(auto c: v) answer+=c;
    return answer;
}

위의 풀이가 내가 작성해서 제출한 풀이이고, 이 풀이를 생각할때, 뭔가 이 문자열 전체를 받아들여서 하는 방법이 있었던것 같은데 생각이 나지 않아서 경우들을 나누어서 위와 같은 코드를 작성해서 프로그램을 만들었다.

위와 같은 풀이를 제출한뒤, 다른 사람의 풀이를 보니까 내가 처음에 이 문제를 접했을때 생각했던데로 전체적인 string에서 흐름을 통해서 문제를 해결하는 방법으로 푼 방법이 가장 위에 있었으며, 거기서 사용한 방법은 stringstream을 이용하는 풀이였다.

아직 나에게 있어서 stringstream을 이용하는 잘 생각이 나지 않는듯 하다.

다른 사람의 풀이에서 가장 위에 올라와 있는 풀이를 첨부해보면,

#include <string>
#include <vector>
#include <sstream>
using namespace std;

int solution(string my_string) {
    int answer = 0;

    stringstream ss;
    ss.str(my_string);

    ss>>answer;

    char ch;
    int tmp = 0;
    while(ss)
    {
        if(ch == '+')
        {
            answer += tmp;
        }
        else if(ch == '-')
        {
            answer -= tmp;
        }
        ss >> ch >> tmp;
    }
    return answer;
}

이와 같은 코드를 볼 수 있는데, 위의 코드에 대한 해석을 돕기 위해서 지피에 해당 코드에 대한 분석을 요구하면

 

 

=====================
이 코드는 문자열 my_string에 포함된 숫자와 연산자를 파싱하여 계산하는 프로그램입니다. 주어진 문자열에는 연속된 숫자와 '+' 또는 '-' 연산자가 포함되어 있습니다.

  1. stringstream 객체인 ss를 생성하고, 이를 문자열 my_string으로 초기화합니다.
  2. ss를 사용하여 첫 번째 숫자를 answer에 저장합니다. 이는 문자열에서 첫 번째 숫자를 읽어온 것입니다.
  3. char 타입의 변수 chint 타입의 변수 tmp를 선언합니다. 이들은 현재 처리 중인 연산자와 숫자를 저장하는 데 사용됩니다.
  4. while 루프를 사용하여 문자열 파싱을 수행합니다. 파싱은 다음과 같이 동작합니다:
    • ch에 '+' 또는 '-' 연산자를 읽어옵니다.
    • tmp에 다음 숫자를 읽어옵니다.
    • 읽어온 연산자와 숫자를 기반으로 answer를 갱신합니다. '+' 연산자면 answer += tmp, '-' 연산자면 answer -= tmp를 수행합니다.
    • 다음 연산자와 숫자를 읽어올 때까지 반복합니다.
    • 루프를 빠져나가면 최종 계산 결과가 answer에 저장되어 반환됩니다.

#이 코드는 문자열에서 수식을 읽어와 계산하는 기본적인 방법을 보여줍니다. 문자열 파싱 및 연산은 입력에 따라 다양한 예외 상황을 처리해야 할 수 있으므로 실제 응용 프로그램에서는 더 강력한 오류 처리와 안정성을 추가해야 할 것입니다.

===================================

 

 

위와 같은 답변을 얻을 수 있다.

위에서 얻을 수 있는 정보들을 통해서 stringstream을 이용해서 위와 같은 문제를 해결하는 방법에 대해서 기록해보자면,
stringstream ss; 형태로 객체를 선언하고,
ss.str(my_string); 형태로, str() 함수를 이용해서 my_string 이라는 이름으로 주어지는 string으로 stringstream 객체를 초기화,
그리고 나서
먼저 ss>>answer; 을 통해서 가장 앞에 있던 숫자를 answer에 저장하고, 그 뒤에 이제 순차적으로 처리를 한다는걸 알 수 있다.
이와 관련해서 추가적으로 어떤식으로 변해가는지에 대해서 검색해보면,

 

 

=====================
ss >> answer를 실행한 후에는 ss 스트림 내에서 현재 읽지 않은 나머지 내용이 남아 있습니다. ss 스트림은 입력 데이터를 순차적으로 읽어 나가는데, ss >> answerss에서 데이터를 읽어 answer에 저장한 것입니다. 따라서 현재 ss 스트림의 내용은 answer를 읽은 후의 상태입니다.

예를 들어, "123+456"이라는 문자열을 ss에 넣고 ss >> answer를 실행하면, answer에는 123이 저장되고, ss에는 "123+456"에서 "123"을 제외한 "+""456" 부분이 남게 됩니다. 이제 ss에서 "+""456"을 읽을 수 있게 됩니다.

#계속해서 ss >> ch >> tmp를 통해 "+""456"을 읽어오고, ch에는 "+"가, tmp에는 456이 저장됩니다. 이후 루프에서 연산을 수행하고 나면, ss"+""456"을 모두 읽어서 내용이 더 이상 없게 됩니다.

======================

 

이와 같은 정보를 볼때, stringstream이라는 객체에서 ch와 tmp에 순차적으로 ss>>ch>>tmp; 을 이용해서 계속 값들을 저장해가면서 stringstream에서 다음 값들로 넘어가면서 위와 같은 연산을 수행한다는걸 알 수 있다.

 

위의 코드와 유사하지만 stringstream을 사용하는 다른 풀이가 있는데, 이 코드 또한 꽤 깔끔한 느낌을 주고, !ss.eof() 을 이용하는 형태로 while 문을 돌리는 코드가 있어서 첨부해본다.

#include <string>
#include <vector>
#include <sstream>

using namespace std;

int solution(string my_string) {
    stringstream ss(my_string);
    char op; int num;

    int result;
    ss >> result;
    while (!ss.eof()) {
        ss >> op;
        ss >> num;

        if (op == '+') result += num;
        else result -= num;
    }

    return result;
}

https://cplusplus.com/reference/sstream/stringstream/stringstream/

  Comments,     Trackbacks