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

用C语言模拟Linux xxd命令:最后一行空格格式问题求助

解决C语言模拟xxd命令的最后一行空格格式问题

我已基本完成用C语言模拟Linux xxd命令的开发,但始终无法正确设置最后一行的空格格式。目前已处理了十六进制数字的空格,但无法计算出所需的其他空格。

原实现代码

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

const int MAX_CHAR = 16;

int main(int argc, char *argv[])
{
    //command line argument for filename
    char *fileName = argv[1];
    
    //open file and check for validity
    FILE *file = fopen(fileName, "r");
    if (file == NULL)
    {
        printf("The file was not opened correctly\n");
        return -1;
    }

    
    char line[MAX_CHAR];   //array to store characters
    int lineCount = 0;     //counter for hexadecimal line display
    int charCount = 0;     //counter for spacing of hex ascii values
    int breakIndex = MAX_CHAR;  //integer to save what index the array is stopped at EOF
    
    //cycle through every 16 characters
    while(!feof(file)) 
    {
        //read 16 characters
        for(int i = 0; i<breakIndex ; i++)
        {
            
            line[i]=fgetc(file);
            if (feof(file))
            {
                breakIndex = i;
                line[i]='\0';
                break;
            }
        }
       
        //print line count in hexadecimal
        printf("%.08x: ",lineCount);
        
        //print hexadecimal for each character
        for(int i = 0; i<breakIndex; i++)
        {
            printf("%.02x",line[i]);
            charCount++;
            if(charCount % 2 == 0)
            {
                printf(" ");
            }
        }

        //spaces for formatting output
        if(breakIndex == MAX_CHAR)
        {
            printf(" ");
        }
        else
        {
            int spaces = (MAX_CHAR - breakIndex) * 2 ;
            //printf("----%d-----",spaces);
            for(int i = 0 ; i< spaces ; i++)    
            {
                printf(" ");
            }
        }
        
        //print actual characters
        for(int i = 0; i<breakIndex ; i++)
        {
            if(!isprint(line[i]))
            {
                line[i]= '.';
            }
        }
        line[16] = '\0';
        printf("%s",line);
        printf("\n");

        //increment line count
        lineCount+=16;
    }

    //close file
    fclose(file);
    return 0;
}

问题分析

原代码的空格计算逻辑存在两个核心问题:

  • 未重置charCount:每次处理新行时,charCount保留上一行的计数,导致后续行的组空格逻辑完全混乱。
  • 空格计算不完整:仅考虑了少输出的十六进制位数,忽略了xxd格式中每个字节间的空格、前8字节与后8字节的分隔空格,以及满行末尾的对齐空格。

标准xxd的格式规则:

  • 每行16字节,每个字节输出两位十六进制,字节间加空格;
  • 前8字节结束后额外加一个空格分隔前后段;
  • 十六进制部分结束后加一个空格,再输出字符部分。

修正后的代码

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

const int MAX_CHAR = 16;

int main(int argc, char *argv[])
{
    if (argc < 2) {
        printf("Usage: %s <filename>\n", argv[0]);
        return -1;
    }

    char *fileName = argv[1];
    FILE *file = fopen(fileName, "rb");  // 二进制模式打开,避免换行符转换
    if (file == NULL)
    {
        printf("The file was not opened correctly\n");
        return -1;
    }

    unsigned char line[MAX_CHAR];  // 用unsigned char避免符号扩展问题
    int lineCount = 0;
    int bytesRead;

    while ((bytesRead = fread(line, 1, MAX_CHAR, file)) > 0)
    {
        // 输出行地址
        printf("%.08x: ", lineCount);

        // 输出十六进制部分
        for (int i = 0; i < bytesRead; i++)
        {
            printf("%.02x", line[i]);
            // 字节间加空格,最后一个字节除外
            if (i != bytesRead - 1) {
                printf(" ");
            }
            // 前8字节结束后加额外分隔空格
            if (i == 7 && bytesRead > 8) {
                printf(" ");
            }
        }

        // 计算需要补充的空格数,对齐到满行格式
        int printedLength = 0;
        if (bytesRead <= 8) {
            printedLength = bytesRead * 3;  // 每个字节占3字符:xx + 空格
        } else {
            // 前8字节长度 + 分隔空格 + 剩余字节长度
            printedLength = 8*3 + 2 + (bytesRead - 8)*3;
        }
        // 满行时冒号后到字符前的总长度为50,计算差值补空格
        int spacesNeeded = 50 - printedLength;
        for (int i = 0; i < spacesNeeded; i++) {
            printf(" ");
        }

        // 输出字符部分
        for (int i = 0; i < bytesRead; i++) {
            printf("%c", isprint(line[i]) ? line[i] : '.');
        }
        printf("\n");

        lineCount += bytesRead;
    }

    fclose(file);
    return 0;
}

关键修正点

  1. 二进制模式打开文件:避免Windows环境下换行符被自动转换,保证读取字节的准确性。
  2. 使用unsigned char存储字节:防止带符号字节的符号扩展导致十六进制输出错误。
  3. 重构空格输出逻辑:按行内字节数直接控制空格,去掉全局计数,避免累积错误。
  4. 准确计算对齐空格:根据已输出的十六进制内容长度,补空格到满行的标准格式长度,确保最后一行与其他行对齐。
  5. 修复行地址递增:按实际读取的字节数递增行地址,适配文件大小不是16倍数的场景。

内容的提问来源于stack exchange,提问作者s k y l i n e

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:54:51