pmmahesh Ответов: 2

Почему я получаю неправильный результат при вызове функции с переменными с похожим именем?


Уважаемый Эксперт

Я пытаюсь решить задачу умножения карастубы с помощью базовых команд языка Си. Я создал функцию для добавления двух чисел, которые хранятся в виде строки.
void sum(a,b, c) присвоит A+b c.
Я смог получить сумму для любого ввода, когда использовал только эту функцию. Но когда я использовал это в рекурсивной функции, я получаю некоторые неправильные результаты. Я вызывал эту функцию последовательно, но получаю результат только для одного вызова функции. Что меня удивляет, так это то, что иногда я получал идеальный результат, когда менял имена переменных. Будет ли имя переменной иметь какое-либо влияние в программе ?
Я делаю все это с помощью кода:: Block

Что я уже пробовал:

#include<stdio.h>
#include<string.h>
void sum(char*,char*,char*);
void prod(char*,char*,char*);
void seperate(char *a,char *b, char *c, char *d, char *x, char *y);
void powercalculation(char*,char);
void difference(char*, char*,char*);
unsigned char pub=0;
int main()
{

   char x[50],y[50],z[50];
    gets(x);
    gets(y);
    prod(x,y,z);
    puts(z);
    return(0);
}

void prod(char *x, char *y, char *z)
{
      char a[25],b[25],c[25],d[25],n;
      char temp1[50],temp2[50],temp3[50],temp4[50],ac[50],bd[50];

    if(strlen(x)>strlen(y))
        n=strlen(x);
    else
        n=strlen(y);
    if(strlen(x)==1||strlen(y)==1)           //either of input is singlr digit
    {

        strcpy(temp1,"0");
        strcpy(temp2,"0");
        if(strlen(x)==1)                    //adding y , x[0] times
        {
            temp3[0]=x[0];
            for(;temp3[0]>'0';temp3[0]--)
            {
                sum(temp1,y,temp2);
                strcpy(temp1,temp2);
            }
        }
        else                                //adding  , y[0] times
         {
            temp3[0]=y[0];
             for(;temp3[0]>'0';temp3[0]--)
            {
                sum(temp1,x,temp2);
                strcpy(temp1,temp2);
            }
        }
        strcpy(z,temp2);                    //copy result and return
        return;
    }
    else
    {
        seperate(a,b,c,d,x,y);              //deriving a,b,c,d from x and y
        sum(a,b,temp1);                     //a+b
        sum(c,d,temp2);                     //c+d
        puts(temp1);
        puts(temp2);
        prod(temp1,temp2,temp3);            //(a+b)*(c+d)
        prod(a,c,ac);                       //a*c
        prod(b,d,bd);                       //b*d
        difference(temp3,ac,temp1);         //(a+b)*(c+d)-ac
        difference(temp1,bd,temp3);         //(a+b)*(c+d)-ac-bd
        powercalculation(temp2,(2*n));      //powercalculation return 10^(n/2), for n even, it returns n/2 zeros,
                                            //Here argument is 2*n so returns n zeros
        strcat(ac,temp2);                   //(10^n)*a*c
        sum(ac,bd,temp2);                   //(10^n)ac+bd
        powercalculation(temp3,(n));
        if(n%2==0)                          //if n is even temp3 is n/2 number of zeros
        strcat(temp1,temp3);
        else
        prod(temp1,temp3,temp4);            //(10^n/2){(a+b)(c+d)-ac-bd}
        sum(temp4,temp2,z);
        return;
    }
}




//function for difference of a and b to c. a should be higher than b
//if difference of two fifty digit number is two digit, difference string size will be 2, no duplicate zeros in MSB


void difference(char *a, char *b, char *c)         //a should be higher
{
    char temp[10],temp1,temp2,i,k;
    temp1=strlen(a)-1;
    temp2=strlen(b)-1;

    for(i=0;temp2>=0;temp2--,temp1--,i++)           //taking individual digit and subtracting, diffenrce is stored in reverse form, ie LSB in temp[0]
    {
        if(a[temp1]>=b[temp2])
            temp[i]=a[temp1]-b[temp2]+48;
        else                                        //in case of borrow
        {
            temp[i]=a[temp1]+10-b[temp2]+48;
            if(a[temp1-1]>48)
                a[temp1-1]--;
            else
            {

                for(k=temp1-2;a[k]=='0';k--);
                a[k]--;

                for(k+=1;k<=temp1-1;k++)
                    a[k]='9';

            }
        }

    }
    for(;temp1>=0;temp1--,i++)                      //if size of b is less
    temp[i]=a[temp1];

    for(i-=1;temp[i]=='0';i--);                     //removing zeros in MSB
    for(k=0;i>=0;k++,i--)                           //reversing string
        c[k]=temp[i];
    if(k>0)
    c[k]='\0';
    else
        strcpy(c,"0");
    return;
}



//function to calculate power(10,n/2)

void powercalculation(char *a, char n)              //to calculate 10^(n/2)
{

    if(n%2==0)                                      //it will return n/2 zeros
    {
            strcpy(a,"00000000000000000000000000000000000000000000000");
            n/=2;
            a[n+1]='\0';
    }
    else                                            //return 10^(n/2)
    {
            strcpy(a,"31622776601683793319988935444327");//sqrt(10)=3.1622776601683793319988935444327
            n/=2;
            a[n+1]='\0';
    }
    return;

}



//function to seperate x,y into a,b,c,d

void seperate(char *a,char *b, char *c, char *d, char *x, char *y)
{
    char n,l1,l2,i,j,k,m,flag;
    l1=strlen(x);
    l2=strlen(y);
    if(l1>l2)
        n=l1;
    else
        n=l2;


if(l1==l2)                                      //size of both numbers same
if(n%2==0)                                      //if size is even
    {
    a[n/2]=b[n/2]=c[n/2]=d[n/2]='\0';
    for(i=n-1,j=(n/2)-1;i>=(n/2);i--,j--)       //assigning x and y to a,b,c,d
    {
        a[j]=x[i-(n/2)];
        b[j]=x[i];
        c[j]=y[i-(n/2)];
        d[j]=y[i];
    }
    }
    else                                        //if numbers are odd
    {
        a[n/2]=c[n/2]='\0';
        b[(n/2)+1]=d[(n/2)+1]='\0';
        b[n/2]=x[n-1];
        d[n/2]=y[n-1];
        for(i=n-2,j=(n/2)-1;j>=0;i--,j--)
        {
        a[j]=x[i-(n/2)];
        b[j]=x[i];
        c[j]=y[i-(n/2)];
        d[j]=y[i];
        }
    }


   else if(l1>l2)                               //if size of first string is higher than second
    if(l1%2==0)                                 //if size of first is even, since n in algorithm is the sizr of bigger string
    {
    k=l2-(l1/2)-1;
    a[l1/2]=b[l1/2]=d[l1/2]=c[k+1]='\0';
    flag=1;

    for(i=l1-1,j=(l1/2)-1,m=l2-1;i>=(l1/2);m--,i--,j--,k--)
    {
        a[j]=x[i-(l1/2)];
        b[j]=x[i];
        if(flag==1)
            if(l2<=l1/2)
        {
            flag=0;
            strcpy(d,y);
            strcpy(c,"0");
        }
        if(flag==1)
        {
            d[j]=y[m];
            if(k>=0)
                c[k]=y[m-(l1/2)];
        }


    }
    }
    else                                    //if size of first string odd
    {
        a[l1/2]='\0';
        b[(l1/2)+1]='\0';
        b[l1/2]=x[l1-1];
        k=l2-(l1/2)-2;
        flag=1;
        for(i=n-2,j=(n/2)-1,m=l2-2;j>=0;i--,j--,m--,k--)
        {
        a[j]=x[i-(n/2)];
        b[j]=x[i];
        if(flag==1)
            if(l2<=(l1/2)+1)
        {
            flag=0;
            strcpy(d,y);
            strcpy(c,"0");
        }
        if(flag==1)
        {
            d[j]=y[m];
            if(k>=0)
                c[k]=y[m-(l1/2)];
        }
        }
        if(flag==1)
        {
            d[(l1/2)+1]='\0';
            d[l1/2]=y[l2-1];
            c[l2-(l1/2)-1]='\0';
        }
    }

    else                                                //if second string is bigger than first
        if(l2%2==0)                                     //size of second string even
    {
    k=l1-(l2/2)-1;
    c[l2/2]=d[l2/2]=b[l2/2]=a[k+1]='\0';
    flag=1;

    for(i=l2-1,j=(l2/2)-1,m=l1-1;i>=(l2/2);m--,i--,j--,k--)
    {
        c[j]=y[i-(l2/2)];
        d[j]=y[i];
        if(flag==1)
            if(l1<=l2/2)
        {
            flag=0;
            strcpy(b,x);
            strcpy(a,"0");
        }
        if(flag==1)
        {
            b[j]=x[m];
            if(k>=0)
                a[k]=x[m-(l2/2)];
        }


    }
    }
    else                                    //size of secomd string odd
    {
        c[l2/2]='\0';
        d[(l2/2)+1]='\0';
        d[l2/2]=y[l2-1];
        k=l1-(l2/2)-2;
        flag=1;
        for(i=l2-2,j=(l2/2)-1,m=l1-2;j>=0;i--,j--,m--,k--)
        {
        c[j]=y[i-(l2/2)];
        d[j]=y[i];
        if(flag==1)
            if(l1<=(l2/2)+1)
        {
            flag=0;
            strcpy(b,x);
            strcpy(a,"0");
        }
        if(flag==1)
        {
            b[j]=x[m];
            if(k>=0)
                a[k]=x[m-(l2/2)];
        }
        }
        if(flag==1)
        {
            b[(l2/2)+1]='\0';
            b[l2/2]=x[l1-1];
            a[l1-(l2/2)-1]='\0';
        }
    }


    return;

}


//function defenition for sum
//it will give a+b to c for any size of a and b
//no zero will be in MSB


void sum(char *a, char *b, char *c)             //to find a+b=c
{

    char temp1,temp2,flag=0,i;
    temp1=strlen(a)-1;                          //index of LSB of a
    temp2=strlen(b)-1;                          //index of LSB of b
   if(temp1==temp2)                             //size of both string equal
   {
        c[temp1+2]='\0';                        //size of c=temp1+1-->extra one for carry
        for(;temp1>=0;temp1--)                  //adding individual characters
        {
        c[temp1+1]=a[temp1]+b[temp1]-48;        //adding ASCII and subtract ASCII of '0' to get difference
        if(flag==1)                             //flag=1 if there is carry from previoud addition; initially its 0
        {
            c[temp1+1]++;                       //existing carry is added and flag set to 0
            flag=0;
        }
        if(c[temp1+1]>57)                       //in case addition exceeds 10, carry will be generated
        {
            c[temp1+1]-=10;
            flag=1;
        }
        }
        if(flag==1)                             //setting up MSB
            c[0]=49;
        else
            {
                for(i=0;i                    c[i]=c[i+1];
            }

    }

    else if(temp1>temp2)                        //if size of first string is higher, follow similar steps
   {


        c[temp1+2]='\0';
        for(;temp2>=0;temp1--,temp2--)
        {
        c[temp1+1]=a[temp1]+b[temp2]-48;
        if(flag==1)
        {
            c[temp1+1]++;
            flag=0;
        }
        if(c[temp1+1]>57)
        {
            c[temp1+1]-=10;
            flag=1;
        }
        }


                for(;temp1>=0;temp1--)           //extra digits in first string is added
                {

                    c[temp1+1]=a[temp1]+flag;

                    if(c[temp1+1]>57)
                    {
                        c[temp1+1]-=10;
                        flag=1;
                    }
                    else
                        flag=0;
                }
            if(flag==1)
                c[0]='1';
            else
                for(i=0;i<strlen(c);i++)>
                    c[i]=c[i+1];


    }
     else                                       //second one is higher
   {


        c[temp2+2]='\0';
        for(;temp1>=0;temp1--,temp2--)
        {
        c[temp2+1]=a[temp1]+b[temp2]-48;
        if(flag==1)
        {
            c[temp2+1]++;
            flag=0;
        }
        if(c[temp2+1]>57)
        {
            c[temp2+1]-=10;
            flag=1;
        }
        }


                for(;temp2>=0;temp2--)            //extra digits in first string is added
                {

                    c[temp2+1]=b[temp2]+flag;

                    if(c[temp2+1]>57)
                    {
                        c[temp2+1]-=10;
                        flag=1;
                    }
                    else
                        flag=0;
                }
            if(flag==1)
                c[0]='1';
            else
                for(i=0;i<strlen(c);i++)>
                    c[i]=c[i+1];


    }

    return;
}

[no name]

Обучение использованию отладчика - это следующий шаг. Кстати: это "Карацуба", названная в честь человека.

Richard MacCutchan

Вы могли бы упростить это всего до нескольких строк кода, хотя бы с некоторыми подробностями о том, что именно вы делаете. Большая часть того, что вы написали, совершенно излишне.

pmmahesh

Я знаю, что это слишком долго. Я сделал то же самое в JAVA, используя substring() и все вместо этих более длинных функций. Здесь я просто старался как можно больше избегать встроенных функций или методов. Мне просто нравится знать, почему изменение имени переменной и все остальное влияет на результат.

Richard MacCutchan

Нет, я имею в виду, что вы должны выбросить весь этот код и начать все сначала. Проблема довольно проста:
1. прочитайте каждую строку.
2. разберите числа и оператор на отдельные токены.
3. Преобразования чисел в целые, дробные, как требуется.
4. вычислите сумму, разницу и т. д., основываясь на операторе.
5. Печатать ответ.

Кроме того, используйте собственные имена для ваших переменных, это поможет вам гораздо легче отлаживать проблемы.

pmmahesh

Ладно, я понял. Но кто-то сказал мне делать все эти операции в самой строке, потому что операции с большими числами можно выполнять только со строками(скажем, с двумя 50-значными числами). И я получил правильные результаты, когда вызвал функцию sum () из main (). Для того же самого ввода я не получил его , когда вызвал его из рекурсивной функции. Извините за беспокойство. Я просто хочу знать, какие могут быть причины для этого. А также дайте мне знать, как можно управлять большими числами.

Richard MacCutchan

Извините, мой предыдущий ответ был связан с C#.

Чтобы использовать большие целые числа, у вас есть довольно простой метод сложения, вычитания и умножения: просто начните с последней цифры каждой строки и обрабатывайте каждую пару до тех пор, пока не будет исчерпана самая короткая строка. Я сомневаюсь, что вам понадобятся все дополнительные переменные в вашем коде. Для подразделения вопрос более сложный, но я уверен, что у google будут какие-то идеи.

pmmahesh

Я сделал сложение и вычитание таким же образом, как вы упомянули выше. Я из электроники и не очень хорошо разбираюсь в языках. Мне просто нравится изучать DSA. Здесь я использовал указатели только для копирования адреса фактических параметров. Но я не получаю правильного результата, когда вызываю sum() дважды, получая правильный результат только один раз. Во всяком случае, я начну с нового. Но я хотел бы знать, есть ли для этого какая-то возможная причина, кроме ошибок в моих кодах, например, что-то связанное с памятью или еще что-то. Например, есть ли что-то, что нужно быть осторожным, имея дело со многими большими струнами.

Richard MacCutchan

Вы всегда должны предполагать, что ваш код не дает правильных результатов -Я ошибаюсь." Это лучшее место для начала и помогает вам настроиться на поиск ошибки в вашем коде, а не думать, что это какой-то другой фактор. Диагностика и исправление ошибок (отладка) может быть сложным процессом, но чем больше вы этим занимаетесь, тем легче.

pmmahesh

Хорошо. Я попробую с этим. Спасибо за помощь.

2 Ответов

Рейтинг:
14

KarstenK

Ваша основная проблема заключается в том, что вы используете указатели совершенно неправильно. Указатель - это некоторая переменная, которая указывает только на память, имеющую значение. Это как адрес, по которому кто-то проживает. Вот некоторые из них новичок объяснение указателей.

Я думаю, что ваш алгоритм - это какая-то манипуляция строками, но не Алгоритм Карацубы. Если вы хотите сделать это следующим образом: объявляйте для каждого вызова новые переменные и заполняйте их фактическими значениями, чтобы избежать проблем с указателями.

Для преобразования строки в число лучше использовать __ttoi. Что бы не только легче, но избежать указателя проблему. :-О


Рейтинг:
10

Patrice T

Вы должны научиться использовать отладчик как можно скорее. Вместо того чтобы гадать, что делает ваш код, пришло время увидеть, как он выполняется, и убедиться, что он делает то, что вы ожидаете.

Отладчик позволяет вам следить за выполнением строка за строкой, проверять переменные, и вы увидите, что есть точка, в которой он перестает делать то, что вы ожидаете.
Отладчик-Википедия, свободная энциклопедия[^]
Освоение отладки в Visual Studio 2010 - руководство для начинающих[^]

вы увидите, как ваш код работает и, вероятно, где он идет не так.