如何移除字符串单数字长除法输出末尾的随机Unicode符号?
字符串大数除以单数字输出乱码问题解决
需求:实现函数接收字符串形式的大数和单个数字,执行长除法,返回「商R余数」格式的字符串。
原代码
#include<stdio.h> #include<stdlib.h> #include<string.h> char* str_div_by_digit(const char* num,int digit) { char *ans=malloc(sizeof(char)*100); int index = 0; int n = strlen(num); int dividend = num[index] - 48; while(dividend < digit && index+1 < n) { dividend = dividend * 10 + (num[++index] - 48); } int i = 0; while(n > index) { char ans1 = 48 + (dividend / digit); ans[i++] = ans1; if(index == n-1) { dividend = dividend % digit; index++; } else { dividend = (dividend % digit) * 10 + (num[++index] - 48); } } int x = strlen(ans)-1; if(x==0) { ans[i++] = 48; dividend = dividend % digit; } ans[i++] = 'R'; ans[i] = 48 + dividend; //void free(void *num); void free(void *ans); // Thanks @WhozCraig for pointing this out. return ans; } int main() { printf("%s\n",str_div_by_digit("15",6)); printf("%s",str_div_by_digit("15002",5)); printf("%s\n",str_div_by_digit("10000000000000000000000000000003",5)); printf("%s",str_div_by_digit("1237657129312587312493712539",7)); }
输出异常
C:\Users\MyName\Desktop\Whatever> program.exe 2R3 // Correct 3000R2╬ // Correct except for last character. 2000000000000000000000000000000R3 // Correct 176808161330369616070530362R5☻►☻ // Correct except for last character(s?).
问题分析与修复
出现乱码的核心原因是C语言字符串必须以'\0'(空字符)结尾,原代码中给ans赋值完余数后没有添加终止符,printf会持续读取内存直到遇到'\0',导致末尾出现随机乱码。此外还有几个潜在问题需要修复:
添加字符串终止符:在赋值完余数后,必须添加
'\0'标记字符串结束:ans[i++] = 'R'; ans[i++] = 48 + dividend; ans[i] = '\0'; // 新增终止符修复内存分配大小:原代码固定分配100字节,对于超长输入(比如第三个测试用例的31位数字)会导致内存不足,应该根据输入字符串长度动态分配:
// 商最多和原数字长度相同,加上R、余数和终止符,分配strlen(num)+3足够 char *ans = malloc(sizeof(char) * (strlen(num) + 3)); if (ans == NULL) { // 增加内存分配失败判断 return NULL; }移除错误的
free声明:原代码中void free(void *ans);是错误的重复声明,直接删除即可。同时main函数中要记得释放返回的内存,避免内存泄漏:int main() { char *res1 = str_div_by_digit("15",6); printf("%s\n", res1); free(res1); char *res2 = str_div_by_digit("15002",5); printf("%s\n", res2); free(res2); char *res3 = str_div_by_digit("10000000000000000000000000000003",5); printf("%s\n", res3); free(res3); char *res4 = str_div_by_digit("1237657129312587312493712539",7); printf("%s\n", res4); free(res4); }修复商为0的处理逻辑:原代码中
strlen(ans)-1的计算是错误的(此时ans还没有终止符,strlen结果不确定),应该直接判断是否没有写入任何商字符:// 替换原有的x相关逻辑 if (i == 0) { // 如果没有写入任何商数字,说明商是0 ans[i++] = '0'; }
修复后的完整代码
#include<stdio.h> #include<stdlib.h> #include<string.h> char* str_div_by_digit(const char* num,int digit) { if (digit == 0) { // 避免除以0 return NULL; } // 动态分配足够内存 size_t num_len = strlen(num); char *ans = malloc(sizeof(char) * (num_len + 3)); if (ans == NULL) { return NULL; } int index = 0; int n = num_len; int dividend = num[index] - '0'; // 用'0'代替48更直观 // 凑够大于等于digit的被除数 while(dividend < digit && index + 1 < n) { dividend = dividend * 10 + (num[++index] - '0'); } int i = 0; while(n > index) { ans[i++] = '0' + (dividend / digit); if(index == n - 1) { dividend = dividend % digit; index++; } else { dividend = (dividend % digit) * 10 + (num[++index] - '0'); } } // 处理商为0的情况 if (i == 0) { ans[i++] = '0'; } // 添加R和余数,加上终止符 ans[i++] = 'R'; ans[i++] = '0' + dividend; ans[i] = '\0'; return ans; } int main() { char *res1 = str_div_by_digit("15",6); printf("%s\n", res1); free(res1); char *res2 = str_div_by_digit("15002",5); printf("%s\n", res2); free(res2); char *res3 = str_div_by_digit("10000000000000000000000000000003",5); printf("%s\n", res3); free(res3); char *res4 = str_div_by_digit("1237657129312587312493712539",7); printf("%s\n", res4); free(res4); // 测试商为0的情况 char *res5 = str_div_by_digit("5",10); printf("%s\n", res5); free(res5); return 0; }
修复后输出
2R3 3000R2 2000000000000000000000000000000R3 176808161330369616070530362R5 0R5
内容的提问来源于stack exchange,提问作者itrycode532435
相关产品推荐
相关产品推荐

