Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <inttypes.h>
- #define SUCCESS 0
- #define ZERO_DIVISION 1
- #define TOO_BIG_POW 2
- #define TOO_LONG_DIAL 3
- #define RESULT_POW_IS_OUT_OF_RANGE 4
- #define INCORRECT_SYMBOL 5
- #define EMPTY_INPUT 6
- #define MISTAKE 7
- #define MAX_DIAL_LEN 40
- #define AMOUNT_OF_INPUT_DIALS 2
- #define MANTISSA_MAX 32
- #define CORRECT_MANTISSA_LENGTH 30
- #define YES 1
- #define NO 0
- #define MINUS 1
- #define PLUS 0
- #define TOTAL_AMOUNT_OF_DIALS 3
- typedef char two_input_dials[AMOUNT_OF_INPUT_DIALS][MAX_DIAL_LEN + 1];
- typedef char dial[MANTISSA_MAX];
- typedef struct
- {
- dial double_dial;
- int double_pow;
- int double_dial_sign;
- } long_dial;
- typedef long_dial all_dials[TOTAL_AMOUNT_OF_DIALS];
- int read_dial(char *str, int max_len);
- int is_digit(char c);
- int is_right_format(char *str, int is_double);
- int long_dial_parsing(char *str, long_dial *data);
- int are_able_to_divide(char *mant1, char *mant2);
- int preparing_for_substraction(char *mant1, char *mant2);
- void increase_dial_mantissa(long_dial *var, int k);
- int substraction_imitating_division(long_dial *a, long_dial b);
- int is_zero(char *var);
- int long_arithmetics(long_dial a, long_dial b, long_dial *result);
- void delete_excess_zeroes(char *str);
- void print_correct_dial(long_dial var);
- void print_result(long_dial *data);
- void kind_of_mistake(int is_wrong);
- void info();
- int main(void)
- {
- two_input_dials input_dials;
- all_dials long_dials;
- info();
- int is_wrong = SUCCESS;
- printf("Enter the first dial (integer)\n\
- |---------|---------|---------|<-30 symbols\n");
- is_wrong = read_dial(input_dials[0], MAX_DIAL_LEN);
- if (is_wrong)
- {
- kind_of_mistake(is_wrong);
- return is_wrong;
- }
- if ((is_wrong = is_right_format(input_dials[0], NO)) != SUCCESS)
- {
- kind_of_mistake(is_wrong);
- return is_wrong;
- }
- printf("\nEnter the second dial: (double)\n\
- |<-10 |<-20 |<-30 |<-pow_border\n\
- |--------|---------|---------|e----|\n");
- is_wrong = read_dial(input_dials[1], MAX_DIAL_LEN);
- if (is_wrong)
- {
- kind_of_mistake(is_wrong);
- return is_wrong;
- }
- if ((is_wrong = is_right_format(input_dials[1], YES)) != SUCCESS)
- {
- kind_of_mistake(is_wrong);
- return is_wrong;
- }
- for (int i = 0; i != 2; i++)
- long_dial_parsing(input_dials[i], &long_dials[i]);
- is_wrong = long_arithmetics(long_dials[0], long_dials[1], &long_dials[2]);
- if (is_wrong)
- {
- if (abs(long_dials[2].double_pow) > 99999)
- {
- kind_of_mistake(RESULT_POW_IS_OUT_OF_RANGE);
- return RESULT_POW_IS_OUT_OF_RANGE;
- }
- kind_of_mistake(ZERO_DIVISION);
- return ZERO_DIVISION;
- }
- print_result(long_dials);
- return SUCCESS;
- }
- int read_dial(char *dial, int max_len)
- {
- char cur_symbol;
- int cur_pos = 0, first_is_zero = 0;
- cur_symbol = getchar();
- while (cur_symbol == '0')
- {
- first_is_zero = 1;
- cur_symbol = getchar();
- }
- if ((cur_symbol == '\n' || cur_symbol == '\0') && first_is_zero)
- {
- strcpy(dial, "0");
- return SUCCESS;
- }
- while (cur_pos != max_len && cur_symbol != '\n' && cur_symbol != '\0')
- {
- dial[cur_pos] = cur_symbol;
- cur_pos += 1;
- cur_symbol = getchar();
- }
- dial[cur_pos] = '\0';
- if (cur_pos == max_len)
- {
- cur_symbol = getchar();
- while (cur_symbol != '\n' && cur_symbol != '\0')
- cur_symbol = getchar();
- return TOO_LONG_DIAL;
- }
- return SUCCESS;
- }
- void print_result(long_dial *data)
- {
- printf("The result is ");
- print_correct_dial(data[2]);
- printf(";\n");
- }
- void print_correct_dial(long_dial dial)
- {
- if (dial.double_dial_sign == MINUS)
- printf("-");
- delete_excess_zeroes(dial.double_dial);
- printf("0.%s", &dial.double_dial[1]);
- if (dial.double_pow != 0)
- printf("e%d", dial.double_pow);
- }
- int long_dial_parsing(char *input_str, long_dial *data)
- {
- int i = 0, j = 0, aux = 0, dots = 0;
- data->double_pow = 0;
- data->double_dial_sign = (input_str[i] == '-') ? MINUS : PLUS;
- if (input_str[i] == '+' || input_str[i] == '-')
- {
- i++;
- }
- else if (input_str[i] == 'e' && strlen(input_str) == 1)
- {
- strcpy(input_str, ".1");
- aux = 1;
- }
- while ((is_digit(input_str[i]) || input_str[i] == '.') && j != MANTISSA_MAX - 1)
- {
- if (input_str[i] == '.')
- {
- dots = 1;
- }
- data->double_dial[j++] = input_str[i++];
- }
- if (!dots)
- data->double_dial[j++] = '.';
- while (j != MANTISSA_MAX - 1)
- data->double_dial[j++] = '0';
- data->double_dial[j] = '\0';
- int sign = 1;
- if (input_str[i] == 'e')
- i++;
- if (input_str[i] == '-')
- {
- sign = -1;
- i++;
- }
- else if (input_str[i] == '+')
- i++;
- while (input_str[i])
- {
- data->double_pow = data->double_pow * 10 + (int)(input_str[i] - '0');
- i++;
- }
- data->double_pow += aux;
- data->double_pow *= sign;
- int up_to_dot = 0;
- while (data->double_dial[up_to_dot] != '.')
- up_to_dot++;
- data->double_pow += up_to_dot;
- while (up_to_dot > 0)
- {
- data->double_dial[up_to_dot] = data->double_dial[up_to_dot - 1];
- up_to_dot--;
- }
- data->double_dial[up_to_dot] = '0';
- if (!is_zero(data->double_dial) && data->double_dial[1] == '0')
- {
- for (i = 1; data->double_dial[i] == '0' && data->double_dial[i];)
- i++;
- increase_dial_mantissa(data, i - 1);
- data->double_pow -= i - 1;
- }
- return SUCCESS;
- }
- int is_right_format(char *str, int is_double)
- {
- int flag = 1, dot = 0, is_there_a_sign = 0, e_counter = 0;
- int i;
- for (i = 0; str[i]; i++)
- {
- switch (flag)
- {
- case 1:
- if (str[i] == '+' || str[i] == '-' || is_digit(str[i]))
- {
- if (!is_digit(str[i]))
- is_there_a_sign = 1;
- flag = 2;
- }
- else if (str[i] == '.')
- {
- if (is_double == NO)
- return INCORRECT_SYMBOL;
- flag = 3;
- }
- else if (str[i] == 'e')
- {
- if (is_double == NO)
- return INCORRECT_SYMBOL;
- flag = 5;
- }
- else
- return INCORRECT_SYMBOL;
- break;
- case 2:
- if (i >= is_there_a_sign + CORRECT_MANTISSA_LENGTH && str[i] != 'e' && str[i] != '.')
- {
- if (is_double == NO)
- return TOO_LONG_DIAL;
- return INCORRECT_SYMBOL;
- }
- if (str[i] == 'e')
- {
- if (is_double == NO)
- return INCORRECT_SYMBOL;
- flag = 5;
- }
- else if (str[i] == '.')
- {
- if (is_double == NO)
- return INCORRECT_SYMBOL;
- flag = 3;
- }
- else if (!is_digit(str[i]))
- return INCORRECT_SYMBOL;
- break;
- case 3:
- dot = 1;
- if (!is_digit(str[i]))
- return INCORRECT_SYMBOL;
- if (!is_digit(str[i]) && str[i] != 'e')
- return INCORRECT_SYMBOL;
- flag = 4;
- break;
- case 4:
- if (i >= is_there_a_sign + dot + CORRECT_MANTISSA_LENGTH && str[i] != 'e' && str[i] != '.')
- {
- if (is_double == NO)
- return RESULT_POW_IS_OUT_OF_RANGE;
- return INCORRECT_SYMBOL;
- }
- if (str[i] == 'e')
- {
- if (is_double == NO)
- return INCORRECT_SYMBOL;
- flag = 5;
- }
- else if (!is_digit(str[i]))
- return INCORRECT_SYMBOL;
- break;
- case 5:
- e_counter = is_digit(str[i]);
- if (str[i] == '+' || str[i] == '-' || e_counter)
- {
- if (is_double == NO)
- return INCORRECT_SYMBOL;
- flag = 6;
- }
- else
- return INCORRECT_SYMBOL;
- break;
- case 6:
- if (!is_digit(str[i]))
- return INCORRECT_SYMBOL;
- else
- e_counter++;
- if (e_counter >= 6)
- return TOO_BIG_POW;
- break;
- default:
- break;
- }
- }
- return (i == 0) ? EMPTY_INPUT : SUCCESS;
- }
- int is_digit(char c)
- {
- return (c - '0' >= 0 && c - '9' <= 0) ? YES : NO;
- }
- int is_zero(char *dial)
- {
- int i;
- for (i = 0; dial[i] == '0'; i++);
- return (!dial[i]) ? YES : NO;
- }
- int long_arithmetics(long_dial up, long_dial down, long_dial *result)
- {
- up.double_dial[0] = '0', down.double_dial[0] = '0';
- if (is_zero(down.double_dial)) //если знаменатель равен нулю
- {
- result->double_pow = 1;
- return ZERO_DIVISION;
- }
- if (is_zero(up.double_dial)) //если числитель равен нулю
- {
- strcpy(result->double_dial, "00\0");
- result->double_pow = 1;
- return SUCCESS;
- }
- if (abs(up.double_dial_sign - down.double_dial_sign) > 99999) //проверяем итоговую степень
- return RESULT_POW_IS_OUT_OF_RANGE;
- int division_result = 0;
- if (!are_able_to_divide(up.double_dial, down.double_dial)) //сдвигаем вправо на разряд, если мантисса знаменателя меньше числителя
- {
- up.double_pow -= 1;
- increase_dial_mantissa(&up, 1);
- }
- result->double_dial[0] = '0';
- division_result = substraction_imitating_division(&up, down);//результат деления
- result->double_dial[1] = division_result + '0';
- int i;
- for (i = 2; i != CORRECT_MANTISSA_LENGTH + 1; i++)
- {
- if (is_zero(up.double_dial))
- {
- result->double_dial[i] = '\0';
- division_result = 0;
- break;
- }
- if (!are_able_to_divide(up.double_dial, down.double_dial))
- {
- increase_dial_mantissa(&up, 1);
- result->double_dial[i] = '0';
- }
- else
- {
- division_result = substraction_imitating_division(&up, down);
- result->double_dial[i] = '0' + division_result;
- }
- }
- result->double_dial[CORRECT_MANTISSA_LENGTH + 1] = '\0';
- if (i == CORRECT_MANTISSA_LENGTH + 1 && (division_result = substraction_imitating_division(&up, down)) >= 5) //округление последней цифры в большую сторону, если период
- result->double_dial[CORRECT_MANTISSA_LENGTH] += 1;
- for (; i != CORRECT_MANTISSA_LENGTH + 1; i++) //заполняем нулями оставшиеся позиции числа
- result->double_dial[i] = '0';
- result->double_dial[CORRECT_MANTISSA_LENGTH + 1] = '\0';
- int to_add = 0;
- for (i = CORRECT_MANTISSA_LENGTH; i >= 0; i--) //проверяем корректность чисел в ячейках. Цtлую часть переносим в ячейку спереди, в текущей оставляем остаток
- {
- result->double_dial[i] += to_add;
- if (result->double_dial[i] == '0' + 10)
- {
- result->double_dial[i] = '0';
- to_add = 1;
- }
- else
- break;
- }
- if (result->double_dial[0] == '1')
- {
- for (i = CORRECT_MANTISSA_LENGTH; i != 0; i--)
- result->double_dial[i] = result->double_dial[i - 1];
- result->double_dial[0] = '0';
- }
- else
- to_add = 0;
- result->double_dial[MANTISSA_MAX - 1] = '\0';
- result->double_dial_sign = MINUS * (up.double_dial_sign != down.double_dial_sign);
- result->double_pow = up.double_pow - down.double_pow + 1 + to_add;
- if (abs(result->double_pow) > 99999)
- return RESULT_POW_IS_OUT_OF_RANGE;
- return SUCCESS;
- }
- void increase_dial_mantissa(long_dial *dial, int move_for)
- {
- for (int i = MANTISSA_MAX - 1 - move_for; i != MANTISSA_MAX - 1; i++)
- dial->double_dial[i] = '0';
- for (int i = 0; i != MANTISSA_MAX - 1 - move_for; i++)
- dial->double_dial[i] = dial->double_dial[i + move_for];
- }
- int are_able_to_divide(char *first_mantissa, char *second_mantissa)
- {
- int digit_difference;
- for (int i = 0; first_mantissa[i]; i++)
- {
- digit_difference = first_mantissa[i] - second_mantissa[i];
- if (digit_difference > 0)
- return YES;
- else if (digit_difference < 0)
- return NO;
- }
- return YES;
- }
- int preparing_for_substraction(char *first_mantissa, char *second_mantissa)
- {
- if (!are_able_to_divide(first_mantissa, second_mantissa))
- return NO;
- for (int i = strlen(second_mantissa) - 1; i >= 0; i--)
- {
- if (first_mantissa[i] - second_mantissa[i] >= 0)
- first_mantissa[i] -= (second_mantissa[i] - '0');
- else
- {
- int index_to_borrow_from = i - 1;
- while (first_mantissa[index_to_borrow_from] - '0' == 0)
- index_to_borrow_from--;
- first_mantissa[index_to_borrow_from]--;
- index_to_borrow_from++;
- for (; index_to_borrow_from != i; index_to_borrow_from++)
- first_mantissa[index_to_borrow_from] += 9;
- first_mantissa[i] += 10 - (second_mantissa[i] - '0');
- }
- }
- return YES;
- }
- int substraction_imitating_division(long_dial *first_mantissa, long_dial second_mantissa)
- {
- int amount_of_second_mantissa_in_first = 0;
- while (preparing_for_substraction(first_mantissa->double_dial, second_mantissa.double_dial))
- amount_of_second_mantissa_in_first++;
- increase_dial_mantissa(first_mantissa, 1);
- return amount_of_second_mantissa_in_first;
- }
- void delete_excess_zeroes(char *dial)
- {
- int dial_length = strlen(dial), i;
- for (i = dial_length - 1; dial[i] == '0' && i != 1; i--);
- dial[i + 1] = '\0';
- }
- void kind_of_mistake(int is_wrong)
- {
- switch (is_wrong)
- {
- case ZERO_DIVISION:
- printf("Division on zero\n");
- break;
- case TOO_BIG_POW:
- printf("Pow is out of allowed borders (from -99999 to 99999)\n");
- break;
- case TOO_LONG_DIAL:
- printf("Too long dial\n");
- break;
- case RESULT_POW_IS_OUT_OF_RANGE:
- printf("Result pow is out of range\n");
- break;
- case INCORRECT_SYMBOL:
- printf("Incorrect symbol was found\n");
- break;
- case EMPTY_INPUT:
- printf("Empty input\n");
- default:
- break;
- }
- }
- void info()
- {
- printf("Instruction\n\
- 1 - It isn't necessary to enter a sign for positive dials\n\
- 2 - The first dial should be integer. It can contain only up to 30 digits and a sign\n\
- 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\
- for a positive power a sign is not required\n\
- 4 - e must be lowercase only\n\
- 5 - The result is a dial which was made by division of integer dial on double\n\
- 6 - The result's format is\n\
- 0.mepow, where\n\
- m is a mantissa up to 30 digits long, pow - power of a dial (up to 5 digits long)\n\
- Examples of correct double input\n\
- 0.121\n\
- .121\n\
- 2.\n\
- 1e15\n\
- 2e-56\n\n\n");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement