//----------------------------------------------------------------------------- // File: HelloMath2.cpp // Class: None // Parent: None // Children: None // Purpose: Tests out various mathematical functions and reads & writes to file. // Author: Melanie Fox // Date: 4/13/07 //----------------------------------------------------------------------------- // The following are standard C/C++ header files. // If a filename is enclosed inside < > it means the header file is in the Include directory. // If a filename is enclosed inside " " it means the header file is in the current directory. #include // Character Types #include // Mathematical Constants #include // Variable Argument Lists #include // Standard Input/Output Functions #include // Utility Functions #include // String Operations #include // Signals (Contol-C + Unix System Calls) #include // Nonlocal Goto (For Control-C) #include // Time and Date information #include // Verify Program Assertion #include // Error Codes (Used in Unix system()) #include // Floating Point Constants #include // Implementation Constants #include // Standard Definitions #include // Exception handling (e.g., try, catch throw) //----------------------------------------------------------------------------- #define PI 3.14159265358979 #define INPUT_ANGLE_ARRAY_SIZE 100 #define PRECISION_ARRAY_SIZE 20 #define LOWER_INPUT_ANGLE_LIMIT 180 #define UPPER_INPUT_ANGLE_LIMIT 720 #define DEFAULT_PRECISION_VALUE 5 #define DEFAULT_ANGLE_VALUE 360 #define LOWER_PRECISION_LIMIT 1 #define UPPER_PRECISION_LIMIT 17 #define OUTPUT_FILENAME "HelloMath2.txt" //----------------------------------------------------------------------------- // Prototypes for local functions (functions not called by code in other files) //----------------------------------------------------------------------------- bool GetStringFromKeyboard( char inputString[], unsigned long sizeOfString ); bool GetStringFromFile( char inputString[], unsigned long sizeOfString, FILE *fptr ); bool WriteStringToScreen( const char outputString[] ); bool WriteStringToFile( const char outputString[], FILE *fptr ); bool WriteDoubleToFileWithEExponentInSpecifiedPrecision( double x, int precision, FILE *fptr ); const char* ConvertStringToDouble( const char *s, double &returnValue, double defaultValue ); const char* ConvertStringToLong( const char *s, long &returnValue, long defaultValue ); double ConvertFromRadiansToDegrees( double angleInRadians ); double ConvertFromDegreesToRadians( double angleInDegrees ); FILE* FileOpenWithMessageIfCannotOpen( const char *filename, const char *attribute ); //----------------------------------------------------------------------------- int main( void ) { // Prompt user to enter the value of an angle in degrees & store the string. char angleInDegreesString[INPUT_ANGLE_ARRAY_SIZE]; WriteStringToScreen( "Enter an angle in degrees from 180 to 720: " ); GetStringFromKeyboard(angleInDegreesString, INPUT_ANGLE_ARRAY_SIZE); WriteStringToScreen( "\nYou entered: " ); WriteStringToScreen( angleInDegreesString ); //Check if entered angle is an integer & within range. If not, assign default value. int inputNotAnInteger = 0; long angleInDegrees = DEFAULT_ANGLE_VALUE; if( ConvertStringToLong( angleInDegreesString, angleInDegrees, DEFAULT_ANGLE_VALUE ) == NULL ) inputNotAnInteger = 1; int inputNotInRange = 0; if( ( angleInDegrees < LOWER_INPUT_ANGLE_LIMIT ) || ( angleInDegrees > UPPER_INPUT_ANGLE_LIMIT ) ) inputNotInRange = 1; if( inputNotAnInteger || inputNotInRange ) WriteStringToScreen( "Entered quantity is not an integer between 180 & 720.\nAngle of 360 degrees will be used instead.\n" ); //Prompt user to enter a precision value for writing numbers. char precisionString[PRECISION_ARRAY_SIZE]; WriteStringToScreen( "Enter the precision for writing numbers, from 1 to 17: " ); GetStringFromKeyboard( precisionString, PRECISION_ARRAY_SIZE ); //Check if entered precision is an integer & within range, if not assign default value. inputNotAnInteger = 0; long precision = DEFAULT_PRECISION_VALUE; if( ConvertStringToLong( precisionString, precision, DEFAULT_PRECISION_VALUE ) == NULL ) inputNotAnInteger = 1; inputNotInRange = 0; if( ( precision < LOWER_PRECISION_LIMIT ) || ( precision > UPPER_PRECISION_LIMIT ) ) inputNotInRange = 1; if( inputNotAnInteger || inputNotInRange ) WriteStringToScreen( "Entered precision is not an integer from 1 to 17.\nPrecision of 5 will be used instead.\n" ); //Find degrees, radians, cos, sin, & tan for all integer angles up to input angle and print to file. const char outputFile[50] = OUTPUT_FILENAME; const char fileAttribute[10] = "w"; FILE* pointerToFile = FileOpenWithMessageIfCannotOpen( outputFile, fileAttribute ); for( int i = 0; i <= angleInDegrees; i++ ) { double angleInRadians = ConvertFromDegreesToRadians( i ); WriteDoubleToFileWithEExponentInSpecifiedPrecision( i, precision, pointerToFile ); WriteDoubleToFileWithEExponentInSpecifiedPrecision( angleInRadians, precision, pointerToFile ); WriteDoubleToFileWithEExponentInSpecifiedPrecision( sin( angleInRadians ), precision, pointerToFile ); WriteDoubleToFileWithEExponentInSpecifiedPrecision( cos( angleInRadians ), precision, pointerToFile ); WriteDoubleToFileWithEExponentInSpecifiedPrecision( tan( angleInRadians ), precision, pointerToFile ); WriteStringToFile( "\r", pointerToFile ); } fclose(pointerToFile); //Pause before exiting program until key is pressed. getchar(); // A normal program exit returns 0 (other return values usually signal an error) return 0; } //----------------------------------------------------------------------------- bool WriteDoubleToFileWithEExponentInSpecifiedPrecision( double x, int precision, FILE *fptr ) { // Ensure the precision (number of digits in the mantissa after the decimal point) makes sense. // Next, calculate the field width so it includes one extra space to the right of the number. if( precision < 0 || precision > 17 ) precision = 15; int fieldWidth = precision + 8; // Create the format specifier and print the number char format[20]; sprintf( format, " %%- %d.%dE", fieldWidth, precision ); return fprintf( fptr, format, x ) > 0; } //----------------------------------------------------------------------------- bool GetStringFromFile( char inputString[], unsigned long sizeOfString, FILE *fptr ) { return( fgets( inputString, sizeOfString, fptr ) ); } //----------------------------------------------------------------------------- bool GetStringFromKeyboard( char inputString[], unsigned long sizeOfString ) { return( GetStringFromFile( inputString, sizeOfString, stdin ) ); } //----------------------------------------------------------------------------- bool WriteStringToFile( const char outputString[], FILE *fptr ) { return( fprintf( fptr, "%s\n", outputString ) ); } //----------------------------------------------------------------------------- bool WriteStringToScreen( const char outputString[] ) { return( WriteStringToFile( outputString, stdout ) ); } //----------------------------------------------------------------------------- const char* ConvertStringToDouble( const char *s, double &returnValue, double defaultValue ) { // Default return value (in case the string is not a valid number) returnValue = defaultValue; // Check if s is a NULL string or "&^%$#" or "abc" or "123huh" if( s ) { // Use the standard math function strtod to parse the number char *pointerToCharacterAfterNumber = NULL; double x = strtod( s, &pointerToCharacterAfterNumber ); // Ensure the character after the number is a space or '\0', not 'a' or 'z' or ... char characterAfterNumber = pointerToCharacterAfterNumber ? *pointerToCharacterAfterNumber : 'z'; if( characterAfterNumber == '\0' || isspace(characterAfterNumber) ) { returnValue = x; return pointerToCharacterAfterNumber; } } return NULL; } //----------------------------------------------------------------------------- double ConvertFromRadiansToDegrees( double angleInRadians ) { return( angleInRadians*180.0/PI ); } //----------------------------------------------------------------------------- double ConvertFromDegreesToRadians( double angleInDegrees ) { return( angleInDegrees*PI/180.0 ); } //----------------------------------------------------------------------------- const char* ConvertStringToLong( const char *s, long &returnValue, long defaultValue ) { // Default return value (in case the string is not a valid number) returnValue = defaultValue; // Check if s is a NULL string or "&^%$#" or "abc" or "123huh" if( s ) { // Use the standard math function strtod to parse the number char *pointerToCharacterAfterNumber = NULL; double x = strtol( s, &pointerToCharacterAfterNumber, 10 ); // Ensure the character after the number is a space or '\0', not 'a' or 'z' or ... char characterAfterNumber = pointerToCharacterAfterNumber ? *pointerToCharacterAfterNumber : 'z'; if( characterAfterNumber == '\0' || isspace(characterAfterNumber) ) { returnValue = x; return pointerToCharacterAfterNumber; } } return NULL; } //----------------------------------------------------------------------------- FILE* FileOpenWithMessageIfCannotOpen( const char *filename, const char *attribute ) { FILE *pointerToFile = fopen( filename, attribute ); if( pointerToFile == NULL) { WriteStringToScreen( "File could not be opened." ); return 0; } return pointerToFile; }