training

Code I wrote during training
git clone git://git.bitsmanent.org/training
Log | Files | Refs | README

metrics3.c (3330B)


      1 /* Exercise 8.40 */
      2 
      3 #include <stdio.h>
      4 #include <string.h>
      5 #include <ctype.h>
      6 #include <stdlib.h>
      7 
      8 #define TYPES 24
      9 #define SIZE 254
     10 
     11 char *getkey(char *s, char units[][TYPES][11], int *idx);
     12 
     13 int main(void)
     14 {
     15    int idx, wordm = 0, loop = 0;
     16    char class, *tokp, string[SIZE], word[12];
     17    double tot, divs;
     18 
     19    char units[3][TYPES][11] = {
     20       { /* The labels */
     21 	"millimetr", "centimetr", "decimetr", "metr", "kilometr",
     22 	"millilitr", "centilitr", "decilitr", "litr", "decalitr", "ettolitr",
     23         "milligramm", "gramm", "decagramm", "kilogramm", "tonnellat", "quintal",
     24         "gallon", "pollic", "pied", "libbr", "yard",
     25 
     26         /* Word meters */
     27         "quart", "dozzin" },
     28 
     29       { /* The values */
     30 	"1", "10", "100", "1000", "1000000",
     31 	"1", "10", "100", "1000", "10000", "100000",
     32 	"1", "1000", "10000", "1000000", "10000000", "100000000",
     33 
     34 	/* 3.7853  "2.54" "30.48"  "0.4536"  "0.9144" */
     35 	"3785", "25.4", "304.8", "4.536", "914.4",
     36 
     37         /* Word meters */
     38 	"4", "12" },
     39 
     40       { /* The classes */
     41 	"A", "A", "A", "A", "A",
     42 	"B", "B", "B", "B", "B", "B",
     43 	"C", "C", "C", "C", "C", "C",
     44 	"B", "A", "A", "C", "A",
     45 
     46         /* Word meters: 0 divide, 1 multiply */
     47 	"0", "1" }
     48    };
     49 
     50    printf("Please, write your answer: ");
     51    gets(string);
     52 
     53    tokp = getkey(string, units, &idx);
     54    while(tokp != NULL) {
     55 
     56       /* Check for the "word meters": un quarto, una dozzina, etc. */
     57       if( !memcmp(tokp, "un", 2) )
     58 	 strcpy(word, "1");
     59       else
     60 	 strcpy(word, tokp);
     61 
     62       if( *units[2][idx] == '0' || *units[2][idx] == '1' ) {
     63 	 wordm = 1; /* Mark the "operation" as "Word meter" */
     64 	 strcat(word, " ");
     65 
     66 	 if( (tokp = getkey(NULL, units, &idx)) != NULL )
     67 	    strcat(word, tokp);
     68 	 else
     69 	    break;
     70       }
     71 
     72       switch(++loop) {
     73 	 case 1:
     74 	    divs = atof(units[1][idx]);
     75 	    class = *units[2][idx];
     76 	    break;
     77 	 case 2:
     78 	    tot = atof(word);
     79 	    break;
     80 	 case 3:
     81 
     82             /* If there is a word meter.. */
     83 	    if(wordm) { /* Marked operation */
     84 	       if( !memcmp(word, "quart", 5) )
     85 		  tot *= atof(units[1][idx]) / 4;
     86 	       else
     87 		  tot *= atof(units[1][idx]) * 12;
     88 	    }
     89 	    else
     90 	       tot *= atof(units[1][idx]);
     91 
     92 	    if(class != *units[2][idx]) {
     93 	       printf("error: conflict in conversion types\n");
     94 	       return -1;
     95 	    }
     96 	    
     97 	    break;
     98 	 default:
     99 	    printf("unknown error: please fix this\n");
    100 	    break;
    101       }
    102 
    103       /* DeBuG
    104       printf("case[%d]===[ word: %s\n", loop, word);
    105       */
    106 
    107       tokp = getkey(NULL, units, &idx);
    108    }
    109 
    110    if(loop != 3)
    111       printf("Are you forgetting something? :-)\n");
    112    else
    113       printf("Results: %.2f\n", tot / divs);
    114 
    115    return 0;
    116 } /* E0F main */
    117 
    118 /* locate and tokenize the units[][][] elements */
    119 char *getkey(char *s, char units[][TYPES][11], int *idx)
    120 {
    121    int i;
    122    char *tokp;
    123    static char *prev_s;
    124 
    125    prev_s = s;
    126 
    127    tokp = strtok( s == NULL ? prev_s : s, " ");
    128    while(tokp != NULL) {
    129 
    130       for(i = 0; i < TYPES; i++) {
    131 	 if( ! memcmp(tokp, units[0][i], strlen(units[0][i])) ||
    132 	     isdigit((int)*tokp) || !memcmp(tokp, "un", 2) ) {
    133 
    134             /* Toggle the '?' at end of string */
    135 	    if( tokp[strlen(tokp) - 1] == '?' )
    136 	      tokp[strlen(tokp) - 1] = '\0';
    137 
    138             if(idx != NULL) *idx = i;
    139 	    return tokp;
    140 	 }
    141       }
    142 
    143       tokp = strtok(NULL, " ");
    144    }
    145 
    146    return NULL;
    147 } /* eof getkey() */
    148