You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言通用文本换行程序求助:长单词换行异常修复

通用文本换行程序的C语言实现问题排查与修复

功能需求

  • 支持自定义最大行长度
  • 短单词仅在空格处换行
  • 超过行长度的长单词直接在长度限制处拆分
  • 正确处理ANSI转义字符,不计入可视长度

现存问题

  • 将测试字符串中的"haveeee"修改为"haveeeeE"时,通用函数my_split_string无法正确执行换行
  • 全长长单词测试用例中,第二、三行的换行位置比预期多一个字符

问题分析与修复方案

核心错误点

  1. ANSI转义字符处理不严谨:遍历字符串时未完整跳过整个转义序列,导致可视长度计算错误,进而影响换行判断。
  2. 长单词拆分边界判断滞后:仅在字符加入后才检查是否超过行长度,导致多计入一个字符,引发换行位置偏移。
  3. 空格换行逻辑的边界遗漏:寻找换行空格时未正确锁定当前行可视长度内的最后一个空格,导致短单词场景下的换行异常。

修复后的关键代码片段

#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;
}

修复说明

  1. ANSI转义序列完整跳过:遇到\x1B[开头的转义序列时,循环跳过直到遇到结束符m,确保这类字符完全不计入可视长度。
  2. 提前判断长单词拆分:在加入单个字符前就检查是否会超过行长度,一旦触发立即拆分,避免多计入字符导致换行位置偏移。
  3. 优化空格换行逻辑:单独处理空格场景,确保在空格处换行时,仅输出当前行已累积的内容,并正确重置起始位置和长度计数器。

内容的提问来源于stack exchange,提问作者Luguecos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:26:01