Publish:

태그: , ,

카테고리:


🤯 언리얼을 하기 위해 C++ 기억 되살리기 프로젝트

입력 (Input)

1. 입력 스트림 (Input Stream)

scanf 는 왜 위험한가
char[4] 하고 4글자 넣으면..
문자열 끝에 문자열이 끝났다고 표시하는 null 문자가 들어가는데
4글자 들어가고나서 끝에 null 문자가 못들어가게 됨

일단 먼저 배열 크기가 4로 잡혀 있는데 마지막에 null문자를 넣으려고 하니,
소유하지 않은 공간에 접근하려고 하는 문제가 생김.

그리고 scanf는 char 포인터를 받는데, char array는 char 포인터임.
포인터로 각 array의 인덱스에 접근할 수 있음.
null 문자가 없으니 문자열이 어디서 끝나는지 알 수 없음.

즉 scanf는 경계 검사를 하지 않는다. 익셉션 같은 것을 던지지 않아서 위험하다.

💡 그럼 cin의 경우?
같은 문제가 있지만 c보단 쉽게 고칠 수 있는 방법이 있음. (c의 경우 fgets 함수로 변수와 사이즈를 지정해서 했었음)

1
2
char firstName[4];
cin >> setw(4) >> firstName;

알아서 끝에 null문자 넣어준다.

2. 스트림 상태 (Stream States)

스트림에서 뭔가를 읽어왔는데 읽다가 실패했는지 성공했는지 상태가 자동으로 저장됨.
이것을 이용해 안전하게 짤 수 있음.

먼저 c와 c++ 의 입력 받는 부분 차이

  • c ver.
    1
    2
    3
    4
    
    if (fgets(line, 10, stdin) != NULL)		// NULL 은 직관적이지 않다.
    {
      //...
    }
    
  • c++ ver.
    1
    2
    3
    4
    5
    
    cin >> line;
    if (!cin.eof())		// eof : End of File. 읽을 게 없으면 그만둔다.
    {
      //...
    }
    

istream 상태

  • 네임스페이스 : ios_base
  • 비트 플래그 (goodbit, eofbit)
  • 메소드 버전 (위와 같은데 메소드 버전으로도 호출 가능)

예제

1
2
int number;
cin >> number;
  • input : 456abc // 456까지만 읽고 멈춘다. (int형 이니까;;)
    • eofbit : unset (끝이 아니니까)
    • failbit : unset (숫자 읽긴 읽었으니까)
  • input : abc // 실패
    • eofbit : unset (못읽었기에 포인터는 끝이 아니라 첫번째를 가리키고 있음)
    • failtbit : set (못읽었으니까)
  • input : 456
    • eofbit : (un)set
      • unset : console에서 데이터 입력하고 엔터 치면, 숫자 뒤에 뉴라인 문자가 들어감 (\0) 이건 eof가 아니니까 unset임.
      • set : 텍스트 파일로 저장하고 읽으면 텍스트파일 끝에 알아서 eof가 위치하기 때문에 set 됨.
    • failbit : unset (숫자니까 잘 읽음)
  • input : eof
    • eofbit : set (끝이니까 ;;)
    • failbit : set (숫자 아니니까 못읽음)

3. 입력 버리기 (Discarding Input)

스트림 상태가 안좋아서 읽으려다가 실패하거나…
유효하지 않은 입력을 버리고 다시 제대로 된 입력을 받고 싶다면 입력을 버리고 진행해야 함.

  • clear()
    • cin.clear();
    • 스트림을 좋은 상태(good state)로 돌려 줌. eof가 들어왔다거나 그럴 때 지워주는 역할. 다시 시도해보자~ 할 때 호출.
  • ignore()
    • 위에서 abc 예제일 때… int 형 변수로 문자를 읽으려 할 때, 못 읽었음. 그런데 포인터는 아직 앞에 머물러있음. 이 때 호출.
    • 파일 끝에 도달하거나 지정한 수 만큼 문자를 버리면 멈춤.
    • cin.ignore(); // 문자 1개 버림
    • cin.ingore(10); // 문자 10개 버림
    • cin.ignore(10, ‘\n’); // 문자 10개 버림. 단! 그 전에 뉴라인 문자를 버리면 바로 멈춘다. eof가 아니라, 뉴라인을 만나면. 버리고 바로 멈춤.
    • cin.ignore(LLONG_MAX, ‘\n’); // 최대 문자 수를 버림. 단! 그 전에 뉴라인 문자를 만나면 뉴라인 버리고 바로 멈춘다.
  • get()
    • 뉴라인 문자를 만나기 직전까지 모든 문자를 가져옴.
    • 그리고 뉴라인 문자는 아직 입력 스트림에 남아 있음.
    • get(firstName, 100); // 99개 문자를 가져오거나 뉴라인 문자가 나올 때 까지 모든 문자를 가져오고, 가져온 문자들은 char 배열(firstName)에 배치
    • get(firstName, 100, ‘#’); // 99개 문자를 가져오거나, ‘#’ 문자가 나올 때 까지의 문자를 가져오고, 가져온 문자들은 char 배열 (firstName)에 배치
  • getline()
    • 뉴라인 문자를 만나기 직전까지의 모든 문자를 가져오고,
    • 뉴라인 문자를 입력 스트림에서 버림!!!

    • getline(firstName, 100);
    • getline(firstName, 100, ‘#’);

이슈 및 공부한 것을 기록해두는 개인 블로그 입니다. 댓글, 피드백 환영합니다 🙂

Update:

댓글남기기