인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

luki님의 프로필 이미지

작성한 질문수

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

gerchar관련 질문?

작성

·

44

·

수정됨

1

while (ch = getchar())를 이용해서 글자수 세는 함수를 만들고있는데,

if (ch == '\n') 는 엔터를 인식하는데

 

if (ch == "\n") 는 엔터를 인식못합니다. 이유가 뭘까요? 그리고 기억상 해당 질문에 관련 개념이 나오는 강의가 있엇던거 같은데, 해당 내용은 몇 강에서 나올까요?

 

 

추가로, if (ch == "\n") 는 인식을 못하는데 printf("\n")는 왜 제대로 작동할까요?

답변 2

1

durams님의 프로필 이미지

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

어떤 강의 영상을 보고 질문을 주신건지 명확하지 않아, 어느정도 강의를 들었다고 생각하고 자세하게 말씀드리겠습니다.

  • '\n'은 문자 리터럴이며, 타입은 char입니다.

  • "\n"는 문자열 리터럴이며, 타입은 char[]입니다.

     

말씀하신 내용 중 ch라는 변수가 char 타입이라는 가정 하에 설명을 드리자면, if (ch == "\n")로 작성할 시에는 서로 다른 타입을 비교하게됩니다. 보다 정확하게 말하면, ch에 저장된 정수값"\n"이라는 리터럴 문자열을 가리키는 포인터 주소를 비교합니다.

실제로 문자열 리터럴이 저장되는 주소를 시험삼아 출력해볼수도 있습니다.

printf("%p\n", (void*)"\n");
// 00007FF668A3B288

if (ch == "\n")는 개행문자를 의미하는 정수 10을 위 포인터 주소와 비교하는 것과 같습니다. 거의 대부분의 경우 둘은 같지 않습니다. 이 때문에 ch == "\n"false로 평가되고, 엔터가 인식되지 않는 것처럼 보입니다.


다만 비교 연산 시 타입이 다른 경우 꼭 이러한 상황이 발생하지는 않습니다. 아래 코드를 실행하면 어떨까요?

    int x = 1;
    float y = 1.0f;

    if (x == y) {
        printf("same\n");
    }
    else {
        printf("not same\n");
    }

결과로는 same이 출력됩니다. 이는 intfloat승격(promotion)되어서 적절한 비교가 이뤄질 수 있기 때문입니다.(사실 이 경우에도 엄밀하게 형변환(캐스팅)을 통해 타입을 맞춰주는 것이 좋습니다)

하지만 위에서 알아본 바와 같이, 정수 타입과 포인터 타입을 비교하는 등 타입 간의 호환이 되지 않는다면 작성한 의도와 다른 결과가 나타날 가능성이 큽니다.


정확히 '개행문자 확인 시 if (ch == "\n")가 아닌 if (ch == '\n')로 써야한다.'라는 내용이 나오는 강의를 찾기에는 어렵지만, 연관된 설명이 나오는 강의를 말씀드리자면 아래와 같습니다.

  • 2.6 printf() 함수의 기본적인 사용법 05:30~07:49

    • 이스케이프 시퀀스와 그 중 개행문자에 대한 소개

    • 문자열을 나타낼 때 큰따옴표로 나타내야 한다는 설명

  • 7.2 표준 입출력 함수들 getchar(), putchar() 예제05:05~5:20

    • char 타입 변수가 개행문자인지 비교할 때 '\n'으로 사용해야 하는 이유 설명


if (ch == "\n")는 제대로 동작하지 않지만printf("\n")는 제대로 동작하는 이유는, printf 함수가 문자열을 인자로 받아 출력하는 함수이기 때문입니다.

인자로 전달한 문자열 중 발견한 이스케이프 시퀀스인 개행문자를 처리했다고 생각하시면 될 것 같습니다.


충분한 설명이 되셨기를 바라며, 혹시 이해가 가지 않거나 더 궁금한 점이 있으시다며 더 질문주셔도 됩니다.

luki님의 프로필 이미지
luki
질문자

if (ch == "\n")는 제대로 동작하지 않지만printf("\n")는 제대로 동작하는 이유는, printf 함수가 문자열을 인자로 받아 출력하는 함수이기 때문입니다.

인자로 전달한 문자열 중 발견한 이스케이프 시퀀스인 개행문자를 처리했다고 생각하시면 될 것 같습니다.


즉 printf는 글자 하나하나를 ' ' 로 받아서 처리한다는 뜻인걸까요?

durams님의 프로필 이미지

어느정도 printf가 작동하는 방식에 근접하신 것 같습니다.

printf가 첫 번째 인자로 포맷 문자열을 전달받고, 두 번째부터는 %d, %c와 같은 conversion specifier에 사용할 변수들을 가변 길이로 받는다는 것을 알고계실겁니다. 이렇게 정해져있지 않은 길이로 뒤에 따라붙는 인자들을 가변 인자 리스트라고 합니다.

printf는 포맷 문자열을 맨 앞부터 순차적으로 살펴보며, %로 시작하는 conversion specifier를 발견한 경우 가변 인자 리스트에서 대응되는 인자를 가져와서 형식에 맞게 문자열로 변환하여 출력 버퍼에 추가하는 방식으로 동작합니다.

예를 들어, 아래 코드의 경우

    int x = 1;
    float f = 3.14f;

    printf("%d %f\n", x, f);

"%d %f\n"을 앞에서부터 한 글자씩 읽어 나가다가 %d를 만나면 가변 인자 리스트에서 x를 꺼내와서 문자열 "1"로 변환해서 버퍼에 추가하고, %f를 만나면 역시 가변 인자 리스트에서 f를 꺼내와서 문자열 "3.140000"으로 변환해서 버퍼에 추가할겁니다. (printf의 default 정밀도는 6자리) 그리고 \n을 만났을 때에는 이스케이프 시퀀스의 동작에 해당하는 개행을 수행하구요.

조심스래 보완해드리자면, printf가 글자 하나씩 ' '로 받아서 처리한다기보다는 " "로 받은 후 함수 내부에서 한 글자씩 처리한다고 이해하시면 될 것 같습니다.

0

인프런 AI 인턴님의 프로필 이미지

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

getchar()를 사용하는 함수에서 '\n'는 캐릭터형 문자이고, "\n"는 문자열로 취급됩니다. C 언어에서 문자 하나는 작은 따옴표 ''로 묶어야 하며, 문자열은 큰 따옴표 ""로 묶어야 합니다. 그래서 if (ch == '\n') 조건은 엔터를 인식하지만, if (ch == "\n")은 두 개의 다른 타입을 비교하려 하기 때문에 제대로 인식하지 못합니다.

기억하신 강의는 아마도 홍정모님의 ‘홍정모의 따라하며 배우는 C언어’ 강의에서 다뤄진 내용일 것입니다. 특히, 8.1 입출력 버퍼 단원에서 getchar()와 관련된 내용을 찾아보시면 좋을 것 같습니다.

아래는 유사한 주제를 다룬 질문과 답변들이므로 참고해 보시면 도움이 될 것입니다:

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

luki님의 프로필 이미지

작성한 질문수

질문하기