본문으로 바로가기

연산식의 해석

category 카테고리 없음 2025. 8. 5. 23:56

C언어 내에서 Tcl의 연산식을 해석하려면 당연히

sprintf(command, "expr %g+%g", a, b);
r = Tcl_Eval(interp, command);

위와 같이 이미 익숙한 API Tcl_Eval을 사용하면 되지만, 전용 API도 준비되어 있기에 수식 계산(expr 명령어 사용) 임을 명확히 알고 있다면 이 API를 사용하는 것이 더 빠릅니다.

sprintf(command, "%g+%g", a, b);
r = Tcl_ExprString(interp, command);
if(r == TCL_OK)
  fprintf(stdout, "result=%g\n", strtod(Tcl_GetStringResult(interp), NULL));

Tcl_ExprString이 가장 고급(즉, 비효율적인) API이며, 그 사용법은 거의 Tcl_Eval과 같은 느낌입니다. 결과 값은 정수의 경우 printf의 "%d" 타입으로, 부동소수점 숫자라면 같은 Tcl API의 유틸리티 함수 Tcl_PrintDouble을 호출하여 변환한 문자열이 interp->result에 들어 있으므로 Tcl_GetStringResult 등으로 가져와서 strtol이나 sscanf로 다시 변환하여 C 언어에서 숫자로 사용합니다. 이렇게 되면 상당히 우회적인지라 수식을 해석한 값을 직접 BOOLEAN, long, double로 C 언어로 변환하는 API도 있는데, 당연히 이쪽이 더 빠릅니다.

double result;
sprintf(command, "%g+%g", a, b);
r = Tcl_ExprDouble(interp, command, &result);

위와 같이 Tcl_ExprDouble 등을 사용 시 문법이 맞으면 그 값이 세 번째 인자에 저장이 됩니다. Tcl_Expr로 시작하는 API는 모두 연산식의 해석이 정상이면 TCL_OK를, 문법 오류이면 TCL_ERROR를 반환하며, TCL_ERROR의 경우 에러 메시지가 interp->result로 설정되어 있으므로 Tcl_Error의 경우 Tcl_GetStringResult 등을 사용하여 GetStringResult 등으로 가져올 수 있습니다.  

연산식의 값 처리는, Tcl_ExprBoolean을 사용하면 식의 값이 0이면 반환값도 0이고, 그렇지 않으면 1을 반환합니다. Tcl_ExprLong의 경우 연산식 값의 소수점 이하 자릿수가 모두 잘립니다.

그런데 연산식 안에는 [...]로 둘러싸인 표현도 사용할 수 있습니다. 예를 들어,

long result;
sprintf(command, "%ld+%ld+[clock seconds]", a, b);
r = Tcl_ExprLong(interp, command, &result);

위와 같은 코드라면, 먼저 [clock seconds]가 Tcl_Eval을 사용하여 해석되고, 그 결과가 숫자이기 때문에 [clock seconds]로 대체되어 해석이 됩니다.

 

지금까지의 예제는 해석하고자 하는 명령을 문자열로 지정했지만, Tcl 오브젝트로 전달하는 Tcl_ExprObj 등의 API도 별도로 준비되어 있습니다. 수치 데이터도 문자열 기반보다 오브젝트 기반으로 처리하는 것이 직접 strtol이나 sscanf로 일일이 변환하는 번거로움이 없어 편리한 경우가 많기 때문에 이러한 API가 사용할 기회를 가져보면 많은 도움이 될 겁니다.