姓名ASCII码拼接转大整数分割求和代码问题求助及简化方案咨询
问题排查与优化方案
先来说说你的代码里几个关键问题,正是这些问题导致无法得到预期输出:
1. 整数溢出与类型错误
你的arr2int函数返回int类型,但姓名ASCII拼接出的数字往往非常大(比如Nova Stark的拼接数是19位),远超过int的最大范围(通常32位,最大值约20亿,仅10位数字)。而且你用atoi转换字符串,它只能处理int范围内的数,溢出后会得到完全错误的结果。
2. 错误的数字分割逻辑
你当前计算div的循环while(num/div>div)是在找接近平方根的除数,这并不是把数字按前后两半分割。比如奇数位数字12345,这个逻辑会得到前3位+后2位,但循环条件本身存在逻辑漏洞,遇到某些数字时会出现不符合预期的分割结果。
3. scanf格式错误
你的scanf(" %[^ ]",name);中换行符写法错误,应该是%[^\n],否则无法正确读取包含空格的姓名(比如Nova Stark中间的空格)。
修正后的代码
下面是修复了所有问题的版本,同时优化了内存使用:
#include<stdio.h> #include<stdlib.h> #include<string.h> // 直接计算拼接后的大整数,避免字符串转换的溢出风险 long long arr2longlong(int arr[], int size) { long long num = 0; for(int i = 0; i < size; ++i) { // 计算当前ASCII值的位数(0-127最多3位) int digit_len = snprintf(NULL, 0, "%d", arr[i]); // 将已有数字左移对应位数 for(int j=0; j<digit_len; j++){ num *= 10; } num += arr[i]; } return num; } // 获取数字的总位数 int get_digit_count(long long num) { if(num == 0) return 1; int count = 0; while(num > 0) { count++; num /= 10; } return count; } int main() { int *A; long long num; char name[50]; printf("Enter your name : "); scanf(" %[^\n]", name); // 修正格式,支持读取带空格的姓名 int len = strlen(name); A = (int*)malloc(len * sizeof(int)); if(A == NULL) { // 检查内存分配是否成功 printf("Memory allocation failed!\n"); return 1; } for(int i=0; i<len; i++) { A[i] = name[i]; // 存储每个字符的ASCII值 } num = arr2longlong(A, len); free(A); // 释放内存,避免泄漏 // 按位数分割成前后两半 int digit_count = get_digit_count(num); int half_digits = digit_count / 2; long long div = 1; for(int i=0; i<half_digits; i++) { div *= 10; } long long a, b; if(digit_count % 2 == 0) { a = num / div; b = num % div; } else { // 奇数位时前半部分多一位(比如12345分成123和45) div *= 10; a = num / div; b = num % div; } long long sum = a + b; printf("The required integer is %lld and the sum is %lld\n", num, sum); return 0; }
更简便的实现方案
其实完全不需要用数组中转,直接遍历姓名字符时完成拼接和位数统计,代码更简洁高效:
#include<stdio.h> #include<string.h> int main() { char name[50]; long long num = 0; int total_digits = 0; printf("Enter your name : "); scanf(" %[^\n]", name); for(int i=0; name[i] != '\0'; i++) { int ascii = name[i]; // 记录当前ASCII值的位数 int digit_len = snprintf(NULL, 0, "%d", ascii); total_digits += digit_len; // 拼接数字 for(int j=0; j<digit_len; j++){ num *= 10; } num += ascii; } // 分割成两半 int half = total_digits / 2; long long div = 1; for(int i=0; i<half; i++){ div *=10; } long long a, b; if(total_digits %2 ==0){ a = num / div; b = num % div; } else { div *=10; a = num / div; b = num % div; } long long sum = a + b; printf("The required integer is %lld and the sum is %lld\n", num, sum); return 0; }
如果姓名过长导致拼接数字超过long long范围(最多19位),还可以用字符串存储拼接结果,再分割字符串求和,完全避免溢出问题:
#include<stdio.h> #include<string.h> int main() { char name[50]; char num_str[200] = {0}; // 足够存储所有ASCII值的拼接字符串 printf("Enter your name : "); scanf(" %[^\n]", name); // 拼接ASCII值为字符串 for(int i=0; name[i] != '\0'; i++) { char ascii_str[4]; // ASCII最多3位,加结束符 sprintf(ascii_str, "%d", name[i]); strcat(num_str, ascii_str); } // 分割字符串为两半 int len = strlen(num_str); int half = len / 2; char first_half[100] = {0}; char second_half[100] = {0}; strncpy(first_half, num_str, len - half); // 奇数位时前半多一位 strcpy(second_half, num_str + (len - half)); // 转成long long求和(超长数字需实现大数加法) long long a = atoll(first_half); long long b = atoll(second_half); long long sum = a + b; printf("The required integer is %s and the sum is %lld\n", num_str, sum); return 0; }
内容的提问来源于stack exchange,提问作者Nova Stark
相关产品推荐
相关产品推荐

