在C语言中如何将字符串转为长整型且保留前导零?
问题本质:整型不存储前导零
long/long long等数值类型仅存储数值本身,前导零属于字符串的格式信息,并非数值的一部分。因此无论用strtol还是sscanf,转换为整型后前导零必然丢失——这是数值类型的特性,无法通过转换函数解决。
你的实际需求是处理链表中的超长数字求和,当前代码还存在两个致命问题:
- 链表拼接的字符串可能长达500位,远超
long long的存储范围(最多19位),会直接导致数值溢出、计算错误; - 依赖整型反转的逻辑在溢出后完全失效。
正确解决方案:字符串模拟大数加法
既然无法用整型处理超长数字,直接在字符串层面模拟加法即可,同时自然保留前导零(或按需处理)。
1. 实现大数加法函数
#include <stdio.h> #include <stdlib.h> #include <string.h> // 大数加法,返回结果字符串(需手动free) char* addStrings(const char* num1, const char* num2) { int len1 = strlen(num1); int len2 = strlen(num2); int max_len = len1 > len2 ? len1 : len2; // 结果最多比最长字符串多1位(进位) char* result = (char*)malloc(max_len + 2); if (!result) return NULL; int carry = 0; int i = len1 - 1, j = len2 - 1, k = 0; // 从低位到高位逐位相加 while (i >= 0 || j >= 0 || carry > 0) { int digit1 = i >= 0 ? num1[i--] - '0' : 0; int digit2 = j >= 0 ? num2[j--] - '0' : 0; int sum = digit1 + digit2 + carry; carry = sum / 10; result[k++] = (sum % 10) + '0'; } // 反转结果(因为是从低位开始存储的) for (int p = 0, q = k - 1; p < q; p++, q--) { char temp = result[p]; result[p] = result[q]; result[q] = temp; } result[k] = '\0'; return result; }
2. 修改链表求和逻辑
替换原代码中整型转换、反转的部分,直接用字符串加法处理:
struct ListNode *addTwoNumbers(struct ListNode * l1, struct ListNode * l2) { char num1[500] = ""; char num2[500] = ""; // 拼接链表节点到字符串(保留所有前导零) struct ListNode *tmp = l1; while (tmp != NULL) { char c[2]; // 单个数字仅需2字节存储 sprintf(c, "%d", tmp->val); strcat(num1, c); tmp = tmp->next; } tmp = l2; while (tmp != NULL) { char c[2]; sprintf(c, "%d", tmp->val); strcat(num2, c); tmp = tmp->next; } printf("%s + %s\n", num1, num2); // 执行大数加法 char* sum_str = addStrings(num1, num2); if (!sum_str) { exit(1); // 内存分配失败处理 } printf("Sum: %s\n", sum_str); // 生成结果链表(保持原逻辑:将字符串逆序生成链表) struct ListNode *head = NULL; int len = strlen(sum_str); for (int i = 0; i < len; i++) { struct ListNode *n = malloc(sizeof(struct ListNode)); if (n == NULL) { // 内存分配失败时,释放已分配资源 while (head) { struct ListNode* next = head->next; free(head); head = next; } free(sum_str); exit(1); } n->val = sum_str[i] - '0'; n->next = head; head = n; } // 释放资源 free(sum_str); tmp = l1; while (tmp != NULL) { struct ListNode *next = tmp->next; free(tmp); tmp = next; } tmp = l2; while (tmp != NULL) { struct ListNode *next = tmp->next; free(tmp); tmp = next; } return head; }
补充说明
- 如果需要去掉结果字符串的前导零(比如
00123转成123),可以在生成链表前遍历字符串,找到第一个非零字符后再处理; - 若链表本身是低位在前的存储结构(如LeetCode经典两数相加题),更高效的方式是直接在链表上逐位相加并处理进位,无需拼接成字符串。
内容的提问来源于stack exchange,提问作者El Barto
相关产品推荐
相关产品推荐

