[알고리즘/백준] 10951번 :: A+B -4 (C++)

mingguriguri·2022년 3월 23일
0

[백준] - 3. 반복문

목록 보기
13/14
post-thumbnail

문제 ✍🏻 :: [10951번] A+B -4

(초록색 글자 클릭 시 문제로 이동)

두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오. (테스트케이스 X)


알고리즘 (접근방법) 💻

10952번 A+B-5번과 마찬가지로 테스트케이스가 없다. 즉, 반복하는 횟수를 모르기 때문에 for문이 아니라 while문을 사용해야 한다.

for문 : 반복 횟수를 정확히 알 때
while문 : 반복 조건을 설정할 때

그러나 10952번과 다른 점은, A와 B가 0일 때 종료되는 것이 아니라 입력되는대로 계속 반복된다는 것이다.

조건을 어떻게 설정해야 할 것인가에 대해서 방향성을 잃었다.

1번째 시도 : 문제에 나와있는 0 < A, B < 10을 조건으로 사용했다.
➡ 결과 : 🚨"출력초과"🚨

2번째 시도 : 조건을 '입력'받는 것으로 변경 (다른 블로그의 답안을 참고)
➡ 결과 : ✨정상 작동!
EOF에 대한 개념 보충 필요

3번째 시도 : 2번째 시도에서 향상된 입출력 추가
최종 답안 제출

자세한 코드는 아래에서 설명하겠다!


💡1번째 시도💡

위에서 설명한 것처럼 while문의 조건을 어떻게 설정해야 할 지 헷갈렸다. EOF(End Of File)의 개념이 없으니 그럴 수 밖에..
그래서 0 < A, B < 10을 조건으로 봤다. while문 조건에 긴 식을 입력하면 오류가 낫기에, while(true)로 무한루프를 돌게 만들었고, 그 안에 if문을 이용하여 조건을 걸어 빠져나오게 했다.

결론적으로 오답이었지만 코드는 다음과 같다.

#include <iostream>

using namespace std;

int main()
{

    int a, b;


    while (true) {
        cin >> a >> b;

        if (a >= 10 || b >= 10) {
            break;
        }
        else if (a < 0 || b < 0) {
            break;
        }
        else {
            cout << a + b << "\n";
        }        
    }

    return 0;
}

🚨문제 발생! "출력초과"가 뭐야?🚨

출력초과 : 하나만 출력하면 되는 문제에서 출력 후 종료하지 않았을 경우.

'틀렸습니다'와 같은 의미. 너무 많은 출력을 하는 경우에 발생한다. 무한 루프에 빠진 경우, 무한 루프에서 출력을 한다면 출력초과를 받을 수 있다고 한다.

(자세한 설명은 링크 참조 : 자주 틀리는 이유 stackdotnews)

이건 내가 프로그램으로 따로 돌렸을 때도, 무한루프에 빠졌다. 즉 오답이라는 소리다. 무한루프에 빠지지 않게 하려면 어떻게 답을 수정해야 하는 걸까?

💡2번 방법 : 문제 수정💡

언제까지 입력되는지 모른다. 간단하게 생각하면 입력이 되면, 더하는 것이다. 입력 되지 않으면 반복될 필요도 없다. 따라서 while문의 () 안에는 입력문이 들어가면 된다.

while (cin >> a >> b) {
	...
}

이렇게 말이다. 입력이 있을 경우는 true, 없을 경우는 false를 리턴하게 되어 테스트 케이스가 없어도 문제를 해결할 수 있다.

코드는 다음과 같다. 이 문제에서는 EOF(End Of File)의 개념이 사용되었다고 한다. 이에 대한 자세한 설명은 다른 블로그의 글을 통해 요약하여 코드 아래에 보충하였다.

#include <iostream>

using namespace std;

int main()
{
    int a, b;

    while (cin >> a >> b) {
        cout << a + b << "\n";        
    }

    return 0;
}

🧐EOF란? (출처 : Stranger's LAB)

EOF(End Of File)
주어진 입력 파일만 갖고 입력을 받을 때 더이상 읽을 수 있는 데이터가 없는 경우. 파일의 끝

위 문제는 입력에서 더이상 읽을 수 있는 데이터가 존재하지 않을 때 반복문을 종료한다. 즉, EOF 개념이라는 것.

이때 파일의 끝까지 읽었다고 EOF가 되는 것은 아님. 끝까지 읽고 난 뒤 그 다음 파일을 읽으려 할 때, 읽을 데이터가 없을 때 EOF가 되는 것이다.

예를 들어 1 2 3 4 <EOF> 가 있을 때,

ReadStatus
1True
2True
3True
4True
<EOF>False

단순히 4까지 읽었다고 EOF가 아니라 끝에 도달해서 하나 더 읽으려고 할 때 EOF가 된다.

방법1) scanf

stdio.h의 scanf는 int반환값이 있다.
만약 데이터를 읽는 동안 파일의 끝(EOF)에 도달한 뒤 읽고자 하면 -1을 반환한다.
다음과 같이 작성할 수 있다.

while (scanf("%d %d", &a, &b) != -1) {
	...
}

방법2-1 ) cin

가장 많이 틀리는 부분이라고 한다. cin 도 마찬가지로 EOF를 발생시킨다.
1번째 방식eof() 함수를 쓰는 경우이고,
2번째 방식간단히 출력하는 경우이다.

1번째 방식은 scanf와 마찬가지로 eof()함수도 파일의 끝에 도달한 뒤 읽고자 할 경우 true를 반환한다. 이때 eof()가 올바른 시점에 true가 되려면 "읽기 시도를 한 후"에 eof검사를 해야 한다.

//cin >> a >> b로 읽기 시도를 한 후
// .eof()로 eof검사
while(!(cin >> a >> b).eof()) {
	...
}

방법 2-2 ) cin 간단 출력

while( cin >> a >> b) {
	...
}

보통은 cin >> a >> b를 읽은 후 스트림 객체가 반환된다. 그러나 위처럼 조건문 안에 있는 경우엔 연산자 오버로딩으로 true 혹은 false 값을 반환한다.
따라서 cin >> a >> b 과정에서 읽기를 실패했을 경우, 스트림 상태를 변경하고, 위 연산자 오버로딩에 의해 반환된 값이 true에서 false로 바뀌면서 while문을 종료하게 된다.

🌟포인트🌟 : cin, scanf 방식 모두 "읽은 뒤 EOF 체크!"를 해야 한다.


💡3번 방법 : 문제 수정 + 향상된 입출력💡

2-2번에서 입출력 동기화를 끊어주는 방법을 합쳐서 작성하였다.

🚨 참고 🚨
그냥 풀이 할 수 있지만,C와 C++의 표준 입출력 동기화를 끊어주는 방법으로 진행하였다. 이번 문제에서는 입력과 출력이 번갈아 반복되므로 cin.tie(NULL)도 함께 써준다.

자세한 설명은 15552번 풀이에 나와있다. (15552에 대한 설명 바로가기)

#include <iostream>

using namespace std;

int main()
{
 
    cin.tie(NULL);					//입출력 끊기
    ios_base::sync_with_stdio(false);	//동기화 해제
    
    int a, b;

// cin >> a >> b 로 읽기 시도
// true일 때 while문 반복. false일 때 while문 종료
//즉, 입력이 있을 시엔 while문을 계속 반복하게 될 것이고, 입력이 없을 시 반복 종료.
	
    while (cin >> a >> b) {
        cout << a + b << "\n";        
    }
    return 0;
}

💡성능비교💡

순서대로
제출번호 40872592 : 3번째 시도(향상된 입출력 추가) ➡ 0ms
제출번호 40872461 : 2번째 시도(EOF사용) ➡ 4ms
제출번호 40871940 : 1번째 시도(while(true)사용) ➡ 출력초과


회고 🤔

  • EOF 개념을 보고 나니까 내가 아직 모르는게 너무 많은 것 같다. 더더 겸손해져야 할 것 같다.

  • 이해하고 내 걸로 다듬는데에 시간이 좀 걸렸다. 내 벨로그에 있는 다수의 글에는 Stranger's LAB님의 티스토리에서 참고한 게 많다. 이 분 덕분에 혼자 공부해도 나아가는 것 같다..!!

  • 임시저장 해놨던 거 다 날라갔다... 시간이 한참 지난 지금 기억이 가물가물하지만 다시 적는다.
    임시저장 해놨던 것도, 시간이 한참 지나 적은 거였다. 그래서인지 그때 내가 뭘 느꼈는지, 어떻게 크게 다가왔는지 가물하다. 최대한 많은 문제를 풀려고 하는 것도 좋지만 '질' 에 더 신경 써야 겠다고 생각이 들었다. 문제를 풀고 휙 넘어갈 게 아니라 벨로그 글까지 다 쓰고 나서 넘어가야겠다고 반성했다.


Reference

profile
To be "irreplaceable"

0개의 댓글