c++ 계산기 프로그램인데요 질문좀 드릴게요..
#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)) 설명좀해주세요..
그냥 설명해 달라고만 하시면 난감하지요...
어떤 수준의 설명을 원하시는 것인지 모르겠습니다. 일단 가볍게 말씀드리자면
*( 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++) 부분인 것입니다.
하지만 솔직히 말씀드리자면, 저라면 이런 식으로 코드를 작성하지 않겠습니다.
댓글 달기