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

C语言简易文本编辑器退格键行首删除时上行内容消失问题求助

C语言简易文本编辑器退格键行首删除时上行内容消失问题求助

兄弟我完全懂你遇到的坑!刚跑了你的代码,确实在光标位于行首按退格时,上一行的内容会“凭空消失”——但其实数据已经合并了,只是显示和内存操作出了问题,咱们一步步来排查修复:

问题根源分析

我帮你揪出了几个关键问题:

  1. 字符串溢出导致未定义行为:你用strcat合并两行时,完全没检查上一行剩余空间够不够。如果两行总长度超过MAX_LINE_LEN-1,就会越界覆盖字符串结束符\0,printf打印时就会乱码甚至“吞掉”内容。
  2. 光标位置没适配屏幕提示:你在main开头打印了编辑器提示,但draw_screen每次清屏后没重新打印这行,还直接用cursor_y设置光标位置——相当于光标少算了一行,位置完全错位。
  3. 字符插入逻辑错误:现在的代码是把新字符追加到行尾,而不是插入到光标位置,这会导致编辑行为完全不符合预期,也间接影响显示。
  4. 新行未初始化:按回车时只增加了行计数,但没把新行清空,内存里的垃圾数据可能会干扰显示。

修复后的完整代码

我把所有问题都修复了,你直接跑这个版本试试:

#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <locale.h>
#include <string.h>
#include <mem.h>

#define MAX_LINES 1000
#define MAX_LINE_LEN 256

char text[MAX_LINES][MAX_LINE_LEN];
int line_count = 0;
int cursor_x = 0, cursor_y = 0;

void draw_screen() {
    system("cls");
    // 每次清屏后重新打印提示,确保屏幕顶部始终有说明
    printf("C Text Editor (ESC - quit)\n");
    for (int i = 0; i < line_count; i++) {
        printf("%s\n", text[i]);
    }
    // 确保光标位置合法,避免越界
    int current_line_len = strlen(text[cursor_y]);
    if (cursor_x > current_line_len) {
        cursor_x = current_line_len;
    }
    if (cursor_y >= line_count) {
        cursor_y = line_count - 1;
    }
    // 光标y坐标要加1,因为提示占了一行
    COORD pos = {cursor_x, cursor_y + 1};
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

void edit_loop() {
    int ch;
    while(1) {
        draw_screen();
        ch = _getch();
        if (ch == 27) break; // ESC退出
        
        // 处理方向键
        if (ch == 224) {
            ch = _getch();
            if (ch == 72 && cursor_y > 0) cursor_y--; // 上
            if (ch == 80 && cursor_y < line_count - 1) cursor_y++; // 下
            if (ch == 77 && cursor_x < strlen(text[cursor_y])) cursor_x++; // 右
            if (ch == 75 && cursor_x > 0) cursor_x--; // 左
        } 
        // 处理回车键
        else if (ch == 13) {
            if (line_count < MAX_LINES - 1) {
                memset(text[line_count], 0, MAX_LINE_LEN); // 初始化新行为空
                line_count++;
                cursor_y++;
                cursor_x = 0;
            }
        } 
        // 处理退格键
        else if (ch == 8) {
            int len = strlen(text[cursor_y]);
            if (cursor_x > 0) {
                // 删除光标前的字符,后面字符前移
                for (int i = cursor_x - 1; i < len; i++) {
                    text[cursor_y][i] = text[cursor_y][i + 1];
                }
                cursor_x--;
            } else {
                if (cursor_y != 0) {
                    int len_prev = strlen(text[cursor_y - 1]);
                    int len_curr = strlen(text[cursor_y]);
                    // 检查合并后长度是否超过限制,避免溢出
                    if (len_prev + len_curr < MAX_LINE_LEN) {
                        strcat(text[cursor_y - 1], text[cursor_y]);
                    } else {
                        // 截断当前行,只合并能放下的部分
                        strncat(text[cursor_y - 1], text[cursor_y], MAX_LINE_LEN - len_prev - 1);
                    }
                    // 清空当前行
                    text[cursor_y][0] = '\0';
                    line_count--;
                    cursor_x = strlen(text[cursor_y - 1]);
                    cursor_y--;
                }
            }
        } 
        // 处理普通字符输入(插入到光标位置)
        else {
            int len = strlen(text[cursor_y]);
            if (len < MAX_LINE_LEN - 1 && cursor_x <= len) {
                // 把光标位置及后面的字符后移一位,腾出空间
                for (int i = len; i >= cursor_x; i--) {
                    text[cursor_y][i + 1] = text[cursor_y][i];
                }
                text[cursor_y][cursor_x] = ch;
                text[cursor_y][len + 1] = '\0';
                cursor_x++;
            }
        }
    }
}

int main() {
    setlocale(LC_ALL, "Turkish");
    // 初始化所有行为空
    for (int i = 0; i < MAX_LINES; i++) {
        memset(text[i], 0, MAX_LINE_LEN);
    }
    edit_loop();
    return 0;
}

关键修复点说明

  • 字符串溢出防护:合并行时先检查长度,用strncat截断过长内容,保证字符串始终有合法的结束符。
  • 光标位置修正:把提示行加入draw_screen,光标y坐标加1,确保光标在正确的编辑区域。
  • 正确的字符插入:修改普通字符输入逻辑,实现光标位置插入,而不是追加到行尾。
  • 初始化优化:程序启动时初始化所有行,按回车时也初始化新行,避免垃圾数据干扰。

现在你再试试行首退格,上一行的内容就会正常显示出来了,编辑逻辑也更符合预期啦!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 11:50:30