C语言通用文本换行程序求助:长单词换行异常修复
通用文本换行程序的C语言实现问题排查与修复
功能需求
- 支持自定义最大行长度
- 短单词仅在空格处换行
- 超过行长度的长单词直接在长度限制处拆分
- 正确处理ANSI转义字符,不计入可视长度
现存问题
- 将测试字符串中的"haveeee"修改为"haveeeeE"时,通用函数
my_split_string无法正确执行换行 - 全长长单词测试用例中,第二、三行的换行位置比预期多一个字符
问题分析与修复方案
核心错误点
- ANSI转义字符处理不严谨:遍历字符串时未完整跳过整个转义序列,导致可视长度计算错误,进而影响换行判断。
- 长单词拆分边界判断滞后:仅在字符加入后才检查是否超过行长度,导致多计入一个字符,引发换行位置偏移。
- 空格换行逻辑的边界遗漏:寻找换行空格时未正确锁定当前行可视长度内的最后一个空格,导致短单词场景下的换行异常。
修复后的关键代码片段
#include <stdio.h> #include <string.h> #include <stdlib.h> void my_split_string(const char *str, int max_line_length) { int len = strlen(str); int start = 0; int current_length = 0; char *line = malloc(max_line_length + 2); // 预留空间存换行和结束符 if (!line) return; for (int i = 0; i <= len; i++) { // 处理字符串结束或空格的情况 if (i == len || str[i] == ' ') { // 计算当前片段的可视长度 int temp_len = 0; for (int j = start; j < i; j++) { if (str[j] == '\x1B' && j < len - 1 && str[j+1] == '[') { // 跳过ANSI转义序列 while (j < len && str[j] != 'm') j++; j++; } else { temp_len++; } } if (current_length + temp_len > max_line_length) { // 先输出当前已累积的内容 memcpy(line, str + start, i - start - (str[i] == ' ' ? 1 : 0)); line[i - start - (str[i] == ' ' ? 1 : 0)] = '\0'; printf("%s\n", line); start = str[i] == ' ' ? i + 1 : i; current_length = temp_len; } else { current_length += temp_len; if (str[i] == ' ') { // 记录空格位置,准备换行 memcpy(line, str + start, i - start); line[i - start] = '\0'; printf("%s\n", line); start = i + 1; current_length = 0; } } } else { // 处理普通字符和ANSI转义序列 if (str[i] == '\x1B' && i < len - 1 && str[i+1] == '[') { // 跳过整个转义序列,不计入可视长度 while (i < len && str[i] != 'm') i++; i++; } else { // 检查当前字符加入后是否超过行长度 if (current_length + 1 > max_line_length) { // 拆分长单词 memcpy(line, str + start, i - start); line[i - start] = '\0'; printf("%s\n", line); start = i; current_length = 1; } else { current_length++; } } } } // 输出最后一行剩余内容 if (start < len) { memcpy(line, str + start, len - start); line[len - start] = '\0'; printf("%s\n", line); } free(line); } // 测试用例 int main() { // 测试用例1:包含修改后的长单词 const char *test1 = "Hello haveeeeE world! This is a test string with long words and ANSI \x1B[31mred\x1B[0m text."; // 测试用例2:全长长单词 const char *test2 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"; printf("Test 1 (max line length 10):\n"); my_split_string(test1, 10); printf("\nTest 2 (max line length 10):\n"); my_split_string(test2, 10); return 0; }
修复说明
- ANSI转义序列完整跳过:遇到
\x1B[开头的转义序列时,循环跳过直到遇到结束符m,确保这类字符完全不计入可视长度。 - 提前判断长单词拆分:在加入单个字符前就检查是否会超过行长度,一旦触发立即拆分,避免多计入字符导致换行位置偏移。
- 优化空格换行逻辑:单独处理空格场景,确保在空格处换行时,仅输出当前行已累积的内容,并正确重置起始位置和长度计数器。
内容的提问来源于stack exchange,提问作者Luguecos
相关产品推荐
相关产品推荐

