С++ Написать алгоритм поразрядных операций с длинными целыми числами, представленными строками символов

Помогите, пожалуйста, сдетектить и исправить ошибки в коде. Я написал код для операций с длинными целыми числами(сложение, вычитание, умножение), и запутался в алгоритме работы. Буду сильно благодарен)

По заданию я ввожу 2 длинных целых неотрицательных числа a1 и a2, прога должна вывести результаты операций над ними. Цифры храню в динамических массивах char malloc, который как строки символов. Операции выполняются через функцию string_operations().

Поразрядные операции — это значит например, что каждый символов char первого числа складывается с char'ом второго числа, и они должны стоять на одинаковых позициях в числах. Если результат их сложения s > 9, то десятичный разряд числа запоминается флагом переноса, переносится и складывается со следующим разрядом. Функция усложняется проверкой чисел на одинаковое кол-во символов, чтобы они правильно сладывались/вычитались. То есть, если ввели a1 = 12000; a2 = 1100 то после проверки числа внутри функции приводятся к такому виду a1 = 12000; a2_same = 01100 . У обоих кол-во символов теперь 5. Строку с недостаточным кол-вом символов, переношу в an_same

Сейчас у кода такие проблемы:

  1. Дебагер жалуется на моменте с проверкой чисел на одинаковое кол-во символов. Что-то я неправильно делаю с памятью и стеком. Решено, см. комментарии к вопросу введите сюда описание изображения

  2. Если убрать проверку чисел на одинаковое кол-во символов, то дальше видно, что алгоритм некорректно работает с вычитанием и умножением чисел. А именно из меньшего не вычитается большее, если результат больше 10, то не работает перенос десятичного разряда на следующую позицию. Я не понимаю, какие ошибки в алгоритме

Тут приложу разные тесты, чтобы было легче понять, где ошибка пример вычитания из меньшего большего числа 1 пример нерабочего переноса 2 пример нерабочего переноса 3 пример нерабочего переноса 4 пример нерабочего переноса

  1. Наверное, неправильно сразу создавать массивы с размером N. Правильнее будет создать пустой массив и по ходу алгоритма выделять память realloc. Но не понимаю, в каком именно месте алгоритма ставить realloc, т.к. переносы и так не работают.

Вот сам код (не обращайте внимание, что C мешается с C++, это не правильно, я это исправлю, но пока мне важна работающая программа и алгоритм):

#include <stdlib.h> 
#include <stdio.h>
#include <malloc.h>
#include <iostream>
using namespace std;

#define N 81

char* sum = (char*)malloc(sizeof(char) * N * N);

int string_operations(char* a1, char* a2, char action, char* sum)
{
    int carry, i = 0, v1, v2, s;
    char a1_same[N]{};
    char a2_same[N]{};
    sum[0] = 0;
    size_t a1_length = strlen(a1); // кол-во символов a1
    size_t a2_length = strlen(a2); // кол-во символов a2
    
    // блок кода ниже для обработки цифр разной длины, чтобы они складывались правильно, к числу с меньшей длиной прибавляю слева нули 0, до длины большего числа
//----------------------------------------------------------------------------------------
    if (a1_length > a2_length)
    {
        size_t temp = a1_length - a2_length; // кол-во недостающих символов, чтобы уравнить a2 с a1
        
        for (i = 0; i < temp; i++) // в a2_same добавляем кол-во нулей, до уравнения длины a2 с a1
        {
            a2_same[i] = '0';
        }
        strcat_s(a2_same, temp, a2); // к концу a2_same добавляем копию a2
    }
    else if (a2_length > a1_length)
    {
        size_t temp = a2_length - a1_length; // кол-во недостающих символов, чтобы уравнить a1 с a2

        for (i = 0; i < temp; i++) // в a1_same добавляем кол-во нулей, до уравнения длины a2 с a1
        {
            a1_same[i] = '0';
        }
        strcat_s(a1_same, N, a1); // к концу a1_same добавляем копию a1
    }

//----------------------------------------------------------------------------------------

    // поразрядно работаем с числами 
    carry = 0; // флаг переноса
    for (i = a1_length - 1; i >= 0; i--)
    {
        if (a1_length > a2_length)
        {
            v1 = (int)(a1[i] - '0');
            v2 = (int)(a2_same[i] - '0');
        }
        else if (a2_length > a1_length)
        {
            v1 = (int)(a1_same[i] - '0');
            v2 = (int)(a2[i] - '0');
        }
        else
        {
            v1 = (int)(a1[i] - '0');
            v2 = (int)(a2[i] - '0');
        }
        
        if ((v1 < 0) || (v1 > 9) || (v2 < 0) || (v2 > 9)) cout << "Введена не цифра \n";
        
        if (action == '+') 
        { 
            s = v1 + v2 + carry; 
            if (s <= 9) 
                carry = 0; 
            else 
            { 
                s = s - 10; 
                carry = 1; 
            } 
        }
        else if(action == '-')
        { 
            if (v1 >= v2)
            {
                s = v1 - v2 - carry;
                if (s >= 0)
                    carry = 0;
                else
                {
                    s = s + 10;

                    carry = 1;
                }
            }
            else 
            {
                s = v2 - v1 - carry;
                s = -fabs(s); // знак меняется на минус 
                carry = 0;
            }            
        }
        else // умножение
        {
            s = v1 * v2;
            if (s > 9)
            {
                int m = (v1 * v2) / 10; // десятичная часть числа 
                int f = (v1 * v2) - (m * 10); // единичная часть числа 
                s = m;
                sum[i + 1] = m; // десятичная часть числа переносится в следующий разряд
                sum[i] = f; // единичная часть числа остается на своем разряде

            }
        }
        sum[i] = (char)(s + '0'); // добавление результата вычисления в массив sum
    }
    sum[a1_length] = 0;
    return 0;
}

int main()
{
    setlocale(LC_ALL, "Russian");
    int result; 
    char *a1 = (char*)malloc(sizeof(char) * N);
    char *a2 = (char*)malloc(sizeof(char) * N);
    cout << "Введите первое длинное число \n";
    cin >> a1;
    cout << "Введите второе длинное число \n";
    cin >> a2;
    // сложение
    result = string_operations(a1, a2, '+', sum);
    printf("%s+%s=%s r=%d\n", a1, a2, sum, result);
    // вычитание
    result = string_operations(a1, a2, '-', sum);
    printf("%s-%s=%s r=%d\n", a1, a2, sum, result);
    // умножение
    result = string_operations(a1, a2, '*', sum);
    printf("%s*%s=%s r=%d\n", a1, a2, sum, result);
    //очистка памяти
    free(a1);
    a1 = NULL;
    free(a2);
    a2 = NULL;
    free(sum);
    sum = NULL;
    return 0;
}

Спасибо, что помогаете начинающим! ❤


Ответы (0 шт):