작성
·
44
·
수정됨
1
while (ch = getchar())를 이용해서 글자수 세는 함수를 만들고있는데,
if (ch == '\n') 는 엔터를 인식하는데
if (ch == "\n") 는 엔터를 인식못합니다. 이유가 뭘까요? 그리고 기억상 해당 질문에 관련 개념이 나오는 강의가 있엇던거 같은데, 해당 내용은 몇 강에서 나올까요?
추가로, if (ch == "\n") 는 인식을 못하는데 printf("\n")는 왜 제대로 작동할까요?
답변 2
1
안녕하세요? 질문&답변 도우미 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
이 출력됩니다. 이는 int
가 float
로 승격(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
함수가 문자열을 인자로 받아 출력하는 함수이기 때문입니다.
인자로 전달한 문자열 중 발견한 이스케이프 시퀀스인 개행문자를 처리했다고 생각하시면 될 것 같습니다.
충분한 설명이 되셨기를 바라며, 혹시 이해가 가지 않거나 더 궁금한 점이 있으시다며 더 질문주셔도 됩니다.
어느정도 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 인턴입니다. luki님!
getchar()
를 사용하는 함수에서 '\n'
는 캐릭터형 문자이고, "\n"
는 문자열로 취급됩니다. C 언어에서 문자 하나는 작은 따옴표 ''
로 묶어야 하며, 문자열은 큰 따옴표 ""
로 묶어야 합니다. 그래서 if (ch == '\n')
조건은 엔터를 인식하지만, if (ch == "\n")
은 두 개의 다른 타입을 비교하려 하기 때문에 제대로 인식하지 못합니다.
기억하신 강의는 아마도 홍정모님의 ‘홍정모의 따라하며 배우는 C언어’ 강의에서 다뤄진 내용일 것입니다. 특히, 8.1 입출력 버퍼 단원에서 getchar()
와 관련된 내용을 찾아보시면 좋을 것 같습니다.
아래는 유사한 주제를 다룬 질문과 답변들이므로 참고해 보시면 도움이 될 것입니다:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
if (ch == "\n")
는 제대로 동작하지 않지만printf("\n")
는 제대로 동작하는 이유는,printf
함수가 문자열을 인자로 받아 출력하는 함수이기 때문입니다.인자로 전달한 문자열 중 발견한 이스케이프 시퀀스인 개행문자를 처리했다고 생각하시면 될 것 같습니다.
즉 printf는 글자 하나하나를 ' ' 로 받아서 처리한다는 뜻인걸까요?