강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

새싹비빔밥님의 프로필 이미지
새싹비빔밥

작성한 질문수

홍정모의 따라하며 배우는 C언어

14.4 구조체의 배열 연습문제

14.4 연습문제 풀이 중 flag 사용에 대해 질문드립니다.

해결된 질문

작성

·

120

1

안녕하세요. 14.4강 구조체의 배열 연습문제 풀이 중 궁금한 점이 생겨 질문 드립니다.

while(1) 코드 내에서 library[count].price의 값을 받을 때

int flag = scanf("%f",&library[count].price);

로 코드를 작성하셨는데요,
scanf를 통해 library[count].price 에 값이 들어왔는지 확인하기 위한 용도라면 위 코드 아래에
if(flag == NULL)

{

printf("가격이 입력되지 않았습니다.\n");

break;

}
뭐 이런 식으로 flag 값을 활용하는 부분이 있어야 의미가 있을 것 같은데.... 해당 코드에서는 flag로 scanf 값을 받은 의미가 없는 것 같아서요.

 

교수님께서 flag를 사용하신 의도가 뭔지, 제가 제시한 코드 외적으로 flag의 추가적인 용도가 있는건지, 아니면 습관적으로 저렇게 코드를 작성하신 건지 궁금합니다.
감사합니다.

답변 2

1

안녕하세요? 질문&답변 도우미 durams입니다.

말씀하신것처럼 flag 변수를 사용하는 부분은 없습니다. 대신 교수님께서는 scanf의 반환값을 변수에 저장하지 않았을 때 인텔리센스가 발생시키는 경고를 보지 않기 위한 목적으로 이렇게 작성하신 것이 아닐까 싶네요.


그리고 약간 보충해드리자면, 값이 들어왔는지 확인하는 용도로 if (flag == NULL)과 같이 작성하는 것은 적절하지 않을 수 있습니다. 본 예제는 구조체에 대해 학습하는 간단한 형태이기 때문에 예외처리에 대해 말씀드리는 것은 조금 범위를 벗어나는 감이 없지 않아 있습니다만, 몇 가지 주제에 대해서 말씀드릴게요.

NULL의 타입

NULLvoid * 타입으로, 그 값은 0입니다. C에서 정수 값과 포인터 값을 바로 비교하는 것은 적절하지 않습니다. 컴파일러에 따라 동작이 달라질 수 있는 정의되지 않은 동작입니다. C에서는 코드에서 피연산자 간의 자료형을 맞춰주는 것이 무척 중요합니다. 현재 질문자님 컴퓨터에서 문제가 없다고 해도, 여러 machine에서도 동일하게 동작한다는 보장이 없어요.

포인터와 정수간의 안전한 형변환을 지원하는 uintptr_t같은 자료형도 존재하니 흥미가 있으시다면 알아보셔도 좋을 것 같습니다.


scanf의 반환값

NULL을 정수 0, 즉 입력된 것이 없다는 의미로 쓰셨다고 해도 사실 적절치 않습니다. scanf의 반환값을 정확히 말하자면 '포맷과 일치하는 입력을 성공적으로 받은 개수'입니다.

    int x;
    int cnt = scanf("%d", &x);

    printf("%d\n", cnt);

위 코드를 실행해서 입력받을 때 수가 아니라 "abc" 이런 문자열을 입력하면 "%d 포맷과 일치하지 않기 때문에 cnt는 0이 됩니다.
그렇다면 적절하지 않은 입력이 주어진 경우를 0으로 검사해야하나 싶지만, 그것도 아닙니다. scanf는 포맷과 일치하지 않는 입력을 만나면 입력이 버퍼에 남은 채로 동작이 중단되기 때문입니다.

    int x;
    int cnt = scanf("%d %d", &x, &x);

    printf("%d\n", cnt);

위 코드는 두 개의 정수를 입력받습니다. 첫 번째 입력으로 정수를 입력하고, 두 번째 입력으로 "abc"를 입력한다면 첫 번째 입력만 정상적으로 되었기 때문에 cnt1이 됩니다.


입력이 주어지지 않은 경우

scanf의 반환값을 EOF 매크로와 비교하는것이 적절하다고 생각됩니다. scanf는 eof(파일의 끝)에 도달하게 되면 -1을 반환합니다. EOF 매크로는 여러 표준 입출력 함수에서 편리하게 사용할 수 있도록 -1 값으로 정의되어 있습니다.


위 내용들을 종합해서 강의 예제를 조금 더 보완해보시는 것도 좋은 공부가 되실 것 같습니다. 적절한 입력이 주어지지 않은 경우 제대로 입력하도록 다시 사용자에게 요구하는 방식으로 작성할 수도 있겠죠. (입력이 아예 주어지지 않은 경우와 적절한 입력이 주어지지 않은 경우를 구분하셔야 합니다)

더 궁금한 점이 있으시다면 질문주세요.

세세한 답변 감사합니다! 값이 입력되지 않은 경우(혹은 올바른 값이 입력되지 않은 경우) NULL과 비교하는 것은 부적절하다는 점 확실히 알게 되었습니다.

다만 위에서 설명해주신 부분 중 교수님이 flag를 활용하신 이유를 "scanf의 반환값을 변수에 저장하지 않았을 때 인텔리센스가 발생시키는 경고를 보지 않기 위한 목적"이라고 예상하셨는데, 이에 대해서도 조금 더 설명해주실 수 있나요? 비주얼스튜디오 내에 내장된 프로그램인가요?

네, 인텔리센스(IntelliSense)는 비주얼 스튜디오에 내장된 기능 중 하나입니다. 코드 자동 완성, 정적 코드 분석 등의 기능을 제공합니다. 비주얼 스튜디오에서 코드를 작성을 하다가 초록색 밑줄(경고)나 빨간색 밑줄(에러)가 그이는 것을 가끔 보셨을 텐데, 이것이 인텔리센스에서 제공하는 오류 감지 덕분입니다. 이는 빌드 시 컴파일러가 발생시키는 에러 또는 경고와는 구분됩니다.

C 라이브러리의 많은 함수들, 특히 시스템 콜을 동반하는 함수들은 실패 시 예외 처리를 위해 특정한 값을 반환하는 경우가 많습니다. 예를 들어 scanf의 경우는 eof 시 -1을 반환하죠. 그리고 C 언어는 그 반환값을 어딘가 변수에 저장하여 확인하거나, 즉시 조건문을 통해 값을 확인하도록 사용자에게 권장하는 경향이 있습니다. 방어적인 프로그래밍의 일환이죠.

gcc 컴파일러에서도 컴파일 옵션 중 이러한 경우를 모두 감지하여 warning을 띄운다거나, 모든 warning(경고)를 에러로 간주하는 옵션이 있는 등, C언어는 low level(특히 포인터&메모리 등)을 다루는 언어이니만큼 이러한 코드 작성 방식에 있어서도 방어적인 방식이 강조됩니다.

이런 종류의 '경고'는 컴파일러에서 빌드 시 띄워줄 수도 있지만, 그런 기능이 인텔리센스에 탑재되어있다고 생각하시면 될 것 같습니다. 빌드하기도 전에 사용자에게 알려주는, 무척 친절한 기능이라고 볼 수 있습니다.

여담으로, 에러 또는 경고 발생 시 아래와 같이 드롭다운 메뉴를 열어 빌드 시에 발생한 것인지 또는 인텔리센스가 발생시킨 것인지 그 출처를 구분하여 조회할 수 있으니, 둘이 동시에 떠 있더라도 구분은 어렵지 않습니다.

image.png

 

키야아 감사합니다!

1

안녕하세요, 인프런 AI 인턴입니다.

새싹비빔밥님께서 질문하신 사항에 대해 설명드리겠습니다. C 언어에서 scanf 함수는 입력된 데이터의 성공적인 변환과 할당을 체크하기 위해 반환값을 사용합니다. scanf 함수는 성공적으로 읽어 들인 데이터의 수를 반환합니다. 그렇게 때문에, scanf가 성공적으로 데이터를 읽어 들였는지를 확인하려면 반환값을 체크해야 합니다.

예를 들어, scanf("%f", &library[count].price) 가 실행될 때, 반환값은 읽어 들인 데이터의 개수입니다. 만약 입력이 실패하게 되면, scanf는 0을 반환하게 됩니다. 이 반환값을 flag 변수에 저장함으로써 입력이 성공했는지 실패했는지를 체크할 수 있습니다.

만약 flag를 통해 입력이 정상적으로 이루어졌는지를 확인하고자 한다면 다음과 같이 활용할 수 있습니다:

int flag = scanf("%f",&library[count].price);
if(flag != 1) {
    printf("가격이 입력되지 않았습니다.\n");
    break;
}

위 코드에서 flag != 1scanf가 데이터를 정상적으로 입력받지 못했을 때 발생하는 상황을 체크합니다. 이와 같이 반환값을 활용하면 입력 검증이나 반복문 제어에 도움이 될 수 있습니다.

관련된 과거 질문으로 다음의 링크들을 참고하실 수 있습니다:
- “7.11 최대,최소,평균 구하기 예제”: scanf 함수의 반환 값에 대해 설명한 예시입니다.
- “scanf질문이요”: scanf의 결과값 체크에 대한 다른 예시입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

새싹비빔밥님의 프로필 이미지
새싹비빔밥

작성한 질문수

질문하기