Doby's Lab

[C++] 백준 1152번: 단어의 개수, 문자열 입력(getline(),cin.get(), cin.getline(), cin.ignore()) 본문

C++

[C++] 백준 1152번: 단어의 개수, 문자열 입력(getline(),cin.get(), cin.getline(), cin.ignore())

도비(Doby) 2021. 9. 3. 03:11

평소 문자열 문제(특히 입력)에 취약하던 입장에서 이 문제로 문자열 입력에 대해 정리를 하려 한다.

 

처음에는 string 변수를 선언하여 입력 문자들을 집어넣으려 했다.

>> 공백 전의 한 단어밖에 담지 못 하기 때문에 pass

 


getline()

 

그래서 공백을 포함한 모든 문자열을 담을 수 있는 방법이 필요했다.

>> getline(입력스트림(입력할 방법(?)), 문자를 담을 곳, 이 문자가 나오면 입력을 끝내겠다는 문자)

getline은 <string>에 선언되어있다.

 

ex)

#include <string>

int main(){
	string idx;
	getline(cin, idx, '\n');
}

>> idx라는 string 변수에 cin을 통해 '\n'이 나오기 전까지 입력을 받겠다는 뜻이다.

 

그밖에도 문자열 입력에 관한 함수들을 간단하게 정리한다.

  1. cin.get()
  2. cin.getline()
  3. cin.ignore()

cin.get()

이 함수는 하나의 언어(char형 데이터)를 받아오는 함수이다.

char a;
a = cin.get();
cout << a;

변수에 할당을 해서 사용할 수도 있으며

char a;
cin.get(a);
cout << a;

함수처럼 call 방식으로 사용할 수도 있다.

 

문자 하나, 공백, '\n' 모든 입력을 받아올 수 있다는 걸 유의해야 한다.


cin.getline()

이 함수는 cin 안에 속해 있는 멤버 함수로 char형 배열을 담아낸다.

(char형 배열인 점을 유의해야 한다. string은 받아내지 않는다.)

 

cin.getline(입력받을 배열, 입력받을 사이즈 + 1, '종결 문자')

어떠한 특정 종결 문자가 나오기 전까지 입력을 받을 수 있다.

종결문자가 따로 선언되어있지 않으면 '\n'으로 default 되어 있다.

 

char a[10];
cin.getline(a, 4, 'b');
cout << a;

// ex
// 입력한 문자가 adb일 때
// 출력: ad (종결 문자인 b전까지 받음)

cin.ignore()

이 함수는 cin과 getline을 함께 사용할 때 필요하다.

 

입력 버퍼에 대한 이해가 필요한데

cin을 통해 string 변수에 입력을 할 때

일반적으로 담을 내용이 hello라면 hello를 치고 엔터('\n')를 누른다

이때, 변수에는 hello가 들어가지만 '\n'을 담지는 않는다.

>> 즉, '\n'이 입력 버퍼에 남아있다는 뜻이다.

 

cin과는 반대로 getline을 이용할 때는 '\n'도 변수에 담는다.

>> 즉, '\n'이 입력 버퍼에 남아있지 않다는 뜻이다.

 

string idx1, idx2;
cin >> idx1;
getline(cin, idx2, '\n');

cout << idx1 << '\n' << idx2;

// 실행 결과
// idx1: hello, idx2: (없음)

idx1에 'hello'를 입력하고, idx2에 'world'를 입력을 하고 싶다면 이 코드로는 불가능하다.

 

'hello'를 입력하고, 입력 버퍼에는 '\n'이 남아있기 때문에 바로 다음 getline에서 '\n'을 입력으로 받아버리고 끝나버린다.

>> 즉, idx2는 아무것도 담겨있지 않다.

 

입력 버퍼에 남은 '\n'을 제거하기 위해 cin.ignore()이 필요한 것이다.

string idx1, idx2;
cin >> idx1;

cin.ignore();
getline(cin, idx2, '\n');

cout << idx1 << '\n' << idx2;

// 실행 결과
// idx1: hello, idx2: world

정답(+확실한 기저 사례)

문자열 입력에 관한 포스팅은 여기서 끝내고, 정답과 관련해 여담을 말하자면

이번 문제가 제출이 계속 95% 정도에 오답이 떴었다.

 

논리나 코드의 문제라기보다는 어떤 오류를 잡지 못하고 있다는 느낌이 들었다.

>> 입력받는 문자가 하나인 경우를 기저 사례를 잡지 못했었다.

 

느낀 점: 문제에 대한 전체적인 통찰력(?)은 어떻게 기르나..?

 

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

int main() {
	string idx;
	getline(cin, idx, '\n');
	
	int cnt = 0;

	if (idx.size() == 1) {
		if (idx[0] == ' ') {
			cout << '0';
			return 0;
		}
		else {
			cout << '1';
			return 0;
		}
	}
	for (int i = 0; i < idx.size() - 1; i++) {
		if (i == 0 && idx[i] != ' ') {
			cnt++;
		}
		if (idx[i] == ' ' && idx[i + 1] != ' ') {
			cnt++;
		}
	}

	cout << cnt;
	return 0;
}
728x90