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

MIPS逐行读取文件异常:字符重复或额外换行问题求助

MIPS汇编文件读取问题修复

问题分析

你的代码存在三个核心问题:

  1. 未定义文件名常量:.data段缺少filename的字符串定义,导致文件打开操作无效,后续读取行为异常。
  2. 字符串无终止符:使用syscall 4输出字符串时,会一直读取到\0终止符,但你每次读取后没有在缓冲区末尾添加终止符,导致输出时可能包含缓冲区中残留的旧数据,出现字符重复。
  3. 未处理换行符:文本每行是8个十六进制数字+换行符(共9字节),每次只读8字节会把换行符留在文件指针位置,导致后续读取时先读换行符,输出时出现额外换行或字符截断。

修复后的代码

.data
filename: .asciiz "sample.text"  # 补充文件名定义
buffer:   .space 1024

.text
main:
    # 打开文件
    li $v0, 13
    la $a0, filename  # 修正语法(原代码缺少逗号)
    li $a1, 0         # 只读模式
    li $a2, 0
    syscall
    move $s0, $v0     # 保存文件描述符

readline:
    # 读取文件内容(每次读1字节,直到换行或EOF)
    li $v0, 14
    move $a0, $s0
    la $a1, buffer
    li $a2, 1         # 逐字节读取,方便处理换行
    syscall
    
    beq $v0, $zero, done_input  # 读取到EOF退出
    
    # 判断是否是换行符
    lb $t0, buffer
    beq $t0, '\n', print_line   # 读到换行符,输出当前行
    
    # 不是换行符,继续读取下一个字节
    j readline

print_line:
    # 在缓冲区末尾添加终止符(这里假设已经读了8个数字+换行,共9字节)
    sb $zero, buffer+9
    
    # 输出缓冲区内容
    li $v0, 4
    la $a0, buffer
    syscall
    
    j readline

done_input:
    # 关闭文件(原代码遗漏,好习惯)
    li $v0, 16
    move $a0, $s0
    syscall
    
    li $v0, 10
    syscall

关键修复点说明

  • 补充文件名定义:在.data段添加filename: .asciiz "sample.text",确保文件能正确打开。
  • 逐字节读取处理换行:改为每次读1字节,直到遇到换行符,这样能完整读取每行的8个数字+换行,避免拆分读取导致的换行混乱。
  • 添加字符串终止符:在输出前给缓冲区添加\0,确保syscall 4只输出当前行的内容,不会读取到之前的残留数据。
  • 补充文件关闭操作:使用syscall 16关闭文件,避免资源泄漏。

替代方案(固定长度读取)

如果确定每行严格是8个数字+换行(9字节),也可以直接每次读9字节,然后添加终止符输出:

readline:
    li $v0, 14
    move $a0, $s0
    la $a1, buffer
    li $a2, 9         # 读取整行(8数字+换行)
    syscall
    
    beq $v0, $zero, done_input
    
    sb $zero, buffer($v0)  # 根据实际读取字节数加终止符
    
    li $v0, 4
    la $a0, buffer
    syscall
    
    j readline

这种方式更高效,但要注意如果文件最后一行没有换行符,需要额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 16:30:44