상세 컨텐츠

본문 제목

scanf vs cin and getline()

C++ Basic

by geminanolja 2024. 12. 13. 10:43

본문

C++에서 입력을 처리하기 위한 두 가지 주요 방식

scanf : 매개변수로 받는 형식을 지정해서 입력을 받음

cin: 개행문자(띄어쓰기, 엔터)직전까지 입력을 받음

만약 문장 끝까지 받고 싶다면 getline을 써서 개행문자(\n/0를 줄의 끝으로 인식하고 그 직전까지 입력을 받음


1. 차이점 비교

언어 C 표준 라이브러리 C++ 표준 라이브러리
속도 더 빠름 (I/O 동기화를 하지 않음) 기본적으로 느림 (I/O 동기화됨)
가독성 가독성이 낮음 가독성이 높음
형식 지정 포맷 문자열 필요 (%d, %f 등) 자동으로 데이터 타입을 추론
유연성 정밀한 제어 가능 유연하고 간결한 사용
입력 검증 직접 포맷 제어 가능 기본적으로 예외를 처리하거나 종료
배열/문자열 입력 편리 (%s, gets, fgets 등) 문자열 입력 시 더 안전 (std::string)
동작 방식 버퍼를 직접 처리 스트림 기반 (입출력 객체)
에러 처리 반환값으로 성공 여부 확인 가능 기본적으로 예외 처리 방식 사용

2. 주요 장단점

scanf

  • 장점:
    1. 빠른 속도: C 기반의 함수로, I/O 동기화를 하지 않아 빠르게 동작.
    2. 정확한 제어: 입력 형식을 명시적으로 지정할 수 있어 정밀한 입력 처리가 가능.
    3. 메모리 사용: 상대적으로 메모리를 적게 사용.
  • 단점:
    1. 복잡한 형식 지정: %d, %f와 같은 형식 지정자를 항상 사용해야 함.
    2. 가독성 낮음: 코드가 길고 복잡해질 수 있음.
    3. 안전성 문제: 버퍼 오버플로우와 같은 문제가 발생할 가능성이 있음 (e.g., %s 사용 시)

cin

  • 장점:
    1. 가독성: 형식 지정이 필요 없고, 더 간단하고 직관적인 코드 작성 가능.
    2. 유연성: 다양한 데이터 타입과 사용자 정의 타입 지원.
    3. C++ 스타일: STL과 잘 연동되며, C++의 철학에 적합.
    4. 안전성: 문자열 입력 처리 시 std::string을 지원하여 안전.
  • 단점:
    1. 속도: 기본적으로 I/O 동기화를 하므로 느림.
    2. 제어 어려움: 특정 포맷으로 데이터를 읽을 때 복잡할 수 있음.

3. 사용 예제

scanf 예제

#include <cstdio>

int main() {
    int a;
    float b;
    char name[50];

    // 입력
    printf("Enter an integer, a float, and a string:\n");
    scanf("%d %f %s", &a, &b, name);

    // 출력
    printf("Integer: %d, Float: %.2f, String: %s\n", a, b, name);

    return 0;
}

cin 예제

#include <iostream>
#include <string>

int main() {
    int a;
    float b;
    std::string name;

    // 입력
    std::cout << "Enter an integer, a float, and a string:\n";
    std::cin >> a >> b >> name;

    // 출력
    std::cout << "Integer: " << a << ", Float: " << b << ", String: " << name << std::endl;

    return 0;
}

4. 속도 최적화

  • 기본적으로 cin은 느리지만, 다음 코드를 추가하여 scanf와 유사한 속도로 만들 수 있습니다:
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
  • 적용 예제:
#include <iostream>

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    int n, sum = 0;
    for (int i = 0; i < 5; i++) {
        std::cin >> n;
        sum += n;
    }
    std::cout << "Sum: " << sum << "\n";

    return 0;
}

5. 언제 사용해야 할까?

scanf를 사용해야 할 때

  1. 입출력 속도가 중요한 경우:
    • 대량의 데이터를 처리해야 하는 경우 (예: 코딩 테스트).
  2. C 스타일 프로젝트:
    • C와 C++이 혼용된 프로젝트에서는 scanf가 더 자연스러울 수 있음.

cin을 사용해야 할 때

  1. 가독성과 유지보수성이 중요한 경우:
    • 팀 프로젝트나 장기적으로 유지보수해야 할 코드에서는 cin이 더 직관적.
  2. C++의 STL과 연동:
    • std::vector, std::string 등 C++ STL과 함께 사용할 때 더 적합.
  3. 유연성이 필요한 경우:
    • 복잡한 데이터 타입이나 클래스 입력이 필요한 경우.

6. 결론

  • 속도 중시: scanf (또는 cin + 최적화).
  • 가독성과 안전성 중시: cin (권장).

 


 

getline()

 

1. getline 함수의 역할

  • getline은 입력 스트림에서 한 줄 전체를 읽어오는 함수
  • 공백을 포함한 문자열 입력에 유용
  • 기본적으로 개행 문자(\n)를 기준으로 입력을 종료

기본 사용법

std::getline(istream& is, std::string& str);
  • istream& is: 입력 스트림 객체 (std::cin, std::ifstream 등).
  • std::string& str: 입력받을 문자열 변수.

2. 사용 예제

기본 예제

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

int main() {
    string line;
    cout << "Enter a line of text:\n";
    getline(cin, line); // 한 줄 입력
    cout << "You entered: " << line << endl;
    return 0;
}

다중 줄 입력

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

int main() {
    string line;
    cout << "Enter multiple lines (type 'exit' to quit):\n";
    while (true) {
        getline(cin, line); // 한 줄 입력
        if (line == "exit") break; // 'exit' 입력 시 종료
        cout << "You entered: " << line << endl;
    }
    return 0;
}

구분 문자 변경

  • 기본적으로 getline은 개행 문자(\n)를 기준으로 입력을 종료하지만, 다른 문자도 구분자로 지정 가능
#include <iostream>
#include <string>
using namespace std;

int main() {
    string line;
    cout << "Enter a line (comma will stop the input):\n";
    getline(cin, line, ','); // ','를 기준으로 입력 종료
    cout << "You entered: " << line << endl;
    return 0;
}

4. getline과 cin 혼용 시 주의사항

  • getline은 **개행 문자(\n)**를 처리하기 때문에, cin과 혼용하면 입력 버퍼에 남아 있는 개행 문자로 인해 문제가 발생할 수 있음

문제 예제

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

int main() {
    int age;
    string name;

    cout << "Enter your age: ";
    cin >> age; // 숫자 입력 (개행 문자가 남음)

    cout << "Enter your name: ";
    getline(cin, name); // 개행 문자를 읽어 빈 입력 처리됨

    cout << "Age: " << age << ", Name: " << name << endl;
    return 0;
}

결과값

 

cin으로 입력을 받고 입력이 종료되었을 때 위에 개행문자 (\n)이 남아있게 되어 getline에서 그 개행문자를 포함하여 한줄을 인식하여 빈 줄을 반환하게 됨!!

 

해결 방법

  • cin.ignore()를 사용해 입력 버퍼에 남아 있는 개행 문자를 제거:
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

수정된 예제

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

int main() {
    int age;
    string name;

    cout << "Enter your age: ";
    cin >> age;

    cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 버퍼 정리

    cout << "Enter your name: ";
    getline(cin, name);

    cout << "Age: " << age << ", Name: " << name << endl;
    return 0;
}

'C++ Basic' 카테고리의 다른 글

typedef & using  (0) 2024.12.13

관련글 더보기