использование массива для хранения больших чисел

я новичок в программировании на С. Я написал этот код для добавления двух чисел со 100 цифрами, но я не знаю, почему код работает неправильно, он предполагает перемещение переноса, но это не так. а другая проблема заключается в том, что он просто игнорирует первую цифру (самую значащую цифру). может ли кто-нибудь помочь мне, пожалуйста?

#include <stdio.h>
#include <ctype.h>
int sum[101] = {0};
int add(int a, int b);

void main()
{
    static int a[100];
    static int b[100];
    char ch;
    int i = 0;
    int t;
    for (t = 0; t != 100; ++t)
    {
        a[t] = 0;
    }
    for (t = 0; t != 100; ++t)
    {
        b[t] = 0;
    }
    do
    {
        ch = fgetc(stdin);
        if ( isdigit(ch) )
        {
            a[i] = ch - 48;
            ++i;
        }
        else
            break;
    }
    while (ch != '\n' || i == 100 || i != '\0');
    i = 0;
    do
    {
        ch = fgetc(stdin);
        if ( isdigit(ch) )
        {
            b[i] = ch - 48;
            ++i;
        }
        else
            break;
    }
    while (ch != '\n' || i == 100 || i != '\0');

    for (;i!=0; --i)
    {
        add(a[i], b[i]);
    }

    for (i==0;i != 101; ++i)
    {
        printf("%d", sum[i]);
    }
}

int add( int a , int b)
{
    static int carry = 0;
    float s = 0;
    static int p = 101;

    if (0 <= a+b+carry <= 9) 
    {
        sum[p] = (a + b + carry);
        carry = 0;
        --p;
        return 0;
    }
    else
    {
        if (10 <= a+b+carry < 20)
        {
        s = (((a+b+carry)/10.0 ) - 1) * 10 ;
        carry = ((a+b+carry)/10.0) - (s/10);
        }
        else 
        {
            s = (((a+b+carry)/10 ) - 2) * 10;
            carry = ((a+b+carry)/10.0) - (s/10);
        }
        sum[p] = s;
        --p;
        return 0;
    }
}

person Mohammad Siavashi    schedule 09.02.2015    source источник
comment
используйте int main, а не void   -  person Ryan Haining    schedule 10.02.2015
comment
while (ch != '\n' || i == 100 || i != '\0'); - это действительно запутано   -  person M.M    schedule 10.02.2015
comment
Я это знаю, но не думаю, что это имеет какое-то отношение к проблеме.   -  person Mohammad Siavashi    schedule 10.02.2015
comment
for (i==0;i != 101; ++i) должно быть for (i = 0; i != 101; ++i)   -  person Anto Jurković    schedule 10.02.2015
comment
что пойдет не так? Что сказал отладчик?   -  person pm100    schedule 10.02.2015
comment
Ваша программа работает неправильно, если a и b имеют разное количество значащих цифр.   -  person John Bollinger    schedule 10.02.2015
comment
Что тебе нужно от этого if (0 <= a+b+carry <= 9) ?   -  person Anto Jurković    schedule 10.02.2015
comment
о, я забыл, что для цикла, но проблема все та же.   -  person Mohammad Siavashi    schedule 10.02.2015
comment
просто чтобы проверить, переносятся ли числа или нет   -  person Mohammad Siavashi    schedule 10.02.2015
comment
проблема в том, что когда я конвертирую строки в int, они будут правильно установлены в массиве a и b, но когда я это сделаю, я не добавлю самую значащую цифру, например, если я хочу добавить 45 + 21, это будет только 06.   -  person Mohammad Siavashi    schedule 10.02.2015


Ответы (1)


У ваших входных циклов есть серьезная проблема. Также вы используете i для подсчета длины как a, так и b, но не сохраняете длину a. Поэтому, если они введут два числа разной длины, вы получите странные результаты.

Потеря первой цифры из-за цикла:

for (;i!=0; --i)

Это будет выполняться для значений i, i-1, i-2, ..., 1. Он никогда не выполняется с i == 0. Порядок операций в конце каждой итерации цикла for таков:

  • применить третье условие --i
  • проверить второе условие i != 0
  • если проверка прошла успешно, введите тело цикла

Вот некоторый исправленный код:

int a_len;

for (a_len = 0; a_len != 100; ++a_len)
{
    int ch = fgetc(stdin);   // IMPORTANT: int, not char

    if ( ch == '\n' || ch == EOF )
        break;

    a[a_len] = ch;
}

Аналогично для b. На самом деле было бы разумно сделать этот код функцией, вместо того, чтобы копировать его и заменять a на b.

После завершения ввода вы можете написать:

if ( a_len != b_len )
{
    fprintf(stderr, "My program doesn't support numbers of different length yet\n");
    exit(EXIT_FAILURE);
}

for (int i = a_len - 1; i >= 0; --i) 
{
    add(a[i], b[i]);
}

Переходя к функции add, здесь есть более серьезные проблемы:

  • Невозможно даже попасть в случай, когда сумма равна 20
  • Не используйте числа с плавающей запятой, это приводит к неточностям. Вместо этого выполнение s = a+b+carry - 10; carry = 1; приводит к тому, чего вы хотите.
  • Вы пишете за пределами sum: массив размером [101] имеет допустимые индексы от 0 до 100. Но p начинается с 101.

NB. Способ, которым код больших чисел обычно решает проблемы ввода разного размера и некоторые другие проблемы, заключается в том, чтобы a[0] было младшей значащей цифрой; затем вы можете просто расширить неиспользуемые места настолько далеко, насколько вам нужно, когда вы добавляете или умножаете.

person M.M    schedule 09.02.2015