C语言按规则拼接字符串时strlen报错、长度计算为负数问题求解
问题1:main函数中大字符串的定义方式
两种安全的定义方案可选,都不会触发strlen报错也不会产生多余空格:
- 方案1:初始分配1字节存字符串结束符,初始就是空字符串,
strlen直接返回0
int main() { char* res = malloc(1); res[0] = '\0'; // 后续正常调用add函数拼接字符串 // 所有操作结束后记得释放内存 free(res); return 0; }
- 方案2:初始设为
NULL,只要在add函数里调用strlen前先做非空判断即可
// add函数内判断逻辑示例 size_t origin_len = (*addTo == NULL) ? 0 : strlen(*addTo);
问题2:newLength的正确计算方式
你计算得到负数的核心原因是用了有符号的int类型存长度,当拼接的字符串长度超过int的最大值时,数值溢出就会变成负数,需要换用strlen原生返回的无符号类型size_t存长度。
另外你原本的长度计算逻辑也有冗余,正确计算规则如下:
- 原有已拼接字符串的长度:
strlen(*addTo)(空串则为0) - 新增单词的长度:
strlen(temp) - 额外需要加2字节:1字节存单词后面的
#,1字节存整个字符串末尾的结束符\0 sizeof(char)固定为1,不需要额外乘
size_t newLength = strlen(*addTo) + strlen(temp) + 2;
现有代码其他问题修正
你当前的代码存在死循环问题:strtok第一次调用传原始字符串,后续取分词必须传NULL才能迭代,你写的while(str != NULL)判断中str永远不会被修改,会直接卡死。修正后的完整add函数参考:
void add(char** addTo, char* str, int on) { if (str == NULL || addTo == NULL) return; // 处理初始addTo为NULL的情况 if (*addTo == NULL) { *addTo = malloc(1); (*addTo)[0] = '\0'; } char* temp = strtok(str, " \n"); int hasWord = 0; while (temp != NULL) { size_t originLen = strlen(*addTo); size_t tempLen = strlen(temp); size_t newLength = originLen + tempLen + 2; *addTo = realloc(*addTo, newLength); // 不是第一个单词先加分隔符# if (hasWord) { strcat(*addTo, "#"); } strcat(*addTo, temp); hasWord = 1; // 取下一个分词,必须传NULL temp = strtok(NULL, " \n"); } // 不是最后一个小字符串加@分隔符 if (on) { size_t curLen = strlen(*addTo); *addTo = realloc(*addTo, curLen + 2); strcat(*addTo, "@"); } }
内容的提问来源于stack exchange,提问作者יונתן אליהו
相关产品推荐
相关产品推荐

