std::getline 함수 사용법
std::getline 함수는 입력 스트림( input stream )으로부터 구분자( delimiter )까지의 문자열을 입력받는 함수입니다.
만약, 구분자를 지정하지 않은 경우, 개행 문자( '\n' )가 기본 구분자가 됩니다.
먼저, 이 함수를 사용하려면 다음의 헤더를 포함해야 합니다.
#include <string>
함수의 정의는 다음과 같습니다.
istream& getline( istream& is, string& str);
istream& getline( istream& is, string& str, char deli );
// C++ 11 이후
istream& getline( istream&& is, string& str);
istream& getline( istream&& is, string& str, char deli );
이 정의에서, 매개 변수 is는 아래 이미지의 C++ 입력스트림 istream을 가리킵니다.

위에서 보면 알 수 있듯이, getline 함수는 이 istream 클래스를 상속받은 사용자 입력( std::cin ), 파일( file ), 그리고 std::string 스트림 객체로부터 데이터를 입력받을 수 있습니다.
그리고, 마지막 매개 변수인 deli는 입력 문자열을 분할하는 구분자입니다.
이 함수는 입력 스트림의 현 위치부터, 이 구분자까지의 문자열을 구하여, str에 그 값을 전달합니다.
● 아래 예문은 getline의 기본적인 사용법입니다.
#include <iostream>
#include <string>
using namespace std;
int main(){
string str1, str2, str3;
getline( cin, str1, ',');
getline( cin, str2, ',');
getline( cin, str3);
cout << str1 << " , " << str2 << " , " << str3;
}
▲입력
apple,banana,strawberry
▼출력
apple , banana , strawberry
위의 마지막 getlne 함수 호출에서는 구분자를 지정하지 않았으므로, 개행 문자 '\n'가 구분자( delimeter )가 됩니다.
따라서, 사용자가 enter를 입력하는 순간, 입력이 끝나고 결과가 출력됩니다.
● 다음 예문은 std::cin 객체의 >> 연산자와 getline 함수를 같이 사용하는 예문입니다.
int main ()
{
string name1, name2, name3;
cout << "Please, enter names: \n";
cin >> name1;
getline (cin, name2); // 개행문자가 구분자
getline (cin, name3);
cout << name1 << "|,|" << name2 << "|,|" << name3;
}
▼출력
Please, enter names:
1
2
output: 1|,||,|2
위에서도 첫 번째 예문처럼, 세 번의 입력을 기대했는데, 1과 2를 입력하자, 바로 결과가 출력되었습니다.
왜 이런 걸까요?
이것은, std::cin 객체의 >> 연산자가 공백, 탭, 개행 문자의 전까지만 입력을 받고 리턴하기 때문입니다.
문자 1 뒤에 개행 문자가 있기 때문에, name1에는 1이 입력되고, 입력 스트림에는 아직 개행 문자가 남아 있습니다.
이 개행 문자는 getline 함수를 통해서 두 번째 입력을 받을 때, 구분자로 역할을 하므로, name2는 아무런 문자도 입력받지 못했습니다.
그리고, 세 번째 입력 시, name3에 2가 입력되어서 위의 결과가 나오게 된 것입니다.
이 결과를 수정하려면, 첫 번째 문자열 1을 입력받은 후, 입력 스트림에 아직 남아있는 개행 문자 '\n'를 제거하면 될 것입니다.
이때 사용하는 함수가 istream::ignore입니다.
istream& ignore( streamsize n = 1, int delim = EOF );
이 함수는 입력 스트림에 남아있는 데이터를 n개만큼 삭제합니다.
만약, delim 구분자를 만나면 함수는 종료합니다.
여기서는, 개행 문자만 제거하면 되므로, 다음 문장으로 문제는 해결됩니다.
cin.ignore();
▼출력
Please, enter names:
1
2
3
output: 1|,|2|,|3
● 참고로, istream 스트림에 남아있는 모든 문자를 무시하려면, 아래와 같이 하면 됩니다.
#include <limits> // for std::numeric_limits
std::cin.ignore( std::numeric_limits<std::streamsize>::max() );
이때, max()의 값을 인자로 ignore 함수에 전달하면, 이 함수는 이것을 매우 큰 숫자를 말하는 것이 아니라, 제한이 없다는 뜻으로 받아들입니다.
그 결과, 아직 입력 스트림에 남아 있는 모든 문자를 무시(제거)하게 됩니다.
● 다음 예문은, 콤마로 구분된 문자열로부터 숫자의 합을 구하는 예문입니다.
#include <iostream>
#include <string>
#include <sstream> // for istringstream
using namespace std;
int main(){
string str = "10, 2, 3, 5, 7, 23";
istringstream input(str); // std::string으로부터 입력 스트림 생성
string val;
int sum = 0;
while( getline( input, val, ',') ){ // ??
sum += stoi(val); // string을 숫자로 변환
}
cout << "sum: " << sum;
}
▼출력
sum: 50
위에서 getline 함수가 반환하는 것은 istream 객체입니다.
그런데, 어떻게 위와 같이 while 구문을 사용할 수 있는 걸까요?
이것은 컴파일러에 의해서 암시적인 타입 변환이 일어나기 때문입니다.
while 구문은 괄호 안 표현식의 bool 값을 평가하는데, 이 값을 얻기 위해서 컴파일러는 istream 객체를 bool 타입의 값으로의 변환을 시도하고, 그 과정에서 bool istream::operator() 연산자를 호출하게 됩니다.
이 연산자는 istream의 내부 상태 플러그에 따라, true와 false를 반환하는데, 스트림이 EOF( end of file )에 도달하거나 스트림의 데이터를 읽으면서 오류가 발생하게 되면, 이 상태 플러그가 오류 상태가 되어 false를 반환하게 됩니다.
그래서, 문자열을 읽는 과정이 입력스트림의 끝에 도달하면, while 루프를 벗어나게 되는 것입니다.
'표준 라이브러리' 카테고리의 다른 글
| [C++] 호출 가능한 객체를 저장하는 std::function (0) | 2025.03.17 |
|---|---|
| [C++] 주어진 원소들에 함수를 적용하는 std::for_each (0) | 2025.03.12 |
| [C++] 입력된 원소들을 차례로 변환하는 std::transform (0) | 2025.03.11 |
| [C++] 배열, 컨테이너, 사용자 정의 데이터를 정렬하기 위한 std::sort (0) | 2025.03.10 |
| [C++] 함수에 std::vector 전달하기 (3) | 2025.01.18 |
