⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 calc.c

📁 CD_《Palm OS编程实践》
💻 C
字号:
//////////////////////////////////////////////////////////////////////////////
// calc.c
// Implements a generic calculator.
// Copyright (c) 1999, Robert Mykland.  All rights reserved.
//////////////////////////////////////////////////////////////////////////////

//////////////
// Includes //
//////////////

#include "app.h"	// The definitions for this application
#include "calc.h"	// The definitions for this module

///////////////////////
// Global Prototypes //
///////////////////////

void calcAdd( void );			// Queue an add operation
void calcAppend( int );			// Append a digit
void calcChangeSign( void );	// Change the sign of the entry
void calcClear( void );			// Clear/reset the calculator
void calcDivide( void );		// Queue a divide operation
void calcEquals( void );		// Finish the current operation
void calcExponent( void );		// Start gathering the exponent
void calcMultiply( void );		// Queue a multiply operation
void calcPoint( void );			// Start gathering the fraction
void calcSubtract( void );		// Queue a subtraction operation

//////////////////////
// Local Prototypes //
//////////////////////

static double ca2n( char* );		// Converts an ascii string to a double
static void n2ca( double, char* );	// Changes a double to a string

/////////////////////
// Local Constants //
/////////////////////

#define MAX_DIGITS			8
#define MAX_EXP_DIGITS		2

enum {
	OPERATION_NONE = 0,
	OPERATION_ADD,
	OPERATION_DIVIDE,
	OPERATION_MULTIPLY,
	OPERATION_SUBTRACT
};

/////////////////////
// Local Variables //
/////////////////////

static char caNumber[MAX_NUMBER_SIZE] = "+0";
static int iDigitCount;
static int iOperator;
static double nOperand;
static int oExponent;
static int oFraction;

//////////////////////
// Global Functions //
//////////////////////

//----------------------------------------------------------------------------
void calcAdd(
//----------------------------------------------------------------------------
// Queues an add operation.
//----------------------------------------------------------------------------
void )
//----------------------------------------------------------------------------
{
	// Resolve any pending operations
	calcEquals();
	
	// Queue the operation
	iOperator = OPERATION_ADD;
	
	// We're done
	return;
}

//----------------------------------------------------------------------------
void calcAppend(
//----------------------------------------------------------------------------
// Appends a digit to the entry.
//----------------------------------------------------------------------------
int iDigit )	// The digit to append
//----------------------------------------------------------------------------
{
	char caDigit[2];
	
	// If we are entering the exponent part
	if( oExponent )
	{
		// If the exponent digit count is at maximum, then signal an error
		if( iDigitCount >= MAX_EXP_DIGITS )
		{
			calcSignalError();
			return;
		}
	}
	
	else
	// If we are entering the number part
	{
		// If the digit count is at maximum, then signal an error
		if( iDigitCount >= MAX_DIGITS )
		{
			calcSignalError();
			return;
		}
	}

	// Destroy leading zeroes
	if( (oFraction == false) && (iDigitCount < 2) && (caNumber[1] == '0') )
		caNumber[1] = '\0';

	// Append the digit	
	caDigit[0] = iDigit + 0x30;
	caDigit[1] = '\0';
	strcat( caNumber, caDigit );

	// Increase the digit count if it wasn't a leading zero
	if( (oFraction == true) || (iDigitCount == 0) || (caNumber[1] != '0') )
		iDigitCount++;
	
	// Display the new number
	calcDisplay( caNumber );
	return;
}

//----------------------------------------------------------------------------
void calcChangeSign(
//----------------------------------------------------------------------------
// Changes the sign of the number or exponent.
//----------------------------------------------------------------------------
void )
//----------------------------------------------------------------------------
{
	int iPlace;
	
	// Find the last sign in the number
	for( iPlace = strlen( caNumber ) - 1; iPlace >= 0; iPlace-- )
	{
		// If it's a plus, change to minus
		if( caNumber[iPlace] == '+' )
		{
			caNumber[iPlace] = '-';
			break;
		}
			
		// If it's a minus, change to plus
		if( caNumber[iPlace] == '-' )
		{
			caNumber[iPlace] = '+';
			break;
		}
	}
	
	// Display the new number
	calcDisplay( caNumber );
	return;
}

//----------------------------------------------------------------------------
void calcClear(
//----------------------------------------------------------------------------
// Clears/resets the calculator.
//----------------------------------------------------------------------------
void )
//----------------------------------------------------------------------------
{
	// Set our local variables in a default state
	strcpy( caNumber, "+0" );
	iDigitCount = 0;
	iOperator = OPERATION_NONE;
	nOperand = 0.0;
	oExponent = false;
	oFraction = false;
	
	// Display the new number
	calcDisplay( caNumber );	
	return;
}

//----------------------------------------------------------------------------
void calcDivide(
//----------------------------------------------------------------------------
// Queues a divide operation.
//----------------------------------------------------------------------------
void )
//----------------------------------------------------------------------------
{
	// Resolve any pending operations
	calcEquals();
	
	// Queue the operation
	iOperator = OPERATION_DIVIDE;
	
	// We're done
	return;
}

//----------------------------------------------------------------------------
void calcEquals(
//----------------------------------------------------------------------------
// Resolves a math operation.
//----------------------------------------------------------------------------
void )
//----------------------------------------------------------------------------
{
	double nOperand2;
	
	// If there is an entry
	if( iDigitCount > 0 )
		// Convert the entry to floating point
		nOperand2 = ca2n( caNumber );
	
	else
	// If there is no entry
		// The entry is the last operand
		nOperand2 = nOperand;
		
	// Perform the operation
	switch( iOperator )
	{
		case OPERATION_ADD:
			nOperand = nOperand + nOperand2;
		break;
		
		case OPERATION_DIVIDE:
			nOperand = nOperand / nOperand2;
		break;
		
		case OPERATION_MULTIPLY:
			nOperand = nOperand * nOperand2;
		break;
		
		case OPERATION_SUBTRACT:
			nOperand = nOperand - nOperand2;
		break;
		
		default:
			nOperand = nOperand2;
		break;
	}

	// Clear the operator
	iOperator = OPERATION_NONE;
		
	// Convert the result from floating point for display
	n2ca( nOperand, caNumber );

	// Display the new number
	calcDisplay( caNumber );
	
	// Reset the entry
	iDigitCount = 0;
	strcpy( caNumber, "+0" );
	oExponent = false;
	oFraction = false;
	
	// We're done
	return;
}

//----------------------------------------------------------------------------
void calcExponent(
//----------------------------------------------------------------------------
// Starts gathering the exponent.
//----------------------------------------------------------------------------
void )
//----------------------------------------------------------------------------
{
	// If we're not already doing the exponent
	if( (oExponent == false) &&
			// and if the number is nonzero
			(ca2n( caNumber ) != 0.0) )
	{
		// Set up the exponent part
		oExponent = true;
		iDigitCount = 0;
		strcat( caNumber, "e+0" );
	
		// Display the new number
		calcDisplay( caNumber );
	}
	
	else
		// This was done in error
		calcSignalError();
	
	// We're done
	return;
}

//----------------------------------------------------------------------------
void calcMultiply(
//----------------------------------------------------------------------------
// Queues a multiply operation.
//----------------------------------------------------------------------------
void )
//----------------------------------------------------------------------------
{
	// Resolve any pending operations
	calcEquals();
	
	// Queue the operation
	iOperator = OPERATION_MULTIPLY;
	
	// We're done
	return;
}

//----------------------------------------------------------------------------
void calcPoint(
//----------------------------------------------------------------------------
// Appends a decimal point to the entry.
//----------------------------------------------------------------------------
void )
//----------------------------------------------------------------------------
{
	// If we are not collecting the fractional part already
	if( (oFraction == false) &&
			// If we are not doing the exponent
			(oExponent == false) &&
			// If we are not maxed out on digits
			(iDigitCount != MAX_DIGITS) )
	{
		// If no digit has been entered, enter a zero
		if( iDigitCount == 0 )
			calcAppend( 0 );
		
		// Now we will have a fractional part
		oFraction = true;
		
		// Append the decimal point
		strcat( caNumber, "." );
	}

	else
		// This was done in error
		calcSignalError();
	
	// Display the new number
	calcDisplay( caNumber );	
	return;
}

//----------------------------------------------------------------------------
void calcSubtract(
//----------------------------------------------------------------------------
// Queues a subtract operation.
//----------------------------------------------------------------------------
void )
//----------------------------------------------------------------------------
{
	// Resolve any pending operations
	calcEquals();
	
	// Queue the operation
	iOperator = OPERATION_SUBTRACT;
	
	// We're done
	return;
}

/////////////////////
// Local Functions //
/////////////////////

//----------------------------------------------------------------------------
static double ca2n(
//----------------------------------------------------------------------------
// Converts a decimal ascii string to a double.
//----------------------------------------------------------------------------
char*	cpNumber )	// The string to convert
//----------------------------------------------------------------------------
{
	double	nSign;
	int		oDecimal;
	int		iDivisor;
	int		iCount;
	char	caInt[MAX_DIGITS + 1];
	int		iNumber;
	double	nNumber;
	
	// Get any leading sign
	nSign = 1.0;
	if( *cpNumber == '+' )
		cpNumber++;
	if( *cpNumber == '-' )
	{
		nSign = -1.0;
		cpNumber++;
	}
	
	// Convert to an integer string
	oDecimal = false;
	iDivisor = 0;
	for( iCount = 0; (iCount <= MAX_DIGITS) && *cpNumber &&
			(*cpNumber != 'e'); iCount++ )
	{
		// Do the decimal point thing
		if( *cpNumber == '.' )
		{
			oDecimal = true;
			iCount--;
			cpNumber++;
			continue;
		}
		
		// If we are gathering the fraction
		if( oDecimal )
			iDivisor++;
		
		// Otherwise, copy the digit
		caInt[iCount] = *cpNumber++;
	}
	
	// Zero delimit the string
	caInt[iCount] = '\0';
		
	// Use atoi
	iNumber = atoi( caInt );
	
	// Convert to a double
	nNumber = nSign * (double)iNumber * pow( 10.0, -(double)iDivisor );
	
	// If there is an exponent
	if( *cpNumber == 'e' )
	{
		cpNumber++;
		
		// Get any leading sign
		nSign = 1.0;
		if( *cpNumber == '+' )
			cpNumber++;
		if( *cpNumber == '-' )
		{
			nSign = -1.0;
			cpNumber++;
		}
		
		// Convert to an integer string
		for( iCount = 0; (iCount <= MAX_EXP_DIGITS) && *cpNumber; iCount++ )
			caInt[iCount] = *cpNumber++;
			
		// Zero delimit the string
		caInt[iCount] = '\0';
		
		// Use atoi
		iNumber = atoi( caInt );	
		
		// Multiply the number
		nNumber *= pow( 10.0, (double)iNumber );
	}
		
	// Return the number
	return( nNumber );	
}

//----------------------------------------------------------------------------
static void n2ca(
//----------------------------------------------------------------------------
// Converts a double to an ascii string.
//----------------------------------------------------------------------------
double	nNumber,	// The number to convert
char*	cpNumber )	// Storage for the converted number
//----------------------------------------------------------------------------
{
	double	nExp;
	int		iExp;
	int		iNumber;
	char	caInt[9];
	int		iZeroes;
	
	// Handle zero
	if( nNumber == 0.0 )
	{
		strcpy( cpNumber, "+0" );
		return;
	}
	
	// Grab the sign
	*cpNumber = '+';
	if( nNumber < 0.0 )
	{
		nNumber = -nNumber;
		*cpNumber = '-';
	}
	cpNumber++;
	
	// Normalize
	nExp = log10( nNumber );
	iExp = (int)nExp;
	if( nExp < 0 )
		iExp--;
	iExp -= MAX_DIGITS - 1;
	nNumber /= pow( 10.0, (double)iExp );

	// Convert to an integer
	iNumber = (int)(nNumber + 0.5);
	
	// Convert to an integer string
	itoa( caInt, iNumber );

	// Count trailing zeroes
	for( iZeroes = 0; caInt[strlen( caInt ) - 1 - iZeroes] == '0'; iZeroes++ )
		;

	// Handle decimal notation
	if( (iExp <= 0) && (iExp > -MAX_DIGITS) )
	{
		// Integer part
		strncpy( cpNumber, caInt, MAX_DIGITS + iExp );
		cpNumber[MAX_DIGITS + iExp] = '\0';
		
		// Decimal point
		strcat( cpNumber, "." );
		
		// Mantissa part
		strcat( cpNumber, caInt + MAX_DIGITS + iExp );
		
		// Eliminate trailing zeroes
		while( cpNumber[strlen( cpNumber ) - 1] == '0' )
			cpNumber[strlen( cpNumber ) - 1] = '\0';				
	}
	
	// Handle decimal notation with leading zeroes
	else if( (iExp <= -MAX_DIGITS) && (iExp > -(MAX_DIGITS + iZeroes)) )
	{
		// Integer part and decimal point
		strcpy( cpNumber, "0." );
		iExp += MAX_DIGITS;
		
		// Other zeroes
		for( ; iExp; iExp++ )
			strcat( cpNumber, "0" );
		
		// Eliminate trailing zeroes
		while( caInt[strlen( caInt ) - 1] == '0' )
			caInt[strlen( caInt ) - 1] = '\0';
			
		// The rest of the number
		strcat( cpNumber, caInt );
	}
	
	else
	// Handle exponential notation
	{
		// Build the number part
		*cpNumber++ = *caInt;
		*cpNumber++ = '.';
		strcpy( cpNumber, caInt + 1 );

		// Convert the exponent to ascii		
		iExp += MAX_DIGITS - 1;
		itoa( caInt, iExp );
		
		// Build the exponent part
		strcat( cpNumber, "e" );
		if( iExp > 0 )
			strcat( cpNumber, "+" );
		strcat( cpNumber, caInt );

		// Eliminate trailing zeroes
		while( cpNumber[strlen( cpNumber ) - 1] == '0' )
			cpNumber[strlen( cpNumber ) - 1] = '\0';				
	}
	
	// We're done
	return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -