题目
Given two numbers represented as strings, return multiplication of the numbers as a string.
Note: The numbers can be arbitrarily large and are non-negative.
题目大意:求两个任意长的全部由数字构成的字符串的乘积。
思路
由于题目已经说明了,两个字符串是任意长的,因此不能将字符串转化为数字,然后相乘得到乘积最后再转化为字符串返回。这种思路将会导致溢出。
因此,我们只能选择边计算边存储的方法来进行计算。
char* multiply(char* num1, char* num2) {
if(num1==NULL||num2==NULL){
return NULL;
}
int len1=strlen(num1);
int len2=strlen(num2);
if(len1<1||len1<1){
return NULL;
}
char *result=(char *)malloc((len1+len2+1)*sizeof(char));//最后一个位置用来放字符'\0'
if(result==NULL){
exit(EXIT_FAILURE);
}
memset(result,'0',(len1+len2+1)*sizeof(char));//初始化为'0';注意:是'0',并不是初始化为 0
int carry=0;//用来表示进位,初始化为零
for(int i=len1-1;i>=0;i--){
int tempNum=num1[i]-'0';
carry=0;
int j=len2-1;
for(;j>=0;j--){
int val=(num2[j]-'0')*tempNum;
//然后将此值存储在正确的位置;并考虑进位·这样使得进行加法是正确的。
int temp=(result[i+j+1]-'0')+val+carry;
carry=temp/10;
result[i+j+1]=temp%10+'0';
// printf("%c ",result[i+j+1]);
}
if(carry>0){//在出内层循环之后,要把最高位的进位进行存储起来
result[i+j+1]=carry+'0';
}
// printf("\n");
}
// bool flag=false;
// if(carry>0){//如果最高位有进位,则result第一个位置有字符在存储,否则没有
// flag=true;//如果没有进位,则要将result最前面的一位去掉。
// }
result[len1+len2]='\0';
// puts(result);
//把前面的零去掉,使得index指向第一个不为零的下标。如果全部为零,则index=len1+len2,输出一个零即可。
int index=0;
for(;index<len1+len2;index++){
if(result[index]!='0'){
break;
}
}
return index==len1+len2?(result+index-1):result+index;
}
测试代码
int main(void){
char str1[100];
char str2[100];
while(gets(str1)){
gets(str2);
puts(multiply(str1,str2));
printf("\n");
}
return 0;
}
出现的问题
1、没有考虑若最高位没有进位时,最后一位将是零。没有将最高位的一个零去掉。
于是就有了如下代码:
bool flag=false;
if(carry>0){//如果最高位有进位,则result第一个位置有字符在存储,否则没有
flag=true;
}
.....
return flag?result:result+1;
可以看到,这样虽然解决了去掉去掉最高位为零的情况。但是并没有考虑到下面这种情况。
2、结果中有多个零的情况。
于是又继续改进,就有了如下的代码:
//把前面的零去掉,使得index指向第一个不为零的下标。如果全部为零,则index=len1+len2,输出一个零即可。
int index=0;
for(;index<len1+len2;index++){
if(result[index]!='0'){
break;
}
}
return index==len1+len2?(result+index-1):result+index;
这样就正确的解决了这个问题。
最后AC结果如下: