Advertisement
Guest User

Untitled

a guest
Oct 21st, 2019
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.33 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include <inttypes.h>
  6.  
  7. #define SUCCESS 0
  8. #define ZERO_DIVISION 1
  9. #define TOO_BIG_POW 2
  10. #define TOO_LONG_DIAL 3
  11. #define RESULT_POW_IS_OUT_OF_RANGE 4
  12. #define INCORRECT_SYMBOL 5
  13. #define EMPTY_INPUT 6
  14. #define MISTAKE 7
  15.  
  16. #define MAX_DIAL_LEN 40
  17. #define AMOUNT_OF_INPUT_DIALS 2
  18. #define MANTISSA_MAX 32
  19. #define CORRECT_MANTISSA_LENGTH 30
  20.  
  21. #define YES 1
  22. #define NO 0
  23. #define MINUS 1
  24. #define PLUS 0
  25. #define TOTAL_AMOUNT_OF_DIALS 3
  26.  
  27. typedef char two_input_dials[AMOUNT_OF_INPUT_DIALS][MAX_DIAL_LEN + 1];
  28. typedef char dial[MANTISSA_MAX];
  29. typedef struct
  30. {
  31.     dial double_dial;
  32.     int double_pow;
  33.     int double_dial_sign;
  34. } long_dial;
  35. typedef long_dial all_dials[TOTAL_AMOUNT_OF_DIALS];
  36.  
  37.  
  38. int read_dial(char *str, int max_len);
  39. int is_digit(char c);
  40. int is_right_format(char *str, int is_double);
  41. int long_dial_parsing(char *str, long_dial *data);
  42. int are_able_to_divide(char *mant1, char *mant2);
  43. int preparing_for_substraction(char *mant1, char *mant2);
  44. void increase_dial_mantissa(long_dial *var, int k);
  45. int substraction_imitating_division(long_dial *a, long_dial b);
  46. int is_zero(char *var);
  47. int long_arithmetics(long_dial a, long_dial b, long_dial *result);
  48. void delete_excess_zeroes(char *str);
  49. void print_correct_dial(long_dial var);
  50. void print_result(long_dial *data);
  51. void kind_of_mistake(int is_wrong);
  52. void info();
  53.  
  54. int main(void)
  55. {
  56.     two_input_dials input_dials;
  57.     all_dials long_dials;
  58.     info();
  59.     int is_wrong = SUCCESS;
  60.     printf("Enter the first dial (integer)\n\
  61. |---------|---------|---------|<-30 symbols\n");
  62.     is_wrong = read_dial(input_dials[0], MAX_DIAL_LEN);
  63.     if (is_wrong)
  64.     {
  65.         kind_of_mistake(is_wrong);
  66.         return is_wrong;
  67.     }
  68.     if ((is_wrong = is_right_format(input_dials[0], NO)) != SUCCESS)
  69.     {
  70.         kind_of_mistake(is_wrong);
  71.         return is_wrong;
  72.     }
  73.  
  74.     printf("\nEnter the second dial: (double)\n\
  75.         |<-10     |<-20     |<-30 |<-pow_border\n\
  76. |--------|---------|---------|e----|\n");
  77.     is_wrong = read_dial(input_dials[1], MAX_DIAL_LEN);
  78.     if (is_wrong)
  79.     {
  80.         kind_of_mistake(is_wrong);
  81.         return is_wrong;
  82.     }
  83.     if ((is_wrong = is_right_format(input_dials[1], YES)) != SUCCESS)
  84.     {
  85.         kind_of_mistake(is_wrong);
  86.         return is_wrong;
  87.     }
  88.     for (int i = 0; i != 2; i++)
  89.         long_dial_parsing(input_dials[i], &long_dials[i]);
  90.  
  91.     is_wrong = long_arithmetics(long_dials[0], long_dials[1], &long_dials[2]);
  92.     if (is_wrong)
  93.     {
  94.         if (abs(long_dials[2].double_pow) > 99999)
  95.         {
  96.             kind_of_mistake(RESULT_POW_IS_OUT_OF_RANGE);
  97.             return RESULT_POW_IS_OUT_OF_RANGE;
  98.         }
  99.         kind_of_mistake(ZERO_DIVISION);
  100.         return ZERO_DIVISION;
  101.     }
  102.     print_result(long_dials);
  103.     return SUCCESS;
  104. }
  105.  
  106. int read_dial(char *dial, int max_len)
  107. {
  108.     char cur_symbol;
  109.     int cur_pos = 0, first_is_zero = 0;
  110.     cur_symbol = getchar();
  111.     while (cur_symbol == '0')
  112.     {
  113.         first_is_zero = 1;
  114.         cur_symbol = getchar();
  115.     }
  116.     if ((cur_symbol == '\n' || cur_symbol == '\0') && first_is_zero)
  117.     {
  118.         strcpy(dial, "0");
  119.         return SUCCESS;
  120.     }
  121.     while (cur_pos != max_len && cur_symbol != '\n' && cur_symbol != '\0')
  122.     {
  123.         dial[cur_pos] = cur_symbol;
  124.         cur_pos += 1;
  125.         cur_symbol = getchar();
  126.     }
  127.     dial[cur_pos] = '\0';
  128.     if (cur_pos == max_len)
  129.     {
  130.         cur_symbol = getchar();
  131.         while (cur_symbol != '\n' && cur_symbol != '\0')
  132.             cur_symbol = getchar();
  133.         return TOO_LONG_DIAL;
  134.     }
  135.     return SUCCESS;
  136. }
  137. void print_result(long_dial *data)
  138. {
  139.     printf("The result is ");
  140.     print_correct_dial(data[2]);
  141.     printf(";\n");
  142. }
  143. void print_correct_dial(long_dial dial)
  144. {
  145.     if (dial.double_dial_sign == MINUS)
  146.         printf("-");
  147.     delete_excess_zeroes(dial.double_dial);
  148.     printf("0.%s", &dial.double_dial[1]);
  149.     if (dial.double_pow != 0)
  150.         printf("e%d", dial.double_pow);
  151. }
  152. int long_dial_parsing(char *input_str, long_dial *data)
  153. {
  154.     int i = 0, j = 0, aux = 0, dots = 0;
  155.     data->double_pow = 0;
  156.     data->double_dial_sign = (input_str[i] == '-') ? MINUS : PLUS;
  157.     if (input_str[i] == '+' || input_str[i] == '-')
  158.     {
  159.         i++;
  160.     }
  161.     else if (input_str[i] == 'e' && strlen(input_str) == 1)
  162.     {
  163.         strcpy(input_str, ".1");
  164.         aux = 1;
  165.     }
  166.     while ((is_digit(input_str[i]) || input_str[i] == '.') && j != MANTISSA_MAX - 1)
  167.     {
  168.         if (input_str[i] == '.')
  169.         {
  170.             dots = 1;
  171.         }
  172.         data->double_dial[j++] = input_str[i++];
  173.     }
  174.     if (!dots)
  175.         data->double_dial[j++] = '.';
  176.     while (j != MANTISSA_MAX - 1)
  177.         data->double_dial[j++] = '0';
  178.     data->double_dial[j] = '\0';
  179.  
  180.     int sign = 1;
  181.     if (input_str[i] == 'e')
  182.         i++;
  183.     if (input_str[i] == '-')
  184.     {
  185.         sign = -1;
  186.         i++;
  187.     }
  188.     else if (input_str[i] == '+')
  189.         i++;
  190.     while (input_str[i])
  191.     {
  192.         data->double_pow = data->double_pow * 10 + (int)(input_str[i] - '0');
  193.         i++;
  194.     }
  195.     data->double_pow += aux;
  196.     data->double_pow *= sign;
  197.     int up_to_dot = 0;
  198.     while (data->double_dial[up_to_dot] != '.')
  199.             up_to_dot++;
  200.     data->double_pow += up_to_dot;
  201.     while (up_to_dot > 0)
  202.     {
  203.         data->double_dial[up_to_dot] = data->double_dial[up_to_dot - 1];
  204.         up_to_dot--;
  205.     }
  206.     data->double_dial[up_to_dot] = '0';
  207.     if (!is_zero(data->double_dial) && data->double_dial[1] == '0')
  208.     {
  209.         for (i = 1; data->double_dial[i] == '0' && data->double_dial[i];)
  210.             i++;
  211.         increase_dial_mantissa(data, i - 1);
  212.         data->double_pow -= i - 1;
  213.     }
  214.     return SUCCESS;
  215. }
  216. int is_right_format(char *str, int is_double)
  217. {
  218.     int flag = 1, dot = 0, is_there_a_sign = 0, e_counter = 0;
  219.     int i;
  220.     for (i = 0; str[i]; i++)
  221.     {
  222.         switch (flag)
  223.         {
  224.             case 1:
  225.                 if (str[i] == '+' || str[i] == '-' || is_digit(str[i]))
  226.                 {
  227.                     if (!is_digit(str[i]))
  228.                         is_there_a_sign = 1;
  229.                     flag = 2;
  230.                 }
  231.                 else if (str[i] == '.')
  232.                 {
  233.                     if (is_double == NO)
  234.                             return INCORRECT_SYMBOL;
  235.                     flag = 3;
  236.                 }
  237.                 else if (str[i] == 'e')
  238.                 {
  239.                     if (is_double == NO)
  240.                             return INCORRECT_SYMBOL;
  241.                     flag = 5;
  242.                 }
  243.                 else
  244.                     return INCORRECT_SYMBOL;
  245.                 break;
  246.  
  247.             case 2:
  248.                 if (i >= is_there_a_sign + CORRECT_MANTISSA_LENGTH && str[i] != 'e' && str[i] != '.')
  249.                 {
  250.                     if (is_double == NO)
  251.                         return TOO_LONG_DIAL;
  252.                     return INCORRECT_SYMBOL;
  253.                 }
  254.                 if (str[i] == 'e')
  255.                 {
  256.                     if (is_double == NO)
  257.                         return INCORRECT_SYMBOL;
  258.                     flag = 5;
  259.                 }
  260.                 else if (str[i] == '.')
  261.                 {
  262.                     if (is_double == NO)
  263.                         return INCORRECT_SYMBOL;
  264.                     flag = 3;
  265.                 }
  266.                 else if (!is_digit(str[i]))
  267.                     return INCORRECT_SYMBOL;
  268.                 break;
  269.  
  270.             case 3:
  271.                 dot = 1;
  272.                 if (!is_digit(str[i]))
  273.                     return INCORRECT_SYMBOL;
  274.                 if (!is_digit(str[i]) && str[i] != 'e')
  275.                     return INCORRECT_SYMBOL;
  276.                 flag = 4;
  277.                 break;
  278.  
  279.             case 4:
  280.                 if (i >= is_there_a_sign + dot + CORRECT_MANTISSA_LENGTH && str[i] != 'e' && str[i] != '.')
  281.                 {
  282.                     if (is_double == NO)
  283.                         return RESULT_POW_IS_OUT_OF_RANGE;
  284.                     return INCORRECT_SYMBOL;
  285.                 }
  286.                 if (str[i] == 'e')
  287.                 {
  288.                     if (is_double == NO)
  289.                         return INCORRECT_SYMBOL;
  290.                     flag = 5;
  291.                 }
  292.                 else if (!is_digit(str[i]))
  293.                     return INCORRECT_SYMBOL;
  294.                 break;
  295.  
  296.             case 5:
  297.                 e_counter = is_digit(str[i]);
  298.                 if (str[i] == '+' || str[i] == '-' || e_counter)
  299.                 {
  300.                     if (is_double == NO)
  301.                         return INCORRECT_SYMBOL;
  302.                     flag = 6;
  303.                 }
  304.                 else
  305.                     return INCORRECT_SYMBOL;
  306.                 break;
  307.  
  308.             case 6:
  309.                 if (!is_digit(str[i]))
  310.                     return INCORRECT_SYMBOL;
  311.                 else
  312.                     e_counter++;
  313.                 if (e_counter >= 6)
  314.                     return TOO_BIG_POW;
  315.                 break;
  316.             default:
  317.                 break;
  318.         }
  319.     }
  320.     return (i == 0) ? EMPTY_INPUT : SUCCESS;
  321. }
  322. int is_digit(char c)
  323. {
  324.     return (c - '0' >= 0 && c - '9' <= 0) ? YES : NO;
  325. }
  326. int is_zero(char *dial)
  327. {
  328.     int i;
  329.     for (i = 0; dial[i] == '0'; i++);
  330.     return (!dial[i]) ? YES : NO;
  331. }
  332. int long_arithmetics(long_dial up, long_dial down, long_dial *result)
  333. {
  334.     up.double_dial[0] = '0', down.double_dial[0] = '0';
  335.     if (is_zero(down.double_dial)) //если знаменатель равен нулю
  336.     {
  337.         result->double_pow = 1;
  338.         return ZERO_DIVISION;
  339.     }
  340.     if (is_zero(up.double_dial)) //если числитель равен нулю
  341.     {
  342.         strcpy(result->double_dial, "00\0");
  343.         result->double_pow = 1;
  344.         return SUCCESS;
  345.     }
  346.     if (abs(up.double_dial_sign - down.double_dial_sign) > 99999) //проверяем итоговую степень
  347.         return RESULT_POW_IS_OUT_OF_RANGE;
  348.  
  349.     int division_result = 0;
  350.     if (!are_able_to_divide(up.double_dial, down.double_dial)) //сдвигаем вправо на разряд, если мантисса знаменателя меньше числителя
  351.     {
  352.         up.double_pow -= 1;
  353.         increase_dial_mantissa(&up, 1);
  354.     }
  355.     result->double_dial[0] = '0';
  356.  
  357.     division_result = substraction_imitating_division(&up, down);//результат деления
  358.     result->double_dial[1] = division_result + '0';
  359.  
  360.     int i;
  361.     for (i = 2; i != CORRECT_MANTISSA_LENGTH + 1; i++)
  362.     {
  363.         if (is_zero(up.double_dial))
  364.         {
  365.             result->double_dial[i] = '\0';
  366.             division_result = 0;
  367.             break;
  368.         }
  369.         if (!are_able_to_divide(up.double_dial, down.double_dial))
  370.         {
  371.             increase_dial_mantissa(&up, 1);
  372.             result->double_dial[i] = '0';
  373.         }
  374.         else
  375.         {
  376.             division_result = substraction_imitating_division(&up, down);
  377.             result->double_dial[i] = '0' + division_result;
  378.         }
  379.     }
  380.     result->double_dial[CORRECT_MANTISSA_LENGTH + 1] = '\0';
  381.     if (i == CORRECT_MANTISSA_LENGTH + 1 && (division_result = substraction_imitating_division(&up, down)) >= 5) //округление последней цифры в большую сторону, если период
  382.         result->double_dial[CORRECT_MANTISSA_LENGTH] += 1;
  383.  
  384.     for (; i != CORRECT_MANTISSA_LENGTH + 1; i++) //заполняем нулями оставшиеся позиции числа
  385.         result->double_dial[i] = '0';
  386.     result->double_dial[CORRECT_MANTISSA_LENGTH + 1] = '\0';
  387.  
  388.     int to_add = 0;
  389.     for (i = CORRECT_MANTISSA_LENGTH; i >= 0; i--) //проверяем корректность чисел в ячейках. Цtлую часть переносим в ячейку спереди, в текущей оставляем остаток
  390.     {
  391.         result->double_dial[i] += to_add;
  392.         if (result->double_dial[i] == '0' + 10)
  393.         {
  394.             result->double_dial[i] = '0';
  395.             to_add = 1;
  396.         }
  397.         else
  398.             break;
  399.     }
  400.     if (result->double_dial[0] == '1')
  401.     {
  402.         for (i = CORRECT_MANTISSA_LENGTH; i != 0; i--)
  403.             result->double_dial[i] = result->double_dial[i - 1];
  404.         result->double_dial[0] = '0';
  405.     }
  406.     else
  407.         to_add = 0;
  408.     result->double_dial[MANTISSA_MAX - 1] = '\0';
  409.     result->double_dial_sign = MINUS * (up.double_dial_sign != down.double_dial_sign);
  410.     result->double_pow = up.double_pow - down.double_pow + 1 + to_add;
  411.     if (abs(result->double_pow) > 99999)
  412.         return RESULT_POW_IS_OUT_OF_RANGE;
  413.     return SUCCESS;
  414. }
  415. void increase_dial_mantissa(long_dial *dial, int move_for)
  416. {
  417.     for (int i = MANTISSA_MAX - 1 - move_for; i != MANTISSA_MAX - 1; i++)
  418.         dial->double_dial[i] = '0';
  419.     for (int i = 0; i != MANTISSA_MAX - 1 - move_for; i++)
  420.         dial->double_dial[i] = dial->double_dial[i + move_for];
  421. }
  422. int are_able_to_divide(char *first_mantissa, char *second_mantissa)
  423. {
  424.     int digit_difference;
  425.     for (int i = 0; first_mantissa[i]; i++)
  426.     {
  427.         digit_difference = first_mantissa[i] - second_mantissa[i];
  428.         if (digit_difference > 0)
  429.             return YES;
  430.         else if (digit_difference < 0)
  431.             return NO;
  432.     }
  433.     return YES;
  434. }
  435. int preparing_for_substraction(char *first_mantissa, char *second_mantissa)
  436. {
  437.     if (!are_able_to_divide(first_mantissa, second_mantissa))
  438.         return NO;
  439.     for (int i = strlen(second_mantissa) - 1; i >= 0; i--)
  440.     {
  441.         if (first_mantissa[i] - second_mantissa[i] >= 0)
  442.             first_mantissa[i] -= (second_mantissa[i] - '0');
  443.         else
  444.         {
  445.             int index_to_borrow_from = i - 1;
  446.             while (first_mantissa[index_to_borrow_from] - '0' == 0)
  447.                 index_to_borrow_from--;
  448.             first_mantissa[index_to_borrow_from]--;
  449.             index_to_borrow_from++;
  450.             for (; index_to_borrow_from != i; index_to_borrow_from++)
  451.                 first_mantissa[index_to_borrow_from] += 9;
  452.             first_mantissa[i] += 10 - (second_mantissa[i] - '0');
  453.         }
  454.     }
  455.     return YES;
  456. }
  457. int substraction_imitating_division(long_dial *first_mantissa, long_dial second_mantissa)
  458. {
  459.     int amount_of_second_mantissa_in_first = 0;
  460.     while (preparing_for_substraction(first_mantissa->double_dial, second_mantissa.double_dial))
  461.         amount_of_second_mantissa_in_first++;
  462.     increase_dial_mantissa(first_mantissa, 1);
  463.     return amount_of_second_mantissa_in_first;
  464. }
  465. void delete_excess_zeroes(char *dial)
  466. {
  467.     int dial_length = strlen(dial), i;
  468.     for (i = dial_length - 1; dial[i] == '0' && i != 1; i--);
  469.     dial[i + 1] = '\0';
  470. }
  471. void kind_of_mistake(int is_wrong)
  472. {
  473.     switch (is_wrong)
  474.     {
  475.         case ZERO_DIVISION:
  476.             printf("Division on zero\n");
  477.             break;
  478.         case TOO_BIG_POW:
  479.             printf("Pow is out of allowed borders (from -99999 to 99999)\n");
  480.             break;
  481.         case TOO_LONG_DIAL:
  482.             printf("Too long dial\n");
  483.             break;
  484.         case RESULT_POW_IS_OUT_OF_RANGE:
  485.             printf("Result pow is out of range\n");
  486.             break;
  487.         case INCORRECT_SYMBOL:
  488.             printf("Incorrect symbol was found\n");
  489.             break;
  490.         case EMPTY_INPUT:
  491.             printf("Empty input\n");
  492.         default:
  493.             break;
  494.     }
  495. }
  496. void info()
  497. {
  498.     printf("Instruction\n\
  499.            1 - It isn't necessary to enter a sign for positive dials\n\
  500.            2 - The first dial should be integer. It can contain only up to 30 digits and a sign\n\
  501.            3 - The second dial should be double. It can contain a sign, up 30 digits (without a one dot), and e-showed power (up to 5 digits)\n\
  502.                for a positive power a sign is not required\n\
  503.            4 - e must be lowercase only\n\
  504.            5 - The result is a dial which was made by division of integer dial on double\n\
  505.            6 - The result's format is\n\
  506.                    0.mepow, where\n\
  507.                m is a mantissa up to 30 digits long, pow - power of a dial (up to 5 digits long)\n\
  508.            Examples of correct double input\n\
  509.                0.121\n\
  510.                .121\n\
  511.                2.\n\
  512.                1e15\n\
  513.                2e-56\n\n\n");
  514. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement