#include #include #include #include #include #ifndef DEBUG #define DEBUG false #endif #ifndef TO_UNITS_ON_THE_END #define TO_UNITS_ON_THE_END false #endif #ifndef FROM_UNITS_ON_THE_END #define FROM_UNITS_ON_THE_END false #endif #ifndef TO_FIRST_NUMBER_VOID #define TO_FIRST_NUMBER_VOID false #endif #ifndef FROM_FIRST_NUMBER_VOID #define FROM_FIRST_NUMBER_VOID false #endif #ifndef TO_INFINITE_BASE #define TO_INFINITE_BASE false #endif #ifndef FROM_INFINITE_BASE #define FROM_INFINITE_BASE false #endif typedef struct NumeralPtr { char const* symbol; struct NumeralPtr *next; struct NumeralPtr *previous; } numeral_ptr; char* program_name = NULL; /* * Creates new digit for numeral_ptr * Return pointer to new numeral_ptr * Returns NULL in case of no memory */ numeral_ptr* new_digit(numeral_ptr* last_numeral, char const* to_first) { numeral_ptr* starting_point = malloc(sizeof(numeral_ptr)); if(starting_point == NULL) { fprintf(stderr, "error: %s: %s!", program_name, strerror(ENOMEM)); return NULL; } starting_point->symbol = to_first; starting_point->previous = last_numeral; starting_point->next = NULL; return starting_point; } numeral_ptr* numeral_infinity(char const* to_first, size_t cases) { numeral_ptr* starting_case = new_digit(NULL, to_first); numeral_ptr* other_case = starting_case; for(size_t i = 2; i <= cases; ++i) { other_case->next = new_digit(other_case, to_first); other_case = other_case->next; } return starting_case; } void increment(numeral_ptr* numeral, char* num_first, char* num_last) { bool cycled = false; if( numeral->symbol == num_last ) { if( numeral->next == NULL ) numeral->next = new_digit(numeral, num_first); else increment(numeral->next, num_first, num_last); cycled = true; } if( cycled ) numeral->symbol = num_first; else ++(numeral->symbol); } void decrement_number_string(char* number, char* first_number, char* last_number, char* numeral_system) { while( *number == *first_number ) { *number = *last_number; ++number; } if( *number == '\0' ) { *(--number) = '\0'; } else { while( !(*numeral_system == *number) ) ++numeral_system; *number = *(--numeral_system); } } bool is_the_same(numeral_ptr* numeral, char* number_arg) { while( !(numeral == NULL) ) { if( *(numeral->symbol) == *(number_arg) ) { numeral = numeral->next; ++(number_arg); continue; } return false; } return (*number_arg == '\0') ? true : false; } void print_numeral(numeral_ptr* numeral) { if( TO_UNITS_ON_THE_END ) { while( !(numeral->next == NULL) ) numeral = numeral->next; while( !(numeral == NULL) ) { printf("%c", *(numeral->symbol)); numeral = numeral->previous; } } else { while( !(numeral == NULL) ) { printf("%c", *(numeral->symbol)); numeral = numeral->next; } } printf("\n"); } void reverse_string(char* string) { char tmp; char* string_end = string + strlen(string); while ( --string_end > string ) { tmp = *string; *string++ = *string_end; *string_end = tmp; } } int main(int argc, char* argv[]) { program_name = argv[0]; /* argument processing */ if( !(argc == 2) ) { fprintf(stderr, "usage: %s \n", program_name); exit(EXIT_FAILURE); } /* Numeral System variables from MACROS */ char* from = malloc( (strlen(FROM_NUMERICALS) + 1) * sizeof(char) ); char* to = malloc( (strlen(TO_NUMERICALS) + 1) * sizeof(char) ); strcpy(from, FROM_NUMERICALS); strcpy(to, TO_NUMERICALS); /* Number variables to be converted */ char* number = argv[1]; /* _first and _last variables */ char* from_first = from; char* from_last = from + (strlen(from) - 1); char* to_first = to; char* to_last = to + (strlen(to) - 1); if( FROM_UNITS_ON_THE_END ) { reverse_string(number); } /* initializing counting and result */ numeral_ptr* counting = NULL; numeral_ptr* result = NULL; if( FROM_INFINITE_BASE ) counting = numeral_infinity(from_first, strlen(number)); else counting = numeral_infinity(from_first, 1); result = numeral_infinity(to_first, 1); /* first number void */ if( !(FROM_FIRST_NUMBER_VOID && TO_FIRST_NUMBER_VOID) ) { if( FROM_FIRST_NUMBER_VOID ) { if( strlen(number) == 1 && *number == *from_first ) { fprintf(stderr, "error: unrepresentable void number\n"); exit(EXIT_FAILURE); } decrement_number_string(number, from_first, from_last, from_first); } if( TO_FIRST_NUMBER_VOID ) increment(result, to_first, to_last); } /* increments until it finishes */ while( !is_the_same(counting, number) ) { if(DEBUG) { puts("----"); print_numeral(result); } increment(result, to_first, to_last); if(DEBUG) print_numeral(counting); increment(counting, from_first, from_last); } if(DEBUG) puts("----"); /* print */ if(DEBUG) { printf("counting: "); print_numeral(counting); printf("result: "); } print_numeral(result); return EXIT_SUCCESS; }