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

Linux下C语言读取TXT文件输出异常及Shell命令历史存储问题

两个问题的解决方案:Linux读TXT异常输出 + Shell命令历史存储隐患

一、Linux下C语言读取TXT文件错误输出的排查与解决

你遇到的问题大概率是换行符差异或者编码不兼容导致的,毕竟Windows和Linux的文件系统细节有区别,给你几个实用的解决思路:

1. 处理Windows换行符(\r\n)

Windows生成的TXT文件换行是\r\n,而Linux只识别\n,直接读取会在每行末尾多出一个^M字符(也就是\r)。你可以选两种方式解决:

  • 命令行转换:用dos2unix your_file.txt把文件转成Linux格式;
  • 代码内过滤:读取时自动去掉\r,示例代码如下:
#include <stdio.h>
#include <string.h>

int main() {
    FILE *fp = fopen("test.txt", "r");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }
    char buf[1024];
    while (fgets(buf, sizeof(buf), fp)) {
        // 用strcspn找到第一个\r的位置,替换为字符串结束符
        buf[strcspn(buf, "\r")] = '\0';
        printf("%s\n", buf);
    }
    fclose(fp);
    return 0;
}

2. 解决编码乱码问题

如果你的TXT是Windows下的GBK编码,Linux默认使用UTF-8,中文内容就会乱码。可以:

  • 命令行转码:iconv -f GBK -t UTF-8 input.txt > output.txt;
  • 代码内处理:用iconv库在读取时动态转码(编译时需要链接-liconv参数)。

3. 检查文件读取逻辑

确保你没有用错文件打开模式(比如用二进制模式rb读取文本文件,不过Linux下文本与二进制模式差异不大),同时用fgets的返回值判断文件结束,避免while(!feof(fp))这类容易出错的写法。


二、Shell命令历史存储的代码修复

看了你给出的addHistory代码,虽然Windows下能正常运行,但存在几个隐患,在Linux下可能会触发崩溃或逻辑错误,我帮你修正并解释问题点:

原代码的问题

  1. 满容量时逻辑不完整:else {...}中没有编写将新命令放到最后一个位置的代码;
  2. 无缓冲区溢出检查:如果输入命令长度超过100字符,strcpy会直接越界,Linux内存保护严格,会直接导致程序崩溃;
  3. 未过滤空命令:用户输入空行时也会被加入历史,属于无效数据;
  4. 多余指针赋值:tempCommand = command完全没必要,直接使用command即可。

修正后的完整代码

#define MAXHIS 20
#define MAX_CMD_LEN 100

// 全局变量必须确保初始化为0!
char commandTable[MAXHIS][MAX_CMD_LEN];
int tempHis = 0;

void addHistory(char *command) {
    // 跳过空命令或NULL指针
    if (!command || command[0] == '\0') {
        return;
    }

    // 截断过长命令,避免缓冲区溢出
    size_t cmd_len = strlen(command);
    if (cmd_len >= MAX_CMD_LEN) {
        // 手动添加字符串结束符,防止越界
        command[MAX_CMD_LEN - 1] = '\0';
    }

    if (tempHis < MAXHIS) {
        strcpy(commandTable[tempHis], command);
        tempHis++;
    } else {
        // 将所有历史命令向前移动一位
        for (int i = 0; i < MAXHIS - 1; i++) {
            strcpy(commandTable[i], commandTable[i + 1]);
        }
        // 新命令放到最后一个位置
        strcpy(commandTable[MAXHIS - 1], command);
        // tempHis保持MAXHIS不变,无需自增
    }
}

额外提醒

在Linux下编译时,一定要开启警告选项,能提前发现很多潜在问题:

gcc -Wall -Wextra your_shell.c -o your_shell

比如如果tempHis未初始化,编译器会直接给出警告,避免出现未定义行为。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:12:40