/* -----------------------------------------------------------------------------------
* Παράδειγμα κώδικα σε C για...
* το διάβασμα μιας γραμμής από την κύρια είσοδο
* αποθήκευσή της σε ένα string (linebuf)
* διάσπασή της σε επί μέρους λέξεις (stokens)
* μετατροπή της κάθε λέξης σε διάφορους τύπους αριθμών (με και χωρίς έλεγχο)
* τύπωμα των αποτελεσμάτων στην οθόνη
*
* Για απλές μετατροπές ενεργοποιήστε τη συνάρτηση: print_conv1simple()
* Για προχωρημένες μετατροπές ενεργοποιήστε τη συνάρτηση: print_conv2advanced()
*
* ( και οι 2 παραπάνω συναρτήσεις βρίσκονται απενεργοποιημένες μέσα σε σχόλια
* στην συνάρτηση main() στις γραμμές 198 και 207, αντίστοιχα )
* -----------------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define MAXLINE 255+1 // μέγιστο μήκος για τη γραμμή εισόδου
#define MAXTOKENS 3 // μέγιστο πλήθος tokens (λέξεων) ανά γραμμή
// Πρότυπα Συναρτήσεων
char *s_get(char */*s*/, int /*maxlen*/);
int s_tokenize(char */*s*/, char *[]/*tokens*/, int /*maxtokens*/, char */*delims*/);
void print_conv1simple( int /*ntokens*/, char *[]/*tokens*/ );
void print_conv2advanced( int /*ntokens*/, char *[]/*tokens*/ );
// -----------------------------------------------------------------------------------
// Διάβασμα του string s από την κύρια είσοδο, μέχρι να πατηθεί ENTER ή μέχρι να
// συμπληρωθούν maxlen-1 χαρακτήρες. Επιστρέφει το διαβασμένο s με μηδενισμένο τον
// τελευταίο χαρακτήρα (αν ήταν '\n' έχει αντικατασταθεί από '\0')
//
char *s_get(char *s, int maxlen)
{
register int i;
for (i
=0; (s
[i
]=getchar()) != '\n' && i
< maxlen
-1; i
++) ; // for-loop με κενό σώμα
s[i] = '\0'; // μηδενισμός τελικού χαρακτήρα
return s;
}
// -----------------------------------------------------------------------------------
// Διάσπαση του s σε έως maxtokens λέξεις, οι οποίες αποθηκεύονται στον πίνακα tokens[].
// Χαρακτήρες διαχωρισμού των tokens λογίζονται όσοι περιέχονται στο string delimiters.
// Επιστρέφει το πλήθος των tokens (λέξεων).
// ΣΗΜΑΝΤΙΚΟ: μετά το πέρας της συνάρτησης το αρχικο s έχει κατακερματιστεί (αν
// αυτό δεν είναι επιθυμητο, τότε θα πρέπει να περαστεί στην συνάρτηση
// κάποιο αντίγραφο του s).
//
int s_tokenize(char *s, char *tokens[], int maxtokens, char *delimiters)
{
register int i=0;
tokens
[0] = strtok(s
, delimiters
); // αποθήκευση 1ου token if (tokens[0] == NULL) // αποτυχία, πρόωρη έξοδος
return 0;
// αποθήκευση υπόλοιπων (έως maxtokens)
for (i
=1; i
< maxtokens
&& (tokens
[i
]=strtok(NULL
, delimiters
)) != NULL
; i
++) ; // for-loop με κενό σώμα
return i;
}
// -----------------------------------------------------------------------------------
// Απλή μετατροπή & τύπωμα των tokens ως int, long int και double, χρησιμοποιώντας
// την οικογένεια των στάνταρ συναρτήσεων ato?() ( ορίζονται στο <stdlib.h> )
// ΣΗΜΑΝΤΙΚΟ: Αυτές οι συναρτήσεις δεν δίνουν δυνατότητα ελέγχου για ενδεχόμενη
// αποτυχία της μετροπής. Αυτό το κάνουν οι συναρτήσεις strto?()
// ( δείτε παρακάτω την συνάρτηση: print_conv2advanced() )
//
void print_conv1simple( int ntokens, char *tokens[] )
{
int toi; // για αποθήκευση σε int
long int tol; // για αποθήκευση σε long int
double tod; // για αποθήκευση σε double
register int i; // για να διατρέξουμε τον tokens[]
for ( i=0; i < ntokens; i++ ) // όσο υπάρχουν tokens
{
// μετατροπές
toi
= atoi( tokens
[i
] ); // μετατροπή σε int tol
= atol( tokens
[i
] ); // μετατροπή σε long int tod
= atof (tokens
[i
] ); // μετατροπή σε double
// τύπωμα αποτελεσμάτων
printf("Token #%d: \"%s\"\n", i
+1, tokens
[i
]); // τύπωμα αρχικού token // τύπωμα των μετατροπών
printf( "as int: %d, as long: %ld, as double: %g\n\n", toi
, tol
, tod
); }
return;
}
// -----------------------------------------------------------------------------------
// Προχωρημένη μετατροπή & τύπωμα των tokens ως double, long και unsigned long,
// χρησιμοποιώντας την οικογένεια των στάνταρ συναρτήσεων strto?() ( ορίζονται
// στο <stdlib.h> ).
//
// Oι συναρτήσεις αυτές χρησιμοποιούν την στάνταρ καθολική μεταβλητή errno (ορίζεται
// στο αρχείο <errno.h>) καθώς κι ένα προσωρινό string ( ptail ) ως 2ο όρισμά τους
// προκειμένου να σηματοδοτήσουν ενδεχόμενη αποτυχία της μετατροπής. Το 3ο τους όρισμα
// είναι η αριθμητική βάση για την μετατροπή (δεκαδική, οκταδική, κλπ).
//
// Υποστηρίζουν εντοπιότητες (locale), έλεγχο για λανθασμένη βάση και άλλα, τα οποία
// δεν τα χρησιμοποιώ εδώ.
//
// Για περισσότερες λεπτομέρειες διαβάστε την επίσημη τεκμηρίωσή τους στον compiler σας
// (εναλλακτικά: http://l...content-available-to-author-only...e.net/man/3/strtol )
//
void print_conv2advanced( int ntokens, char *tokens[] )
{
extern int errno; // in <errno.h>
double tod; // για αποθήκευση σε double
long int tol; // για αποθήκευση σε long
unsigned long int toul; // για αποθήκευση σε unsigned long
char *ptail; // για έλεγχο περιττών χαρακτήρων
const int base = 10; // αριθμητική βάση για την μετατροπή
register int i; // για να διατρέξουμε τον tokens[]
char errmsg[MAXLINE] = ""; // βοηθητικό string για σφάλματα
for ( i=0; i < ntokens; i++ ) // όσο υπάρχουν tokens
{
*errmsg = '\0'; // εκκαθάριση του errmsg
// μετατροπή σε double
errno = 0; // εκκαθάριση του errno
tod
= strtod( tokens
[i
], &ptail
); if ( *ptail != '\0' || errno == ERANGE) { // έλεγχος αποτυχίας
if ( tod == 0 )
strncpy(errmsg
, "*** double failed ", MAXLINE
); else if (errno == ERANGE)
strncpy(errmsg
, "+++ double overflowed ", MAXLINE
); else
strncpy(errmsg
, "--- double fixed ", MAXLINE
); }
// μετατροπή σε long int
errno = 0; // εκκαθάριση του errno
tol
= strtol( tokens
[i
], &ptail
, base
); if ( *ptail != '\0' || errno == ERANGE) { // έλεγχος αποτυχίας
if (tol == 0)
strncat(errmsg
, "*** long failed ", MAXLINE
-1); else if (errno == ERANGE)
strncpy(errmsg
, "+++ long overflowed ", MAXLINE
); else
strncat(errmsg
, "--- long fixed ", MAXLINE
-1); }
// μετατροπή σε unsigned long
errno = 0; // εκκαθάριση του errno
toul
= strtoul(tokens
[i
], &ptail
, base
); if ( *ptail != '\0' || errno == ERANGE) { // έλεγχος αποτυχίας
if (toul == 0)
strncat(errmsg
, "*** unsigned long failed", MAXLINE
-1); else if (errno == ERANGE)
strncpy(errmsg
, "+++ unsigned overflowed ", MAXLINE
); else
strncat(errmsg
, "--- unsigned long fixed", MAXLINE
-1); }
// τύπωμα αποτελεσμάτων
printf("Token #%d: \"%s\"\n", i
+1, tokens
[i
]); // τύπωμα αρχικού token // τύπωμα των μετατροπών
printf( "as double: %g, as long: %ld, as unsigned long: %lu\n", tod, tol, toul
);
// τύπωμα του ptail
printf("%s\n(ptail = \"%s\")\n\n", errmsg
, ptail
); }
return;
}
// -----------------------------------------------------------------------------------
int main( void )
{
char linebuf[ MAXLINE ]; // για το διάβασμα της γραμμής ειδόδου
char *stokens[ MAXTOKENS ]; // για την αποθήκευση των tokens
int ntokens = 0; // το πλήθος των διαβασμένων tokens
register int i; // βοηθητικός μετρητής
// διάβασμα ολόκληρης της γραμμής εισόδου
printf("Enter up to %d words (tokens): ", MAXTOKENS
); s_get( linebuf, MAXLINE);
// διάσπαση σε έως MAXTOKENS λέξεις (διαχωριστικοί χαρακτήρες: space & tabs)
ntokens = s_tokenize( linebuf, stokens, MAXTOKENS, " \t");
// τύπωμα των λέξεων στις οποίες διασπάστηκε η γραμμή
printf("\n%d typed token(s):\n", ntokens
); for (i=0; i < ntokens; i++)
printf("\t%s\n", stokens
[i
] );
/*
* ΕΝΕΡΓΟΠΟΙΗΣΤΕ τη συνάρτηση που ακολουθεί για απλή μετατροπή των λέξεων
* σε αριθμούς (δηλαδή χωρίς έλεγχο κι ενημέρωση σε περίπτωση αποτυχίας)
*/
// απλή μετατροπή και τύπωμα των αποτελεσμάτων στην οθόνη
// print_conv1simple( ntokens, stokens ); // απλή μετατροπή
/*
* Εναλλακτικά, ΕΝΕΡΓΟΠΟΙΗΣΤΕ τη συνάρτηση που ακολουθεί για προχωρημένη
* μετατροπή των λέξεων σε αριθμούς (δηλαδή, με έλεγχο κι ενημέρωση σε
* περίπτωση αποτυχίας).
*/
// προχωρημένη μετατροπή και τύπωμά των αποτελεσμάτων στην οθόνη
// print_conv2advanced( ntokens, stokens ); // προχωρημένη μετατροπή
}