벌써 13일 차네요. 꾸준히 무언가를 한다는 게 참 힘든 것 같아요. 열심히 끝까지 해서 달라진 나의 모습을 보고 싶습니다.
문제 설명
단어들의 리스트가 주어질 때, 이를 반대로 뒤집어서 출력하는 프로그램을 작성하는 문제입니다.
생각 흐름
문제를 보았을 때, 공백이 포함된 문자열이 주어지고 공백으로 구분된 문자들을 거꾸로 출력한다는 점을 보았을 때,
이 친구가 공백이 포함된 문자열을 다룰 줄 아는지,
선입후출의 개념인 stack 자료구조를 잘 사용할 수 있는지를 보는 문제라는 게 바로 보였던 것 같습니다.
우선, 전체 케이스의 개수 n을 받아오고 이를 반복문을 돌려 공백 포함된 문자열을 getline() 함수를 통해서 받아주었습니다.
그리고 string 변수인 s, tmp, ans를 각각 선언해서 받아온 문자열의 공백을 기준으로 stack 자료구조에 일일이 집어넣어 주었습니다. 공백을 발견했을 때, 그전까지 문자열을 tmp라고 하고 이를 ans에 선입후출 방식으로 stack 저장하며 문제를 풀었습니다.
이 문제의 핵심은 getline() 함수를 사용할 때 버퍼 마지막에 "\n"가 들어가는 것을 아느냐, stack 자료구조를 잘 활용할 수 잇느냐, 공백 포함 문자열을 잘 다룰 줄 아느냐인 것 같았습니다.
#include <iostream>
#include <string>
#include <stack>
using namespace std;
int main () {
ios_base::sync_with_stdio();
cin.tie(); cout.tie();
int n; // 전체 테스트 개수 n
cin >> n;
cin.ignore();
for (int i = 1; i <= n; i++) {
string s, tmp, ans; // 전체 문자열 s, 자를 문자열 tmp, 정답 문자열 ans
getline (cin, s);
stack <string> st; // 문자열을 저장할 스택 st
for (int j = 0; j < s.length(); j++) {
if (s[j] == ' ') { // 문자사이에 공백이 나오면
st.push(tmp); // 그전까지의 문자 넣어주기
st.push(" "); // 공백도 넣어주기
tmp.clear(); // tmp 변수 초기화
}
else {
tmp += s[j];
}
}
st.push(tmp); // 마지막 단어에는 공백이 안나오므로 따로 추가
while (!st.empty()) {
ans += st.top();
st.pop();
}
cout << "Case #" << i << ": " << ans << "\n";
}
return 0;
}
공부한 내용 정리
1. getline () 함수
문제를 풀면서 getline() 함수의 특징을 제대로 알지 못해서 계속 해서 컴파일 오류가 났었다.
그건 바로 getline() 함수는 마지막 버퍼에 "\n"를 저장한다는 사실이였는데, 이것을 몰라서 반복문 범위 설정이 잘못되었다는 오류가 계속 떴었다.
좀 더 자세히 알아보자면..
cin #
<iostream>에 포함되어 있다.
표준 입력버퍼에서 개행 문자를 제외한 값을 가져온다
공백이나 개행 입력시 공백 이전까지의 값만 결과로 받아들인다.
개행 문자를 입력 버퍼에 남겨둔다.
getline() #
getline() 함수는 두 가지가 존재하는데 각기 다른 라이브러리에 존재한다.
iostream 라이브러리에 속한 cin.getline() 함수와 string 라이브러리에 속하는 getline() 함수가 있다.
1) iostream 라이브러리의 cin.getline()
cin.getline(char* str, streamsize n);
cin.getline(char* str, streamsize n, char dlim);
- 문자 배열이며 마지막 글자가 '\0'(terminator)인 c-string을 입력받는 데 사용한다.
- n-1개의 문자 개수만큼 읽어와 str에 저장 (n번째 문자는 NULL('\0')로 바꾼다.)
- 세 번째 인자인 delim은 별도로 지정해주지 않으면 엔터('\0')로 인식
- delim을 지정해주면 그 제한자 (delim) 문자 직접까지 읽어서 str 저장
cin.getline(변수 주소, 최대 입력 가능 문자 수, 종결 문자);
ex) cin.getline(str, 100);
2) string 라이브러리의 getline()
getline(istream& is, string str);
getline(istream& is, string str, char dlim);
- 최대 문자 수를 입력하지 않아도 됨
- 원하는 구분자(delimiter)를 만날 때까지 모든 문자열을 입력받아 하나의 string 객체에 저장
getline (입력 스트림 오브젝트, 문자열을 저장할 string 객체, 종결 문자);
ex) getline(cin, str);
주의!
getline() 함수를 사용할 때 주의할 점이 있다.
int n;
string str;
cin >> n;
getline(cin, str);
위와 같은 상황을 보자. 위 코드대로 실행을 하면 n을 입력 받은 후 문자열을 입력받지 않고 바로 다음 코드로 넘어가게 된다. 이유는 버퍼에 정수 값을 입력한 뒤 누른 엔터 ('\n')가 그대로 남아있어 getline()에 들어가기 때문이다. 이를 해결하기 위해 cin.ignore() 함수를 사용할 수 있다.
int n;
string str;
cin >> n;
cin.ignore();
getline(cin, str);
위와 같이 변경하면 cin.ignore()가 입력 버퍼의 모든 내용을 제거해 주어 getline()이 정상적으로 동작할 수 있다.
추가적으로 cin.ignore() 함수에 대해 알아보자면
cin.ignore(int n, char dim);
cin.ignore(읽어들일 문자의 개수, 종결 문자);
와 같은 형태로도 사용이 가능하다.
cin.get()
- 표준 입력 버퍼에서 문자를 하나만 가져온다.
- 문자 하나만 입력이 가능하며 공백과 개행도 입력으로 포함한다.
'코테 > 항해99' 카테고리의 다른 글
[99클럽 코테 스터디 15일차 TIL] #스택/ 큐 4 (2) | 2024.11.11 |
---|---|
[99클럽 코테 스터디 14일차 TIL] #스택/ 큐 3 (3) | 2024.11.11 |
[99클럽 코테 스터디 12일차 TIL] #스택/ 큐 1 (0) | 2024.11.09 |
[99클럽 코테 스터디 11일차 TIL] #해시7 (0) | 2024.11.07 |
[99클럽 코테 스터디 10일차 TIL] #해시6 (0) | 2024.11.07 |