1. std::istream::getline - cin.getline()
인자:
s - C 형식 문자열을 저장할 배열을 가리키는 포인터
n - 저장할 문자의 최대 개수 (끝의 종료 널 문자를 포함한 값). 만약 입력 스트림의 최대 크기에 도달하여 입력이 중단되면 failbit 플래그가 설정된다.
delim - 제한자로 이 문자에 도달시 추출이 중단다. 이 때 이 문자는 s에 기록되지는 않지만 스트림에서 사라지게 된다.
즉 istream을 상속받는 클래스에서 getline()함수를 사용할 수 있다.
콘솔에서 문자열을 입력받으려면 cin.getline()을, 파일으로부터 문자열을 가져오려면 파일입력스트림인 ifstream의 인스턴스에서 getline()을 호출하면 된다.
#include <iostream>
#include <fstream> //파일입출력
using namespace std;
int main()
{
char greeting[100];
cout << "say sth: ";
cin.getline(greeting, 10);
cout << "greeting console: " << greeting<<"\n";
ifstream ifs;
ifs.open("fileinput.txt");
ifs.getline(greeting, 100);
cout << "greeting file: " << greeting;
ifs.close();
return 0;
}
콘솔에는 hello Console!을 입력해주고 파일명은 fileinput.txt로 저장을 한뒤 내용은 이렇게 작성한 결과다
cin.getline(greeting, 10)은 10자를 입력받아 greeting이라는 변수에 넣어라! 라는 뜻이다.
그런데 greeting에 저장되어 있는 것은 10자인 'hello Cons'이 아닌 'hello Con'이다. getline()함수는 c스타일 문자열 형식을 따른다 마지막에 널('\0)을 저장해줘야 하기 때문에 실질적으로 저장되는 자리수는 n-1인 9자리이다. 또 n의 자리수를 크게 하면 파일에 쓰여진 글은 두 줄이지만 한 줄(hello File!)까지만 출력된다.
즉 이 함수는 n-1개의 문자 개수만큼 읽어와서 s에다가 저장시킨다. 3번째 인자인 char delim을 별도로 지정해주지 않으면 엔터('\n')로 인식하기 때문에 n이 클 경우 s에는 한 줄이 저장된다. 3번째 인자를 지정해주면 그 문자를 만나면 읽어오지 않기 때문에 그 제한자(delim) 문자 직전까지 읽어다가 s에 저장해준다. 즉 ifs.getline(greeting, 10, 'i');하면 i직전인 hello F까지 저장된다.
istream& getline(char* s, streamsize n);
2. std::getline (string)
istream& getline (istream& is, string& str);
istream& getline (istream& is, string& str, char delim);
인자:
is - 입력스트림 오브젝트 ex) cin
str - 입력받은 문자열을 저장할 string 객체
delim - 제한자로 이 문자에 도달시 추출이 중단된다. 이 때 이 문자는 s에 기록되지는 않지만 스트림에서 사라지게 된다.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string greeting;
getline(cin, greeting);
cout << "console 입력 값:"<<greeting <<"\n";
ifstream ifs;
ifs.open("fileinput.txt");
getline(ifs, greeting);
cout << "file 입력 값:" << greeting << "\n";
return 0;
}
3. 주의해야 할 점 (getline 함수 둘 다 모두 해당)
#include <iostream>
using namespace std;
int main()
{
char a[100], b[100], c[100];
cin >> a;
cin.getline(b, 100);
cin.getline(c, 100);
cout << "a:" << a << endl;
cout << "b:" << b << endl;
cout << "c:" << c << endl;
return 0;
}
이렇게 코드를 작성한 후 입력을 아래처럼 주었을 경우 결과가 어떻게 될까?
입력: hello 엔터 Ella 엔터 Yang
a에 hello, b에 Ella c에 Yang이 들어갔을까?
이럴 경우, cin 이후에 버퍼를 비워주는 함수(ex cin.ignore())를 실행해서 버퍼를 비워주고 난 뒤 getline으로 입력을 받아야한다. 이런 문제는 cin함수와 getline함수의 차이인데 어떤 원리로 입력을 받아들이는지 하나씩 살펴보자.
-- cin의 경우
#include <iostream>
using namespace std;
int main()
{
char a[100], b[100], c[100];
cin >> a;
cin >> b;
cin >> c;
cout << "a:" << a << endl;
cout << "b:" << b << endl;
cout << "c:" << c << endl;
return 0;
}
입력을 'hello Ella Yang'으로 사이사이에 공백을 충분히 주고 넣어줬다.
이 결과에서 알 수 있는 것은 cin은 공백을 무시한다는거다. cin은 입력값의 기준을 띄어쓰기, 엔터, 탭 등으로 나눈다. 그래서 문자를 읽다가 띄어쓰기를 만나면 그 전까지를 하나의 입력으로 받아들인다. 반면 띄어쓰기, 엔터, 탭 등 이런 문자가 먼저 나오면 그냥 무시한다. 대신에 버퍼에는 그대로 남아있다.
cin이 버퍼에 있는 글자 하나하나를 읽어들인다. hello까지 읽고 공백이 나오니까 공백 전 hello까지를 a에 저장시킨 후 다음 버퍼에 남아있는 문자들은 띄어쓰기다 이때 cin은 멀쩡한 문자가 나올 때까지 공백들을 다 무시한고 Ella가 나오면 읽고 저장한다.
입력함수가 계속 cin이라면 문제되지 않는다. cin은 내부적으로 공백 같은 문자들을 무시해주는 formatting된 함수이기 때문에 버퍼에 공백이 남아도 무시하고 지나가기 때문이다.
-- getline() 의 경우
getline이 하나의 입력으로 받아들이는 기준은 따로 delim을 지정해주지 않는한 엔터('\n')이다.
그런데 getline()함수는 unformatting 함수다.
getline은 엔터('\n')를 무시하지 않고 잡는다. 즉 getline만 사용할 경우에는 문자열을 치고 엔터를 쳤을 때, 엔터 직전까지를 하나의 입력으로 받아들이고 엔터를 버린다.
'프로그래밍 언어 > C++' 카테고리의 다른 글
[C++] 재귀함수 응용 (0) | 2023.10.31 |
---|---|
[C++] tuple (튜플) 사용법 & 예제 (0) | 2023.10.23 |
[C++] 문자열 찾기: string.find() (0) | 2023.10.19 |
[C++] 파스칼의 삼각형 (Pascal's triangle) (0) | 2023.10.15 |
[C/C++] 32bit 자료형 / 64bit 자료형의 크기 정리 (0) | 2023.10.13 |