Почему я получаю неправильный результат при вызове функции с переменными с похожим именем?
Уважаемый Эксперт
Я пытаюсь решить задачу умножения карастубы с помощью базовых команд языка Си. Я создал функцию для добавления двух чисел, которые хранятся в виде строки.
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
Хорошо. Я попробую с этим. Спасибо за помощь.