在处理大数运算时,由于普通数据类型(如 int、long long)的范围限制,我们需要用字符串模拟手工乘法的过程。本文以 LeetCode 风格的 “字符串相乘” 题目为例
题目描述
给定两个以字符串形式表示的非负整数num1和num2,返回它们的乘积(同样以字符串形式表示)。
- 不能使用内置的大整数库或直接将输入转换为整数。
- 输入字符串长度范围:1 ≤ length ≤ 200,仅包含数字,且无前置零(除非本身是 “0”)。
核心思路:模拟手工乘法
手工乘法的步骤是:用num2的每一位去乘num1的每一位,将结果按位累加,最后处理进位得到最终结果。
具体步骤:
- 初始化临时数组:两个长度为
len1和len2的数相乘,结果长度最多为len1+len2,因此用一个长度为len1+len2的数组temp存储每一位的累加结果。 - 按位相乘并累加:遍历
num1和num2的每一位,计算乘积后,将 “个位” 累加到temp[i+j+1],“十位”(进位)累加到temp[i+j]。 - 处理进位与转换字符串:遍历临时数组,处理进位,再将有效数字转换为字符形式的结果字符串
完整代码实现
#include <stdio.h> #include <stdlib.h> #include <string.h> char* multiply(char* num1, char* num2) { // 特殊情况:其中一个数是0,直接返回"0" if (num1[0] == '0' || num2[0] == '0') { char* res = (char*)malloc(2 * sizeof(char)); res[0] = '0'; res[1] = '\0'; return res; } int len1 = strlen(num1); int len2 = strlen(num2); // 临时数组,存储每一位的累加结果(最多len1+len2位) int* temp = (int*)calloc(len1 + len2, sizeof(int)); // 按位相乘,累加结果到temp数组 for (int i = len1 - 1; i >= 0; i--) { int digit1 = num1[i] - '0'; // num1的当前位数字 for (int j = len2 - 1; j >= 0; j--) { int digit2 = num2[j] - '0'; // num2的当前位数字 int product = digit1 * digit2; // 累加:个位存到i+j+1,十位(进位)存到i+j int sum = temp[i + j + 1] + product; temp[i + j + 1] = sum % 10; temp[i + j] += sum / 10; } } // 将temp数组转换为结果字符串 char* result = (char*)malloc((len1 + len2 + 1) * sizeof(char)); int idx = 0; // 跳过开头的0(如果有的话) for (int i = 0; i < len1 + len2; i++) { if (temp[i] != 0 || idx > 0) { // 避免全0(已在开头处理) result[idx++] = temp[i] + '0'; } } result[idx] = '\0'; // 字符串结束符 free(temp); // 释放临时数组 return result; } // 测试示例 int main() { char num1[] = "123"; char num2[] = "456"; char* res = multiply(num1, num2); printf("结果:%s\n", res); // 输出:56088 free(res); return 0; }
代码解释
- 特殊情况处理:如果其中一个数是 “0”,直接返回 “0”,避免后续无效计算。
- 临时数组初始化:用
calloc初始化temp数组(默认值为 0),长度为len1+len2。 - 按位相乘:
- 从
num1和num2的 ** 末尾(低位)** 开始遍历,将字符转换为数字(- '0')。 - 计算两位的乘积后,将 “个位”(
sum%10)存入temp[i+j+1],“十位”(sum/10)存入temp[i+j](进位)。
- 从
- 结果转换:遍历
temp数组,跳过开头的 0(有效数字从第一个非 0 位开始),将数字转换为字符存入结果字符串,并添加结束符。
注意事项
- 内存管理:C 语言中需手动分配 / 释放内存(如
malloc/free),避免内存泄漏。 - 字符串结束符:结果字符串必须以
'\0'结尾,否则会出现乱码。 - 边界处理:需考虑 “其中一个数是 0”“结果开头有 0” 等边界情况。