/*
* Starting with C: Primitive 2 operands calculator
*/
#include <stdio.h>
#include <ctype.h> // for tolower()
#include <math.h> // for pow(), sqrt(), ...
#include <stdlib.h> // for exit()
#include <errno.h> // for errno
#define MAXSLEN_LINEBUF 255+1 // for reading menu * nums as a strings
typedef enum { FALSE= 0 , TRUE } bool; // our custom boolean type
// -------------------------------------------------------------------------------
// Read s from stdin until either 'ENTER is pressed or len-1 chars have been entered
// Remove ENTER (if any), null terminate s and return it
//
char * s_get( char * s, size_t len)
{
register char * cp;
for ( cp
= s
; ( * cp
= getc ( stdin
) ) != '\n ' && ( cp
- s
) < len
- 1 ; cp
++ ) ; // for-loop with empty body */
* cp = '\0 ' ; // null-terminate last character
return s;
}
// -------------------------------------------------------------------------------
// Read num as a string from stdin and convert it to double. Demand a successfull
// convertion (otherwise keep asking). The conversion is done via the standard
// function: strtod()... read the C manual for more info.
//
void num_askuser( char * prompt, double * num, int maxslen_num )
{
char inbuf[ maxslen_num ] , * pend= NULL;
bool stop;
do
{
errno = 0 ; // reset errno (defined in <errno.h>
stop = TRUE; // reset boolen flag
printf ( prompt
) ; // display a prompt asking for input fflush ( stdin
) ; // clear the input buffer (stdin) s_get( inbuf, maxslen_num ) ; // read user input as string in inbuf
* num
= strtod ( inbuf
, & pend
) ; // convert it to double if ( * pend ) // *pend != '\0', possibly invalid num
{
if ( * num == 0.0 ) { // num was indeed invalid, not converted
puts ( "\t *** error: invalid number" ) ; stop = FALSE;
continue ;
}
else { // converted ok, invalid chars ignored
printf ( "\t *** info: \" %s\" ignored\n " , pend
) ; stop = TRUE;
continue ;
}
}
if ( errno == ERANGE ) // too big (or too small) num
{
puts ( "\t *** error: number out of range" ) ; stop = FALSE;
}
} while ( ! stop || * inbuf == '\0 ' ) ;
return ;
}
// -------------------------------------------------------------------------------
int main ( void )
{
double x, y; // operands
int stop = FALSE; // boolean controlling the main loop
#ifdef __GNUC__
char inbuf[ MAXSLEN_LINEBUF ] ; // menu choice
#endif
do { // display menu
puts ( "\n \n AVAILABLE OPTIONS\n =================" ) ; printf ( "1 or +\t add\n 2 or -\t subtract\n 3 or *\t multiply\n 4 or /\t divide\n 5 or %%\t percentage\n 6 or ^\t power\n 7\t square root\n 8 or x\t exit\n \n Your choice: " ) ;
fflush ( stdin
) ; // clear input buffer #ifdef __GNUC__
switch ( tolower ( * s_get
( inbuf
, MAXSLEN_LINEBUF
) ) ) // GET USER CHOICE #else
#endif
{
case '1' : // 1. ADDITTION
case '+' :
puts ( "\n Addition\n --------" ) ; num_askuser( "1st addendum: " , & x, MAXSLEN_LINEBUF) ;
num_askuser( "2nd addendum: " , & y, MAXSLEN_LINEBUF) ;
printf ( "--------\n RESULT: %g + %g = %g\n " , x, y, x + y ) ;
break ;
case '2' : // 2. SUBTRACTION
case '-' :
puts ( "\n Subtraction\n -----------" ) ; num_askuser( "Reducer : " , & x, MAXSLEN_LINEBUF) ;
num_askuser( "Subtrahend: " , & y, MAXSLEN_LINEBUF) ;
printf ( "-----------\n RESULT: %g - %g = %g\n " , x, y, x - y ) ;
break ;
case '3' : // 3. MULTIPLICATION
case '*' :
puts ( "\n Multiplication\n --------------" ) ; num_askuser( "1st number: " , & x, MAXSLEN_LINEBUF) ;
num_askuser( "2nd number: " , & y, MAXSLEN_LINEBUF) ;
printf ( "--------------\n RESULT: %g * %g = %g\n " , x, y, x * y ) ;
break ;
case '4' : // 4. DIVISION
case '/' :
{ double intpart;
puts ( "\n Division\n --------" ) ; num_askuser( "Divident: " , & x, MAXSLEN_LINEBUF) ;
do { // demand non-zero value
num_askuser( "Divisor : " , & y, MAXSLEN_LINEBUF) ;
if ( y == 0.0 )
puts ( "*** error: divisor cannot be 0" ) ; } while ( y == 0.0 ) ;
printf ( "--------\n RESULT: %g / %g = %g (quotient = %g, remainder = %g)\n " , x
, y
, x
/ y
, trunc
( x
/ y
) , y
* modf ( x
/ y
, & intpart
) ) ; }
break ;
case '5' : // 5. PERCENTAGE
case '%' :
puts ( "\n Percentage\n ----------" ) ; num_askuser( "Number: " , & x, MAXSLEN_LINEBUF) ;
printf ( "----------\n RESULT: %g%% = %g\n " , x
, x
/ 100 ) ; break ;
case '6' : // 6. POWER
case '^' :
num_askuser( "Base : " , & x, MAXSLEN_LINEBUF) ;
num_askuser( "Exponent: " , & y, MAXSLEN_LINEBUF) ;
printf ( "-----\n RESULT: %g ^ %g = %g\n " , x
, y
, pow ( x
, y
) ) ; break ;
case '7' : // 7. SQUARE ROOT
puts ( "\n Square Root\n -----------" ) ; num_askuser( "Number: " , & x, MAXSLEN_LINEBUF) ;
printf ( "-----------\n RESULT: sqrt(%g) = %g\n " , x
, sqrt ( x
) ) ; break ;
case '8' : // 8. EXIT
case 'x' :
stop = TRUE;
break ;
default : // ALL OTHER CHOICES
puts ( "*** error: invalid choice, try again..." ) ; break ;
} // switch
} while ( ! stop ) ;
}
LyoKICogU3RhcnRpbmcgd2l0aCBDOiBQcmltaXRpdmUgMiBvcGVyYW5kcyBjYWxjdWxhdG9yCiAqLwoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxjdHlwZS5oPgkJCQkvLyBmb3IgdG9sb3dlcigpCiNpbmNsdWRlIDxtYXRoLmg+CQkJCS8vIGZvciBwb3coKSwgc3FydCgpLCAuLi4KI2luY2x1ZGUgPHN0ZGxpYi5oPgkJCQkvLyBmb3IgZXhpdCgpCiNpbmNsdWRlIDxlcnJuby5oPgkJCQkvLyBmb3IgZXJybm8KCiNkZWZpbmUgTUFYU0xFTl9MSU5FQlVGCQkyNTUrMQkJLy8gZm9yIHJlYWRpbmcgbWVudSAqIG51bXMgYXMgYSBzdHJpbmdzCgp0eXBlZGVmIGVudW0geyBGQUxTRT0wLCBUUlVFIH0gYm9vbDsJCS8vIG91ciBjdXN0b20gYm9vbGVhbiB0eXBlCgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIFJlYWQgcyBmcm9tIHN0ZGluIHVudGlsIGVpdGhlciAnRU5URVIgaXMgcHJlc3NlZCBvciBsZW4tMSBjaGFycyBoYXZlIGJlZW4gZW50ZXJlZAovLyBSZW1vdmUgRU5URVIgKGlmIGFueSksIG51bGwgdGVybWluYXRlIHMgYW5kIHJldHVybiBpdAovLwpjaGFyICpzX2dldChjaGFyICpzLCBzaXplX3QgbGVuKQp7CglyZWdpc3RlciBjaGFyICpjcDsKCglmb3IgKGNwPXM7ICgqY3A9Z2V0YyhzdGRpbikpICE9ICdcbicgJiYgKGNwLXMpIDwgbGVuLTE7IGNwKysgKQoJCTsJCQkJCS8vIGZvci1sb29wIHdpdGggZW1wdHkgYm9keSAqLwoJKmNwID0gJ1wwJzsJCQkJCS8vIG51bGwtdGVybWluYXRlIGxhc3QgY2hhcmFjdGVyCgoJcmV0dXJuIHM7Cn0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gUmVhZCBudW0gYXMgYSBzdHJpbmcgZnJvbSBzdGRpbiBhbmQgY29udmVydCBpdCB0byBkb3VibGUuIERlbWFuZCBhIHN1Y2Nlc3NmdWxsCi8vIGNvbnZlcnRpb24gKG90aGVyd2lzZSBrZWVwIGFza2luZykuIFRoZSBjb252ZXJzaW9uIGlzIGRvbmUgdmlhIHRoZSBzdGFuZGFyZAovLyBmdW5jdGlvbjogc3RydG9kKCkuLi4gcmVhZCB0aGUgQyBtYW51YWwgZm9yIG1vcmUgaW5mby4KLy8Kdm9pZCBudW1fYXNrdXNlciggY2hhciAqcHJvbXB0LCBkb3VibGUgKm51bSwgaW50IG1heHNsZW5fbnVtICkKewoJY2hhciBpbmJ1ZlsgbWF4c2xlbl9udW0gXSwgKnBlbmQ9TlVMTDsKCWJvb2wgc3RvcDsKCglkbwoJewoJCWVycm5vID0gMDsJCQkJCQkJCS8vIHJlc2V0IGVycm5vIChkZWZpbmVkIGluIDxlcnJuby5oPgoJCXN0b3AgPSBUUlVFOwkJCS8vIHJlc2V0IGJvb2xlbiBmbGFnCgoJCXByaW50ZiggcHJvbXB0ICk7CQkvLyBkaXNwbGF5IGEgcHJvbXB0IGFza2luZyBmb3IgaW5wdXQKCQlmZmx1c2goc3RkaW4pOwkJCS8vIGNsZWFyIHRoZSBpbnB1dCBidWZmZXIgKHN0ZGluKQoJCXNfZ2V0KCBpbmJ1ZiwgbWF4c2xlbl9udW0gKTsJLy8gcmVhZCB1c2VyIGlucHV0IGFzIHN0cmluZyBpbiBpbmJ1ZgoKCQkqbnVtID0gc3RydG9kKCBpbmJ1ZiwgJnBlbmQgKTsJLy8gY29udmVydCBpdCB0byBkb3VibGUKCQlpZiAoICpwZW5kICkJCQkvLyAqcGVuZCAhPSAnXDAnLCBwb3NzaWJseSBpbnZhbGlkIG51bQoJCXsKCQkJaWYgKCAqbnVtID09IDAuMCApIHsgCS8vIG51bSB3YXMgaW5kZWVkIGludmFsaWQsIG5vdCBjb252ZXJ0ZWQKCQkJCXB1dHMoIlx0KioqIGVycm9yOiBpbnZhbGlkIG51bWJlciIpOwoJCQkJc3RvcCA9IEZBTFNFOwoJCQkJY29udGludWU7CgkJCX0KCQkJZWxzZSB7CQkJLy8gY29udmVydGVkIG9rLCBpbnZhbGlkIGNoYXJzIGlnbm9yZWQKCQkJCXByaW50ZigiXHQqKiogaW5mbzogXCIlc1wiIGlnbm9yZWRcbiIsIHBlbmQpOwoJCQkJc3RvcCA9IFRSVUU7CgkJCQljb250aW51ZTsKCQkJfQoJCX0KCgkJaWYgKCBlcnJubyA9PSBFUkFOR0UgKQkJLy8gdG9vIGJpZyAob3IgdG9vIHNtYWxsKSBudW0KCQl7CgkJCXB1dHMoIlx0KioqIGVycm9yOiBudW1iZXIgb3V0IG9mIHJhbmdlIik7CgkJCXN0b3AgPSBGQUxTRTsKCQl9CgoJfSB3aGlsZSAoICFzdG9wIHx8ICppbmJ1ZiA9PSdcMCcgKTsKCglyZXR1cm47Cn0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KaW50IG1haW4gKHZvaWQpCnsKCWRvdWJsZSB4LCB5OyAJCQkJLy8gb3BlcmFuZHMKCWludCBzdG9wID0gRkFMU0U7CQkJLy8gYm9vbGVhbiBjb250cm9sbGluZyB0aGUgbWFpbiBsb29wCiNpZmRlZiBfX0dOVUNfXwoJY2hhciBpbmJ1ZlsgTUFYU0xFTl9MSU5FQlVGIF07CQkvLyBtZW51IGNob2ljZSAKI2VuZGlmCglkbyB7CQkJCQkvLyBkaXNwbGF5IG1lbnUKCQlwdXRzKCJcblxuQVZBSUxBQkxFIE9QVElPTlNcbj09PT09PT09PT09PT09PT09Iik7CgkJcHJpbnRmICgiMSBvciArXHQgYWRkXG4yIG9yIC1cdCBzdWJ0cmFjdFxuMyBvciAqXHQgbXVsdGlwbHlcbjQgb3IgL1x0IGRpdmlkZVxuNSBvciAlJVx0IHBlcmNlbnRhZ2VcbjYgb3IgXlx0IHBvd2VyXG43XHQgc3F1YXJlIHJvb3Rcbjggb3IgeFx0IGV4aXRcblxuWW91ciBjaG9pY2U6ICIpOwoKCQlmZmx1c2goc3RkaW4pOwkJCS8vIGNsZWFyIGlucHV0IGJ1ZmZlcgojaWZkZWYgX19HTlVDX18KCQlzd2l0Y2ggKCB0b2xvd2VyKCAqc19nZXQoaW5idWYsIE1BWFNMRU5fTElORUJVRikgKSApLy8gR0VUIFVTRVIgQ0hPSUNFCiNlbHNlCgkJc3dpdGNoICggdG9sb3dlciggZ2V0Y2hhcigpICkgKQkvLyBHRVQgVVNFUiBDSE9JQ0UKI2VuZGlmCgkJewoJCQljYXNlICcxJzoJCS8vIDEuIEFERElUVElPTgoJCQljYXNlICcrJzoKCQkJCXB1dHMoIlxuQWRkaXRpb25cbi0tLS0tLS0tIik7CgkJCQludW1fYXNrdXNlcigiMXN0IGFkZGVuZHVtOiAiLCAmeCwgTUFYU0xFTl9MSU5FQlVGKTsKCQkJCW51bV9hc2t1c2VyKCIybmQgYWRkZW5kdW06ICIsICZ5LCBNQVhTTEVOX0xJTkVCVUYpOwoJCQkJcHJpbnRmICgiLS0tLS0tLS1cblJFU1VMVDogJWcgKyAlZyA9ICVnXG4iLAoJCQkJeCwgeSwgeCArIHkgKTsKCQkJYnJlYWs7CgoJCQljYXNlICcyJzoJCS8vIDIuIFNVQlRSQUNUSU9OCgkJCWNhc2UgJy0nOgoJCQkJcHV0cygiXG5TdWJ0cmFjdGlvblxuLS0tLS0tLS0tLS0iKTsKCQkJCW51bV9hc2t1c2VyKCJSZWR1Y2VyICAgOiAiLCAmeCwgTUFYU0xFTl9MSU5FQlVGKTsKCQkJCW51bV9hc2t1c2VyKCJTdWJ0cmFoZW5kOiAiLCAmeSwgTUFYU0xFTl9MSU5FQlVGKTsKCQkJCXByaW50ZiAoIi0tLS0tLS0tLS0tXG5SRVNVTFQ6ICVnIC0gJWcgPSAlZ1xuIiwKCQkJCQl4LCB5LCB4IC0geSApOwoJCQlicmVhazsKCgkJCWNhc2UgJzMnOgkJLy8gMy4gTVVMVElQTElDQVRJT04KCQkJY2FzZSAnKic6CgkJCQlwdXRzKCJcbk11bHRpcGxpY2F0aW9uXG4tLS0tLS0tLS0tLS0tLSIpOwoJCQkJbnVtX2Fza3VzZXIoIjFzdCBudW1iZXI6ICIsICZ4LCBNQVhTTEVOX0xJTkVCVUYpOwoJCQkJbnVtX2Fza3VzZXIoIjJuZCBudW1iZXI6ICIsICZ5LCBNQVhTTEVOX0xJTkVCVUYpOwoJCQkJcHJpbnRmICgiLS0tLS0tLS0tLS0tLS1cblJFU1VMVDogJWcgKiAlZyA9ICVnXG4iLAoJCQkJCXgsIHksIHggKiB5ICk7CgkJCWJyZWFrOwoKCQkJY2FzZSAnNCc6CQkvLyA0LiBESVZJU0lPTgoJCQljYXNlICcvJzoKCQkJewlkb3VibGUgaW50cGFydDsKCQkJCXB1dHMoIlxuRGl2aXNpb25cbi0tLS0tLS0tIik7CgkJCQludW1fYXNrdXNlcigiRGl2aWRlbnQ6ICIsICZ4LCBNQVhTTEVOX0xJTkVCVUYpOwoJCQkJZG8gewkJCQkJCQkvLyBkZW1hbmQgbm9uLXplcm8gdmFsdWUKCQkJCSAgIG51bV9hc2t1c2VyKCJEaXZpc29yIDogIiwgJnksIE1BWFNMRU5fTElORUJVRik7CgkJCQkgICBpZiAoIHkgPT0gMC4wICkKCQkJCQkgIHB1dHMoIioqKiBlcnJvcjogZGl2aXNvciBjYW5ub3QgYmUgMCIpOwoJCQkJfSB3aGlsZSAoeSA9PSAwLjApOwoJCQkJcHJpbnRmICgiLS0tLS0tLS1cblJFU1VMVDogJWcgLyAlZyA9ICVnIChxdW90aWVudCA9ICVnLCByZW1haW5kZXIgPSAlZylcbiIsCgkJCQkJeCwgeSwgeC95LCB0cnVuYyh4L3kpLCB5ICogbW9kZih4L3ksICZpbnRwYXJ0KSApOwoJCQl9CgkJCWJyZWFrOwoKCQkJY2FzZSAnNSc6CQkvLyA1LiBQRVJDRU5UQUdFCgkJCWNhc2UgJyUnOgoJCQkJcHV0cygiXG5QZXJjZW50YWdlXG4tLS0tLS0tLS0tIik7CgkJCQludW1fYXNrdXNlcigiTnVtYmVyOiAiLCAmeCwgTUFYU0xFTl9MSU5FQlVGKTsKCQkJCXByaW50ZiAoIi0tLS0tLS0tLS1cblJFU1VMVDogJWclJSA9ICVnXG4iLCB4LCB4LzEwMCk7CgkJCWJyZWFrOwoKCQkJY2FzZSAnNic6CQkvLyA2LiBQT1dFUgoJCQljYXNlICdeJzoKCQkJCXB1dHMoIlxuUG93ZXJcbi0tLS0tIik7CgkJCQludW1fYXNrdXNlcigiQmFzZSAgICA6ICIsICZ4LCBNQVhTTEVOX0xJTkVCVUYpOwoJCQkJbnVtX2Fza3VzZXIoIkV4cG9uZW50OiAiLCAmeSwgTUFYU0xFTl9MSU5FQlVGKTsKCQkJCXByaW50ZiAoIi0tLS0tXG5SRVNVTFQ6ICVnIF4gJWcgPSAlZ1xuIiwgeCwgeSwgcG93KHgsIHkpKTsKCQkJYnJlYWs7CgoJCQljYXNlICc3JzoJCS8vIDcuIFNRVUFSRSBST09UCgkJCQlwdXRzKCJcblNxdWFyZSBSb290XG4tLS0tLS0tLS0tLSIpOwoJCQkJbnVtX2Fza3VzZXIoIk51bWJlcjogIiwgJngsIE1BWFNMRU5fTElORUJVRik7CgkJCQlwcmludGYgKCItLS0tLS0tLS0tLVxuUkVTVUxUOiBzcXJ0KCVnKSA9ICVnXG4iLCB4LCBzcXJ0KHgpICk7CgkJCWJyZWFrOwoKCQkJY2FzZSAnOCc6CQkvLyA4LiBFWElUCgkJCWNhc2UgJ3gnOgoJCQkJc3RvcCA9IFRSVUU7CgkJCWJyZWFrOwoKCQkJZGVmYXVsdDoJCS8vIEFMTCBPVEhFUiBDSE9JQ0VTCgkJCQlwdXRzKCIqKiogZXJyb3I6IGludmFsaWQgY2hvaWNlLCB0cnkgYWdhaW4uLi4iKTsKCQkJYnJlYWs7CgkJfQkvLyBzd2l0Y2gKCgl9IHdoaWxlICggIXN0b3AgKTsKCglleGl0KCAwICk7Cn0K