c++ 계산기 프로그램인데요 질문좀 드릴게요..

haedal의 이미지

#include
using namespace std;

void main()
{
char str[50],ch,oper;
int i=0,check=0;
double num1=0,num2=0;

cin >> str;

while(ch=*(str+i++)) //*(str+i++) 이 부분과 아래 보시면 !(*(str+i)) 설명좀해주세요..
{
if ('0'<=ch && ch<='9')
{
if (check)
num2=num2*10+ch-'0';
else
num1=num1*10+ch-'0';
}

if (ch=='+' || ch=='-' || ch=='*' || ch=='/' || ch=='=' || !(*(str+i)))
{
switch(oper)
{
case '+':
num1+=num2;
break;
case '-':
num1-=num2;
break;
case '*':
num1*=num2;
break;
case '/':
num1/=num2;
break;
};
oper=ch,check=1,num2=0;
}
}
cout << num1 << endl;
}

*(str+i++) 이 부분과 !(*(str+i)) 설명좀해주세요..

Trace의 이미지

어떤 수준의 설명을 원하시는 것인지 모르겠습니다. 일단 가볍게 말씀드리자면
*( str + i )는 str[i]와 같습니다. 당연히 *( str + i++ )는 str[i++] 와 같은 의미입니다.

이 프로그램은 연산자의 우선순위 같은 것은 전혀 고려하지 않고, '앞에서부터' 계산해 나가는 프로그랩입니다. 예컨대 주어진 식이

10 + 20 * 30 / 40 - 50 * 60

라면, 이를
( ( 10 + 20 ) * 30 / 40 - 50 ) * 60 으로 계산하게 되겠지요.
따라서 이 프로그램에서는 3개의 변수만이 필요합니다. num1, num2, 그리고 oper 입니다.
oper은 앞에서 나왔던 연산자를 저장하고 있습니다.

'앞에서 나왔던 연산자' 따위가 필요한 이유는, 연산자가 나왔을 때 계산해야 할 숫자의 정체가 분명하지 않기
때문입니다. 그래서 다음 연산자가 나왔을 때 비로소 계산을 실행합니다.
앞의 예로 돌아가서,

10 + 20 * 30 / 40 - 50 * 60

이 식을 처리한다고 생각해 보지요. 처음에 '1', '0' 을 읽어들여서 10이라는 숫자를 구성한 후, '+' 연산자를 발견했습니다. 하지만 이 단계에서는 10에 어떤 숫자를 더해야 할지 알 수 없습니다. 그래서 10과 +를 각각 num1과 oper에 보관해 놓고 그대로 진행합니다.
다음으로 '2', '0', 그리고 그 다음에 '*'를 읽어들입니다. 이 때에야 비로소 10에 더해야 할 숫자가 20임을 알게 되어 10 + 20 이라는 연산을 수행하는 것입니다. 즉 연산자를 읽어들였을 때 실행하는 것은 지금 읽어들인 연산자에 대한 계산이 아니라, 앞에서 읽어들였던 연산자에 대한 계산인 것입니다.

그런데 문제는 연산자를 마지막까지 읽어들인 다음입니다. '6', '0' 까지 읽어들인 후 '\0'이 와서 while문 자체가 끝나버립니다. 즉 * 60 의 결과는 계산되지 않는 것입니다. 이를 피하기 위해서, 이 계산기에서는 "다음에 읽어들일 숫자가 string의 끝을 나타내는 '\0'이 아닌가"를 확인해서, 이 경우에도 다음 연산자를 읽어들인 경우와 마찬가지로 '앞에서 읽어들였던 연산자'에 의한 계산을 실행하고 있습니다. 이를 확인하는 코드가 바로 *(str + i++) 부분인 것입니다.

하지만 솔직히 말씀드리자면, 저라면 이런 식으로 코드를 작성하지 않겠습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.