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