Calculator γραμμένο σε C

...του ubuntu και έργων ΕΛ/ΛΑΚ (Έργα-Οδηγοί-Προτάσεις)

Συντονιστής: konnn

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό UnKnown96 » 06 Ιουν 2011, 19:02

konnn έγραψε:
UnKnown96 έγραψε:Εννοώ ότι ας πούμε ότι διαλέγεις την επιλογή 4 (διέρεση) και δώσεις 9/2 αντί να βγάλει 3,5 βγάζει 4...

Αυτό συμβαίνει διότι οι μεταβλητές σου είναι integer, δηλαδή ακέραιοι.
edit:9/2=4,5.


Είμουν πολύ βιαστικός εκείνη την στιγμή που απαντούσα και το έγραψα λάθος χωρίς να το καταλάβω :)

migf1 έγραψε:Καλημέρα, μόλις έτρεξα το πρόγραμμα και αμέσως εντόπισα 2 προβλήματα:
1. Αν αντί για νούμερο δώσω string, μπαίνει σε infinite loop
2. Αν διαιρέσεις με το 0, κρασάρει

Δεν έχω προλάβει να δω κώδικα ακόμα, αλλά τα παραπάνω είναι εύκολο να διορθωθούν. Επίσης, θα ήταν πολύ καλύτερα αν οι όροι διαβάζονταν και οι 2 σε μια γραμμή κι όχι ξεχωριστά.


Σε ευχαριστώ πάρα πολύ!
Θα τον μελετίσω αμέσως :)
Άβαταρ μέλους
UnKnown96
dudeTUX
dudeTUX
 
Δημοσιεύσεις: 370
Εγγραφή: 08 Ιουν 2010, 15:23
Τοποθεσία: Ρόδος
Εκτύπωση

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό migf1 » 06 Ιουν 2011, 22:03

UnKnown96 έγραψε:
Σε ευχαριστώ πάρα πολύ!
Θα τον μελετίσω αμέσως :)

Τίποτα, να 'σαι καλά :)

Υπάρχουν διάφορα που μπορείς να βελτιώσεις ακόμα, όπως π.χ. το να διαβάζεις το input του χρήστη ως string και να το μετατρέπεις μετά σε double ή int, με έτοιμες συναρτήσεις όπως π.χ. οι strtod() και atoi().

Αν σκέφτεσαι να το πας ένα επίπεδο παραπάνω πάντως, μαθαίνοντας ταυτόχρονα τη γλώσσα, τα calculators συνήθως υλοποιούνται με τη χρήση στοίβας (stack) για τις πράξεις και τους όρους, και reverse polish notation για την διαχείριση της προτεραιότητας στις πράξεις.

Ανάλυση σχετικού αλγόριθμου μαζί με κώδικα μπορείς να διαβάσεις εδώ:
http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Stack/
(θα βρεις πολλούς και μόνος σου αν το ψάξεις).

Πλήρη ανάλυση ειδικά για το Reverse Polish Notation μπορείς να διαβάσεις στο σχετικό άρθρο της Wikipedia:
http://en.wikipedia.org/wiki/Reverse_Polish_notation

Ένας πολύ απλοποιημένος κώδικας είναι επίσης αυτός:
http://www.java2s.com/Code/C/Data-Struc ... ulator.htm

Αν έχω καταλάβει καλά δεν έχεις μεγάλη εμπειρία, οπότε τα παραπάνω μπορεί να σου φαντάζουν... κινέζικα, αλλά ίσως σου φανούν χρήσιμα όσο προχωράς την εκμάθησή σου. Ειδικά η στοίβα (stack) είναι από τις πιο απλές δομές δεδομένων και χρησιμοποιείται κατά κόρον σε διάφορες εφαρμογές (προσωπικά για να θυμηθώ τα παλιά έφτιαξα πριν λίγο καιρό το παιχνίδι της Ξερής σε στάνταρ C, χρησιμοποιώντας κατά κόρον στοίβες για τα χαρτιά του τραπεζιού και τα μαζέματα των παικτών... αν νομίζεις πως μπορεί να σου φανεί χρήσιμο πες μου να σου δώσω τον κώδικα).
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό migf1 » 07 Ιουν 2011, 15:24

Σου παραθέτω μερικές ακόμα προσθήκες στον κώδικα, που πλέον διαβάζει τους αριθμούς ως 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 );
}

Τελευταία επεξεργασία από migf1 και 17 Ιουν 2011, 00:55, έχει επεξεργασθεί 1 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό UnKnown96 » 08 Ιουν 2011, 16:24

Ετιμάζω την version2 (v2), ο κώδικας σου με βοηθάει πάρα πολύ να βάλω ορισμένα πράγματα που θέλω, αν και έχει πολλά bugs.
Άβαταρ μέλους
UnKnown96
dudeTUX
dudeTUX
 
Δημοσιεύσεις: 370
Εγγραφή: 08 Ιουν 2010, 15:23
Τοποθεσία: Ρόδος
Εκτύπωση

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό migf1 » 08 Ιουν 2011, 17:40

Τι είδους bugs?
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό UnKnown96 » 08 Ιουν 2011, 17:59

Μόλις πάρεις το αποτέλεσμα σου δίχνει το το menu 2 φορές μαζί με το error ότι έδωσες λάθως απάντηση.
Επείσης όταν δώσεις λάθως απάντηση σου βγένει το error + τις 2 φόρες το Menu μαζί με το error πάλι...
Για αυτό τον λόγο δεν θα ενσοματόσω τον ελεγχο του fflush (stdin) στο δικό μου διότι πιο πολλά προβλήματα προκαλεί παρά βοήθεια.
Άβαταρ μέλους
UnKnown96
dudeTUX
dudeTUX
 
Δημοσιεύσεις: 370
Εγγραφή: 08 Ιουν 2010, 15:23
Τοποθεσία: Ρόδος
Εκτύπωση

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό migf1 » 08 Ιουν 2011, 18:16

Δεν κατάλαβα τι εννοείς.

Το μενού δεν βγαίνει 2 φορές. Σε κάθε απάντηση που δίνεις το πρόγραμμα κάνει ότι έχει να κάνει, τυπώνει το αποτέλεσμα ή το σφάλμα και εμφανίζει πάλι το μενού περιμένοντας την επόμενη επιλογή σου. Αυτό δεν είναι bug, είναι ο τρόπος που επέλεξα να δουλεύει το πρόγραμμα.

ΥΓ. Btw, το fflush(stdin) δεν έχει καμία σχέση με τα παραπάνω.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό UnKnown96 » 08 Ιουν 2011, 18:25

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

AVAILABLE OPTIONS
=================
1. Addition
2. Subtraction
3. Multiplication
4. Division
5. Percentage
6. Power
7. Square Root
8. Exit

Your choice: 1 <--- αυτό το έγραψα εγώ

output:

Addition
--------
1st addendum: 23
2nd addendum: 24
--------
RESULT: 47


AVAILABLE OPTIONS
=================
1. Addition
2. Subtraction
3. Multiplication
4. Division
5. Percentage
6. Power
7. Square Root
8. Exit

Your choice: Wrong answer...


AVAILABLE OPTIONS
=================
1. Addition
2. Subtraction
3. Multiplication
4. Division
5. Percentage
6. Power
7. Square Root
8. Exit

Your choice:



Όπως βλέπεις έβγαλε ξανά το μενού, υπόθεσε μια λάθος απάντηση μόνο του, χωρίς να γράψω τίποτα και μετά με ρωτάει τι πράξη θέλω να κάνω...
Αυτό το bug λέω...
Άβαταρ μέλους
UnKnown96
dudeTUX
dudeTUX
 
Δημοσιεύσεις: 370
Εγγραφή: 08 Ιουν 2010, 15:23
Τοποθεσία: Ρόδος
Εκτύπωση

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό migf1 » 08 Ιουν 2011, 18:34

Μήπως αφαίρεσες κάνα fflush(stdin) ?
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Calculator γραμμένο σε C

Δημοσίευσηαπό UnKnown96 » 08 Ιουν 2011, 18:38

Κανένα. Το ανίγω όμως μέσα από FreeBSD.
Τι κάνει η εντολή αυτή;
Δοκίμασες την v2 που έκανα post πριν μισή ώρα;
Άβαταρ μέλους
UnKnown96
dudeTUX
dudeTUX
 
Δημοσιεύσεις: 370
Εγγραφή: 08 Ιουν 2010, 15:23
Τοποθεσία: Ρόδος
Εκτύπωση

ΠροηγούμενηΕπόμενο

Επιστροφή στο Ανάπτυξη Λογισμικού / Αλγόριθμοι