c - Multiply Strings - [leetcode] 该代码在计算机上运行良好,但在网站上却不行
问题描述
对于 LeetCode 上的“字符串相乘”挑战,我用 C 编写了这段代码;
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char *multiply(char *num1, char *num2){
int num1_len = strlen(num1);
int num2_len = strlen(num2);
int *multiplication;
int total_len = num1_len+num2_len;
multiplication = (int *)malloc(sizeof(int)*total_len);
int i, j, k, l;
for(i = 0; i<total_len; i++){
multiplication[i] = 0;
}
for(i = num1_len-1, k = total_len-1; i>= 0; i--, k--){
for(j = num2_len-1, l = 0; j>= 0; j--, l++){
multiplication[k-l] += (num1[i]-48)*(num2[j]-48);
if(multiplication[k-l]>= 10){
int number = multiplication[k-l];
int carry = number%10;
multiplication[k-l] = carry;
multiplication[k-l-1] += (number-carry)/10;
}
}
}
char *multiplication_result;
multiplication_result = (char *)malloc(sizeof(char));
int start_index;
for(i = 0; i<total_len; i++){
if(multiplication[i] != 0){
start_index = i;
break;
}
}
for(i = start_index, j = 0; i<total_len; i++, j++){
multiplication_result[j] = multiplication[i]+48;
multiplication_result = (char *)realloc(multiplication_result, j+2);
}
return multiplication_result;
}
这在我的电脑上工作得很好。我用不同的字符串对其进行了测试,每个测试都给出了预期的输出。但是,每次我在 leetcode 上运行完全相同的代码时,都会出现运行时错误。它给出了以下错误:
==================================================== =================33==错误:AddressSanitizer:地址 0x602000000092 上的堆缓冲区溢出在 pc 0x55d553422e2b bp 0x7fff8bada4d0 sp 0x7fff8bada4c0 在 0x602000007092 线程 T002fcef01 处读取大小为 1在 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2) 中,0x602000000092 位于线程 T0 分配的 2 字节区域 [0x602000000090,0x602000000092) 右侧的 0 字节:#0 0x7fcef26f6ffe in __interceptorrealloc /lib/x86_64-linux-gnu/libasan.so.5+0x10dffe) #3 0x7fcef1ab10b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2) 错误地址周围的影子字节:0x0c047fff7fc0:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c047fff7fd0:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c047fff7fe0:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c047fff8000: fa fa 02 fa fa fa 02 fa fa fa 00 fa fa fa fd fa => 0x0c047fff8010:fa fa [02]fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8020:fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 影子字节图例(一个影子字节代表 8 个应用程序字节):
可寻址:00 部分可寻址:01 02 03 04 05 06 07 堆左redzone:fa 释放的堆区域:fd
堆栈左 redzone:f1 堆栈中 redzone:f2 堆栈右 redzone:f3 返回后堆栈:f5 堆栈使用范围后:f8 全局 redzone:f9 全局初始化顺序:
f6 被用户中毒:f7 容器溢出:fc 数组 cookie:ac Intra object redzone:bb ASan internal:
fe Left alloca redzone:ca Right alloca redzone:cb
Shadow gap:cc ==33==ABORTING
我刚开始对leetcode不太熟悉,也不太擅长阅读这些错误信息。那么是什么导致了这个问题呢?
解决方案
您的代码中有(可能)两个问题。第一个(明确的)是您永远不会在字符串中添加nul
终止符。要解决此问题,只需在最终循环之后和语句之前multiplication_result
添加以下行:for
return
multiplication_result[j] = '\0';
第二个(可能的)问题——被 clang-cl 编译器标记为警告——是在最终循环start_index
开始时变量的值可能未初始化。for
要解决这个问题,只需在声明时给它一个初始值 ( 0
):
int start_index = 0;
据我所知,第二个问题只有在两个输入字符串都表示零时才会成为问题(但我不想在上面赌任何钱)。
此外,作为可能的改进,以下行:
multiplication[k - l - 1] += (number - carry) / 10;
可以简化为:
multiplication[k - l - 1] += number / 10;
因为整数除法的商将与减去该除法的(潜在)余数后i/n
执行除法的结果相同(这就是运算符的工作方式)。%