使用GO编写C程序,但C程序在scanf()处无法停止。

huangapple go评论86阅读模式
英文:

Writing to C program using GO but C program doesn't stop at scanf()

问题

在这些代码片段中,Go程序试图向C程序的stdin写入数据。问题在于,当Go循环结束后,C程序会启动一个无限循环。

main.c

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

int main(){
    int age;
    char name[8]; 

    for(;;)
    {
    scanf(" %s : %d\n",&name, &age);
    printf("%s : %d\n",name, age);
    }
    return 0;
}

run/main.go

func main() {

    proc := exec.Command("../main")
    stdin, err := proc.StdinPipe()
    if err != nil {
        fmt.Println(err) 
    }

    defer stdin.Close()

    proc.Stdout = os.Stdout
    proc.Stderr = os.Stderr

    fmt.Println("START")                      
    if err = proc.Start(); err != nil { 
        log.Fatal("An error occured: ", err)
    }

    for i := 0; i < 500; i++ {
        io.WriteString(stdin, fmt.Sprintf("hello : %d\n", i))
        //如何在这里等待并读取printf()的输出?
    }

    //proc.Process.Kill() 在这里杀死proc会太快

    fmt.Println("END")
}

当被杀死时,进程无法完成其输出。

输出

START
END
hello : 497
hello : 498
hello : 499
hello : 499 

期望输出

START
....
hello : 497
hello : 498
hello : 499
END
英文:

In these snippets the go program tries to write to C program's stdin. The problem is that the c program starts an infinite loop after the go loop finishes.

main.c

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;


int main(){
    int age;
    char name[8]; 

    for(;;)
    {
    scanf(&quot; %s : %d\n&quot;,&amp;name, &amp;age);
    printf(&quot;%s : %d\n&quot;,name, age);
    }
    return 0;
}

run/main.go

func main() {

    proc := exec.Command(&quot;../main&quot;)
	stdin, err := proc.StdinPipe()
	if err != nil {
		fmt.Println(err) 
	}

	defer stdin.Close()

	proc.Stdout = os.Stdout
	proc.Stderr = os.Stderr

	fmt.Println(&quot;START&quot;)                      
	if err = proc.Start(); err != nil { 
		log.Fatal(&quot;An error occured: &quot;, err)
	}

	for i := 0; i &lt; 500; i++ {
		io.WriteString(stdin, fmt.Sprintf(&quot;hello : %d\n&quot;, i))
        //How to wait here and read from printf()?
	}

	//proc.Process.Kill() Here proc gets killed too fast

	fmt.Println(&quot;END&quot;)
}

When killed, process doesn't complete it's output

Output

START
END
hello : 497
hello : 498
hello : 499
hello : 499 

Output Expected

START
....
hello : 497
hello : 498
hello : 499
END

答案1

得分: 0

在阅读了评论并进行了更多搜索后,我解决了问题。

在C程序中,我从scanf()中删除了\n,并在printf之后添加了fflush(stdout)。

根据这个页面,我将它们更改为以下内容:

int main(){
    int age;
    char name[8]; 

    int ret;

    for(;;)
    {
    ret= scanf("%s : %d",&name, &age);
    if (ret == -1) {
        break;
    }
    printf("%s : %d\n",name, age);

    fflush(stdout);
    }
    
    return 0;
}
func main(){
	proc := exec.Command("../main")

	stdin, err := proc.StdinPipe()
	if err != nil {
		fmt.Println(err)
	}

	reader, err := proc.StdoutPipe()
	if err != nil {
		fmt.Println(err)
		return
	}

	scanner := bufio.NewScanner(reader)
	resp := make(chan string)

	go func() {
		for scanner.Scan() {
			resp <- scanner.Text()
		}
	}()

	err = proc.Start()
	if err != nil {
		fmt.Fprintln(err)
		return
	}
	fmt.Println("START")

	for i := 0; i < 500; i++ {
		io.WriteString(stdin, fmt.Sprintf("hello : %d\n", i))

		v := <-resp
		print(v+"\n")

	}

	err = proc.Process.Kill()

	if err != nil {
		fmt.Fprintln(err)
		return
	}
	fmt.Println("END")

}
英文:

After reading the comments and few more searching I have worked it out.
On C program I removed \n from scanf() and added fflush(stdout) after printf.
According to this page I changed them to these:

int main(){
    int age;
    char name[8]; 

    int ret;

    for(;;)
    {
    ret= scanf(&quot;%s : %d&quot;,&amp;name, &amp;age);
    if (ret == -1) {
        break;
    }
    printf(&quot;%s : %d\n&quot;,name, age);

    fflush(stdout);
    }
    
    return 0;
}
func main(){
	proc := exec.Command(&quot;../main&quot;)

	stdin, err := proc.StdinPipe()
	if err != nil {
		fmt.Println(err)
	}

	reader, err := proc.StdoutPipe()
	if err != nil {
		fmt.Println(err)
		return
	}

	scanner := bufio.NewScanner(reader)
	resp := make(chan string)

	go func() {
		for scanner.Scan() {
			resp &lt;- scanner.Text()
		}
	}()

	err = proc.Start()
	if err != nil {
		fmt.Fprintln(err)
		return
	}
	fmt.Println(&quot;START&quot;)

	for i := 0; i &lt; 500; i++ {
		io.WriteString(stdin, fmt.Sprintf(&quot;hello : %d\n&quot;, i))

		v := &lt;-resp
		print(v+&quot;\n&quot;)

	}

	err = proc.Process.Kill()

	if err != nil {
		fmt.Fprintln(err)
		return
	}
	fmt.Println(&quot;END&quot;)

}

huangapple
  • 本文由 发表于 2022年2月10日 03:34:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/71055681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定