Golang中Printf函数在for循环中无法正常工作的问题

Golang中Printf函数在for循环中无法正常工作的问题 我正在用Go语言编写一个Brainf**k解释器。 但我的程序中有一个奇怪的bug,我找不到原因。

func Execute(code string) {
	program, err := Compile(code)

	if program == nil {
		panic(err)
	}

	for i := 0; i < len(program); i++ {
		e := program[i]

		switch e[0] {
		case dec_ptr:
			if ptr <= 0 {
				ptr = mem_size - 1
				break
			}

			ptr--
		case inc_ptr:
			if ptr >= mem_size-1 {
				ptr = 0
				break
			}

			ptr++

		case decrease:
			if memory[ptr] <= 0 {
				memory[ptr] = 255
				break
			}

			memory[ptr]--
		case increase:
			if memory[ptr] >= 255 {
				memory[ptr] = 0
				break
			}

			memory[ptr]++

		case output:
			fmt.Printf("%s", string(memory[ptr]))
		case input:

		case loop_start:
			if memory[ptr] == 0 {
				i = e[1] - 1
			}
		case loop_end:
			if memory[ptr] != 0 {
				i = e[1] - 1
			}
		}

		// fmt.Printf("%d, %d, %d, %d, %d\n", memory[0], memory[1], memory[2], memory[3], memory[4])
	}
}

以上是我的程序中存在bug的主要函数。 当我使用 go run .go build, ./<program-name> 来运行我的程序时,它不会打印结果。 但是当我使用VS Code的调试工具来运行它时,它会打印结果。 我找不到原因!请帮帮我!

以下是我用来测试的BF代码,这个bug在其他BF代码中没有出现。

hello.bf

[-] H
++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
++++++++++ ++++++++++ ++ .
[-] e
++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++ + .
[-] l 2
>++
[<
++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++

此文件已被截断。显示原文


更多关于Golang中Printf函数在for循环中无法正常工作的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中Printf函数在for循环中无法正常工作的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题在于标准输出缓冲。fmt.Printf 在默认情况下是行缓冲的,当输出不是完整行时,内容可能不会立即刷新到终端。

在调试器中运行时,通常会强制刷新输出缓冲,所以能看到结果。但在普通执行时,输出被缓冲了,程序结束时可能没有正确刷新。

解决方案是显式刷新输出,或者使用无缓冲输出。以下是修改后的代码:

case output:
    fmt.Printf("%s", string(memory[ptr]))
    // 显式刷新标准输出
    fmt.Print()

或者使用 os.Stdout 直接写入:

case output:
    os.Stdout.Write([]byte{memory[ptr]})

完整修改示例:

import (
    "fmt"
    "os"
)

func Execute(code string) {
    program, err := Compile(code)

    if program == nil {
        panic(err)
    }

    for i := 0; i < len(program); i++ {
        e := program[i]

        switch e[0] {
        case dec_ptr:
            if ptr <= 0 {
                ptr = mem_size - 1
                break
            }

            ptr--
        case inc_ptr:
            if ptr >= mem_size-1 {
                ptr = 0
                break
            }

            ptr++

        case decrease:
            if memory[ptr] <= 0 {
                memory[ptr] = 255
                break
            }

            memory[ptr]--
        case increase:
            if memory[ptr] >= 255 {
                memory[ptr] = 0
                break
            }

            memory[ptr]++

        case output:
            // 方法1: 使用fmt.Printf并刷新
            fmt.Printf("%s", string(memory[ptr]))
            fmt.Print() // 强制刷新
            
            // 或者方法2: 直接写入os.Stdout
            // os.Stdout.Write([]byte{memory[ptr]})
        case input:

        case loop_start:
            if memory[ptr] == 0 {
                i = e[1] - 1
            }
        case loop_end:
            if memory[ptr] != 0 {
                i = e[1] - 1
            }
        }
    }
    
    // 程序结束时确保所有输出都被刷新
    os.Stdout.Sync()
}

另一个选择是在程序开始时设置无缓冲输出:

func init() {
    // 设置标准输出为无缓冲
    buf := bufio.NewWriter(os.Stdout)
    os.Stdout = &unbufferedWriter{w: buf}
}

type unbufferedWriter struct {
    w *bufio.Writer
}

func (uw *unbufferedWriter) Write(p []byte) (n int, err error) {
    n, err = uw.w.Write(p)
    uw.w.Flush()
    return n, err
}

这个问题在Brainfuck解释器中特别明显,因为Brainfuck程序通常逐个字符输出,而不是按行输出。

回到顶部