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

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

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

问题

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

main.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(){
  4. int age;
  5. char name[8];
  6. for(;;)
  7. {
  8. scanf(" %s : %d\n",&name, &age);
  9. printf("%s : %d\n",name, age);
  10. }
  11. return 0;
  12. }

run/main.go

  1. func main() {
  2. proc := exec.Command("../main")
  3. stdin, err := proc.StdinPipe()
  4. if err != nil {
  5. fmt.Println(err)
  6. }
  7. defer stdin.Close()
  8. proc.Stdout = os.Stdout
  9. proc.Stderr = os.Stderr
  10. fmt.Println("START")
  11. if err = proc.Start(); err != nil {
  12. log.Fatal("An error occured: ", err)
  13. }
  14. for i := 0; i < 500; i++ {
  15. io.WriteString(stdin, fmt.Sprintf("hello : %d\n", i))
  16. //如何在这里等待并读取printf()的输出?
  17. }
  18. //proc.Process.Kill() 在这里杀死proc会太快
  19. fmt.Println("END")
  20. }

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

输出

  1. START
  2. END
  3. hello : 497
  4. hello : 498
  5. hello : 499
  6. hello : 499

期望输出

  1. START
  2. ....
  3. hello : 497
  4. hello : 498
  5. hello : 499
  6. 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

  1. #include &lt;stdio.h&gt;
  2. #include &lt;stdlib.h&gt;
  3. int main(){
  4. int age;
  5. char name[8];
  6. for(;;)
  7. {
  8. scanf(&quot; %s : %d\n&quot;,&amp;name, &amp;age);
  9. printf(&quot;%s : %d\n&quot;,name, age);
  10. }
  11. return 0;
  12. }

run/main.go

  1. func main() {
  2. proc := exec.Command(&quot;../main&quot;)
  3. stdin, err := proc.StdinPipe()
  4. if err != nil {
  5. fmt.Println(err)
  6. }
  7. defer stdin.Close()
  8. proc.Stdout = os.Stdout
  9. proc.Stderr = os.Stderr
  10. fmt.Println(&quot;START&quot;)
  11. if err = proc.Start(); err != nil {
  12. log.Fatal(&quot;An error occured: &quot;, err)
  13. }
  14. for i := 0; i &lt; 500; i++ {
  15. io.WriteString(stdin, fmt.Sprintf(&quot;hello : %d\n&quot;, i))
  16. //How to wait here and read from printf()?
  17. }
  18. //proc.Process.Kill() Here proc gets killed too fast
  19. fmt.Println(&quot;END&quot;)
  20. }

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

Output

  1. START
  2. END
  3. hello : 497
  4. hello : 498
  5. hello : 499
  6. hello : 499

Output Expected

  1. START
  2. ....
  3. hello : 497
  4. hello : 498
  5. hello : 499
  6. END

答案1

得分: 0

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

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

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

  1. int main(){
  2. int age;
  3. char name[8];
  4. int ret;
  5. for(;;)
  6. {
  7. ret= scanf("%s : %d",&name, &age);
  8. if (ret == -1) {
  9. break;
  10. }
  11. printf("%s : %d\n",name, age);
  12. fflush(stdout);
  13. }
  14. return 0;
  15. }
  1. func main(){
  2. proc := exec.Command("../main")
  3. stdin, err := proc.StdinPipe()
  4. if err != nil {
  5. fmt.Println(err)
  6. }
  7. reader, err := proc.StdoutPipe()
  8. if err != nil {
  9. fmt.Println(err)
  10. return
  11. }
  12. scanner := bufio.NewScanner(reader)
  13. resp := make(chan string)
  14. go func() {
  15. for scanner.Scan() {
  16. resp <- scanner.Text()
  17. }
  18. }()
  19. err = proc.Start()
  20. if err != nil {
  21. fmt.Fprintln(err)
  22. return
  23. }
  24. fmt.Println("START")
  25. for i := 0; i < 500; i++ {
  26. io.WriteString(stdin, fmt.Sprintf("hello : %d\n", i))
  27. v := <-resp
  28. print(v+"\n")
  29. }
  30. err = proc.Process.Kill()
  31. if err != nil {
  32. fmt.Fprintln(err)
  33. return
  34. }
  35. fmt.Println("END")
  36. }
英文:

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:

  1. int main(){
  2. int age;
  3. char name[8];
  4. int ret;
  5. for(;;)
  6. {
  7. ret= scanf(&quot;%s : %d&quot;,&amp;name, &amp;age);
  8. if (ret == -1) {
  9. break;
  10. }
  11. printf(&quot;%s : %d\n&quot;,name, age);
  12. fflush(stdout);
  13. }
  14. return 0;
  15. }
  1. func main(){
  2. proc := exec.Command(&quot;../main&quot;)
  3. stdin, err := proc.StdinPipe()
  4. if err != nil {
  5. fmt.Println(err)
  6. }
  7. reader, err := proc.StdoutPipe()
  8. if err != nil {
  9. fmt.Println(err)
  10. return
  11. }
  12. scanner := bufio.NewScanner(reader)
  13. resp := make(chan string)
  14. go func() {
  15. for scanner.Scan() {
  16. resp &lt;- scanner.Text()
  17. }
  18. }()
  19. err = proc.Start()
  20. if err != nil {
  21. fmt.Fprintln(err)
  22. return
  23. }
  24. fmt.Println(&quot;START&quot;)
  25. for i := 0; i &lt; 500; i++ {
  26. io.WriteString(stdin, fmt.Sprintf(&quot;hello : %d\n&quot;, i))
  27. v := &lt;-resp
  28. print(v+&quot;\n&quot;)
  29. }
  30. err = proc.Process.Kill()
  31. if err != nil {
  32. fmt.Fprintln(err)
  33. return
  34. }
  35. fmt.Println(&quot;END&quot;)
  36. }

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:

确定