안전하지 않음
scanf("%s", buf);
어느정도 대체함 그러나 cin 도 scanf 처럼 메모리 경계를 검사하지 않아서 여전히 위험한 코드이다, 데이터를 주는대로 받고 메모리를 벗어나서 기록한다.
cin >> buf;
char buf[5];
cin >> buf;//"123456789" 입력
cout << buf << endl;//"123456789" 출력, 이미 메모리는 벗어남.
c 에서는 fgets나 sscanf같은 경계 검사 함수를 사용한다
char line[512];
char temp[512];
char firstName[4];
if (fgets(line, 512, stdin) != NULL) {
if(sscanf(line, "%s", temp) == 1 && strlen(temp) < 4) {
strcpy(firstName, temp);
}
}
C++ 은 다음과 같이 해결한다
//이렇게 하면 3글자만 받아오고 끝에 NULL을 채워준다.
char buf[4];
cin >> setw(4) >> buf;//1234567890 입력
cout << buf << endl;//123 출력
//한번만 적용 되기 때문에 주의...
//4567890 출력 하려는데 Exception
cin >> buf;
cout << buf << endl;
//에러를 막기 위해서는 역시 setw로 길이 설정
//cin >> setw(4) >> buf;//456, 에러 발생하지 않음
c 와 c++은 데이터 구분을 공백으로 하여 데이터를 읽어 들인다.
"Hello 123 "
//firstdata -> Hello
//seconddata -> 123
scanf("%s%d", firstdata, &seconddata);
//firstdata -> Hello
//seconddata -> 123
cin >> firstdata >> seconddata >> endl;
//NULL은 직관적이지 않다, 무슨 의미일까?? 다 읽었다는 것일까?? 아니면 실패??
if (fgets(line, 10, stdin) != NULL) {
}
//End Of File(EOF) char를 읽을때 true
//console에서 입력 받을때 백날 엔터 입력해보았자 eof 플래그를 set 못하고
//ctrl + z 같이 eof 문자를 입력 시켜야 함
cin >> line;
if (!cin.eof()) {
}
input stream 상태 확인 api(ios_base)(비트 플래그 / 확인 메서드)
int number = 10;
cin >> number;
스트림을 좋은 상태(good state) 로 바꿈, fail bit 를 정리(fail bit => 0)
cin.clear()
인자로 넘긴 숫자만큼 버리면 멈춤 또는 파일 끝(eof)에 도달하면 멈춤
cin.ignore();// 문자 한개 버림
cin.ignore(10);// 문자 10개 버림
/*
10개 문자를 버리는데 그전에 '\n' 만나면 멈춤,
끝나는 문자가 eof가 아니라 '\n'으로 지정
*/
cin.ignore(10, '\n');
cin.ignore(LLONG_MAX, '\n');// 최대 문자수를 버리는데 그전에 \n을 만나면 멈춤
/*
한 단어씩 읽는 도중 잘못된 단어를 입력받고 걸릴때.
한줄을 다 버리는 일반적인 방법
*/
cin.ignore(LLONG_MAX, ' ');
/*
한 문자를 읽는 것 처럼 보이는데 사실은 한 줄을 읽는 것이다. 한문자를 읽을 수 도 있다
Input 1234567, get(buf, 5)
failbit 설정되지 않음, 다시 get 호출하면 남은 스트림들 다시 읽을 수 있음.
*/
cin.get();
/*
99개의 문자(나머지 하나는 null)를 가져오거나 '\n'을 만나기 전까지 문자를 읽어서 buff에 저장
'\n' 전 까지 모든 문자를 가져오는데 \n은 스트림에 남긴다.
*/
cin.get(buf, 100);
cin.get(buff, 100, '#');// 위와 똑같은데 '\n'대신 #
char buf[5];
while (true) {
cin.get(buf, 5);
cout << buf << endl;
cout << setfill('-') << setw(6) << "" << endl << setfill(' ');
}
char buf[5];
while (true) {
cin.get(buf, 5);
if (cin.fail()) {
cout << "FAIL" << endl;
}
cout << buf << endl;
cout << setfill('-') << setw(6) << "" << endl << setfill(' ');
}
/*
입력 : 1234567890\n
출력 :
1234
------
5678
------
90
------
FAIL
Text를 읽을 동안은 Fail bit 설정 안됨
*/
// failbit 설정됨. 다시 getline 해보았자 스트림에 있는 남은 문자열 못 읽음
// 대신 clear하면 failbit 초기화 되면서 다시 getline 호출하면 읽을 수 있음.
cin.getline(buf, 5);// Input 1234567
char buf[5];
while (true) {
cin.getline(buf, 5);
if (cin.fail()) {
cout << "FAIL" << endl;
}
cout << buf << endl;
cout << setfill('-') << setw(6) << "" << endl << setfill(' ');
//cin.clear();
}
/*
입력 : abc\n
- \n 전인 abc 출력
- 무한루프 돌지 않는다. 스트림에 남은 \n은 버리기에...
입력 : 1234ab\n
- 4개만 읽는다, 1234 출력
- 계속 무한루프 돈다, 이유는 fail비트 설정 되어서 getline이 계속 실패, 스트림에는 ab\n이 남아 있음
- 루프 끝자락에 clear 해주면 남은 스트림 다시 읽을 수 있음.
*/
buffer를 넘어서 입력을 할 때 대처가 다르다.
char buf[5] = "";
cin.get(buf, 5);
if (cin.fail()) {
cout << "Fail" << endl;
}
cout << buf << endl;
/*
출력
-> abcd\0
범위를 넘어서는 입력 받아도 fail 아님,
다시 한번 get 하면 스트림에 남은 데이터를 읽음
*/
char buf[5] = "";
cin.getline(buf, 5);
if (cin.fail()) {
cout << "Fail" << endl;
}
cout << buf << endl;
/*
출력
-> abcd\0
-> Fail
:
범위를 넘어서는 입력 받으면 fail임
*/
char buf[5] = "";
while (true) {
cin.get(buf, 5);
cout << buf << endl;
}
/*
-> abc
-> :
-> :
무한 루프에 빠짐, get이 \n은 스트림에 남기니 get을 호출하면서
계속 읽을것이 없는 상태로 실패함.
*/
char buf[5] = "";
while (true) {
cin.getline(buf, 5);
cout << buf << endl;
}
/*
-> abc
-> 다음 입력 대기
*/
알아서 문자들을 잘 읽는 것 같다.
#include<iomanip>
while (true) {
cin >> setw(5) >> buf;
cout << buf << endl;
}
/*
-> abc
-> 잘 읽고 다음 입력 대기
-> abcdefg
-> abcd
-> efg
-> 잘 읽고 다음 입력 대기
*/
char buf[5];
while (true) {
cin >> buf;
if (cin.fail()) {
cout << "FAIL" << endl;
}
cout << buf << endl;
cout << setfill('-') << setw(6) << "" << endl << setfill(' ');
}
/*
입력 : abc\n
정상 입력
입력 : 1234ab\n
buf끝에 NULL을 안 넣고 오버플로우 되어서 값을 넣는다.
그래서 결과로는 1234ab가 정상적으로 출력 되는것 같지만
메모리 범위 넘어서 1234ab가 적히기 때문에 위험.
그리고 fail bit도 설정이 안된다.
*/