Δημοσιεύτηκε: 07 Ιουν 2011, 15:24
από migf1
Σου παραθέτω μερικές ακόμα προσθήκες στον κώδικα, που πλέον διαβάζει τους αριθμούς ως strings και τους μετατρέπει σε double, απαιτώντας παράλληλα να είναι έγκυροι πριν τους αποδεχτεί για την εκάστοτε πράξη (ο έλεγχος χρησιμοποιεί και την στάνταρ βιβλιοθήκη <errno.h>).

Επίσης προστέθηκαν μερικές ακόμα εναλλακτικές στις επιλογές του αρχικού μενού (+, -, *, /, %, ^ και x) ενώ έσβησα και τα σχόλια που παρέπεμπαν στον παλιό κώδικα. Το διάβασμα ενός string γίνεται με τη συνάρτηση: s_get() η οποία χρησιμοποιείται στην συνάρτηση: num_askuser(). Αυτή η τελευταία είναι που ζητάει τον κάθε αριθμό από τον χρήστη και κάνει όλους τους απαιτούμενους ελέγχους εγκυρότητας πριν τον επιστρέψει στη main(). Για την κατανόηση της λειτουργίας της είναι καλό πρώτα να διαβάσεις πως λειτουργεί η στάνταρ συνάρτηση: strtod() η οποία μετατρέπει strings σε double.

Έχω βάλει πολλά σχόλια στον κώδικα, αλλά στα Αγγλικά (ελπίζω να μην έχεις πρόβλημα)...

Κώδικας: Επιλογή όλων

#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_NUM 127+1 // for reading num as a string

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 ) // 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 = 0; // boolean controlling the main loop

do {
// display menu
puts("\n\nAVAILABLE OPTIONS\n=================");
printf ("1 or +\t add\n2 or -\t subtract\n3 or *\t multiply\n4 or /\t divide\n5 or %\t percentage\n6 or ^\t power\n7\t square root\n8 or x\t exit\n\nYour choice: ");

fflush(stdin); // clear input buffer
switch ( tolower( getchar() ) ) // GET USER CHOICE
{
case '1': // 1. ADDITTION
case '+':
puts("\nAddition\n--------");
num_askuser("1st addendum: ", &x, MAXSLEN_NUM);
num_askuser("2nd addendum: ", &y, MAXSLEN_NUM);
printf ("--------\nRESULT: %g + %g = %g\n", x, y, x + y);
break;

case '2': // 2. SUBTRACTION
case '-':
puts("\nSubtraction\n-----------");
num_askuser("Reducer : ", &x, MAXSLEN_NUM);
num_askuser("Subtrahend: ", &y, MAXSLEN_NUM);
printf ("-----------\nRESULT: %g - %g = %g\n", x, y, x - y);
break;

case '3': // 3. MULTIPLICATION
case '*':
puts("\nMultiplication\n--------------");
num_askuser("1st number: ", &x, MAXSLEN_NUM);
num_askuser("2nd number: ", &y, MAXSLEN_NUM);
printf ("--------------\nRESULT: %g * %g = %g\n", x, y, x * y);
break;

case '4': // 4. DIVISION
case '/':
{ double intpart;
puts("\nDivision\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 ("--------\nRESULT: %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("\nPercentage\n----------");
num_askuser("Number: ", &x, MAXSLEN_NUM);
printf ("----------\nRESULT: %g\% = %g\n", x, x/100);
break;

case '6': // 6. POWER
case '^':
puts("\nPower\n-----");
num_askuser("Base : ", &x, MAXSLEN_NUM);
num_askuser("Exponent: ", &y, MAXSLEN_NUM);
printf ("-----\nRESULT: %g ^ %g = %g\n", x, y, pow(x, y));
break;

case '7': // 7. SQUARE ROOT
puts("\nSquare Root\n-----------");
num_askuser("Number: ", &x, MAXSLEN_NUM);
printf ("-----------\nRESULT: sqrt(%g) = %g\n", x, sqrt(x) );
break;

case '8': // 8. EXIT
case 'x':
stop = 1; // TRUE
break;

default: // ALL OTHER CHOICES
puts("*** error: invalid choice, try again...");
break;
} // switch

} while ( !stop );

exit( 0 );
}