从标准输入读取行,直到遇到特定字符。

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

Read lines from stdin until certain character

问题

我正在学习Go语言。

我的程序应该从标准输入读取数据,直到我输入一行只有一个句点为止。

package main

import (
  "os"
  "fmt"
  "bufio"
)

func main(){

  in    := bufio.NewReader(os.Stdin)
  input := ""

  for input != "." {
    input, err := in.ReadString('\n')
    if err != nil {
      panic(err)
    }
  }
}

我应该如何修改我的for循环,以便在输入一个句点时停止程序?

我尝试使用for语句实现while循环,但我的方法有问题吗?条件是错误的吗?还是ReadString影响了我的数据?

英文:

I'm learning Go.

My program should read data from stdin until I enter a line with a single period.

package main

import (

  "os"
  "fmt"
  "bufio"

)

func main(){

  in    := bufio.NewReader(os.Stdin)
  input := ""

  for input != "." {
    input, err := in.ReadString('\n')
    if err != nil {
      panic(err)
    }
  }
}

How I should modify my for loop, to stop the program when I enter a single dot ?

I tried to implement a while loop with the for statement, is there something wrong with my approach, is the condition wrong, or is ReadString messing with my data ?

答案1

得分: 21

自Go 1.1以来,有一种更好的方法可以循环遍历输入的行。这是我今天解决OP问题的方式:

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        line := scanner.Text()
        if line == "." {
            break
        }
        fmt.Println(line) // 或者对line进行其他操作
    }
}

scanner.Text()会自动去除行尾的换行符。

英文:

Just in case anybody else comes across this question:

Since Go 1.1 there's a much nicer way of looping over the lines of some input available. This is how I would tackle OP's problem today:

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line := scanner.Text()
		if line == "." {
			break
		}
		fmt.Println(line) // or do something else with line
	}
}

scanner.Text() automatically strips the trailing newline.

答案2

得分: 13

...是ReadString损坏了我的数据吗?

不,它没有。它只是读取到下一个'\n'为止。这意味着只有一个点的行将具有数据".\n"".\r\n",具体取决于操作系统。

要删除行尾,我会使用input = strings.TrimRight(input, "\r\n")

英文:

>... is ReadString messing with my data?

No, it isn't. It is reading up to the next '\n'. That means that a line with only a dot on it will have the data ".\n" or ".\r\n" depending on the operating system.

To remove line endings, I would do input = strings.TrimRight(input, "\r\n")

答案3

得分: 2

使用任何bufio辅助函数的主要问题是它可能会读取超出停止字符'\n'的一些额外数据。它会读取所有可用的输入,直到缓冲区的大小。在同时访问os.Stdin的情况下,下一个读取器可能会错过在它之前由bufio读取的一些输入。下面是我非缓冲的“草稿”代码,用于概述从输入流中读取所有字符直到CR('\n')字符的并发安全方法。

package main

import "os"

// 将输入的一行回显到输出
// 你也可以在复制循环中添加退出信号
func main() {
    const BUF_SIZE = 128
    in := os.Stdin
    out := os.Stdout
    bufOut := make([]byte, BUF_SIZE)
    n := 0
    for {    // 复制循环
        // 非缓冲的逐字节读取
        if _, err := in.Read(bufOut[n : n+1]); err != nil {
            break
        }
        if bufOut[n] == 0xa || n == BUF_SIZE { // 到达CR或大小限制
            if _, err = out.Write(bufOut[0 : n+1]); err != nil {
                break
            }
            n = 0
        } else {
            n++
        }
    }
}
英文:

The main problem with using any bufio helper function is that it may read some more data beyond stop character '\n'. It reads all available input up to the size of the buffer. In case of concurrent access to os.Stdin the next reader may miss some input that was read by bufio before it. Below is my non buffered "draft" code to sketch concurrent safe method of reading from input stream all characters up to CR ('\n') char.

package main

import "os"

// echo a line in input to output
// you may add exit signal in copy loop as well
func main() {
    const BUF_SIZE = 128
	in := os.Stdin
    out := os.Stdout
	bufOut := make([]byte, BUF_SIZE)
    n := 0
	for {    // copy loop 
        // non buffered byte-by-byte
	    if _, err := in.Read(bufOut[n : n+1]); err != nil {
		    break
		}
    	if bufOut[n] == 0xa || n == BUF_SIZE { // reached CR or size limit 
    		if _, err = out.Write(bufOut[0 : n+1]); err != nil {
	    		break
		    }
			n = 0
		} else {
			n++
		}
	}
}

答案4

得分: 0

刚刚注意到主题内的问题与标题中的问题不同。
问题中初始示例的错误是在循环内重新声明了输入变量。这就是为什么您的条件检查永远不会达到退出点的原因。

英文:

Just noticed that question inside the topic is not same as in title.
The error with initial sample in question is with input variable been re declared inside the loop. That is why your condition check never gets to the exit point.

huangapple
  • 本文由 发表于 2013年1月8日 06:37:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/14205337.html
匿名

发表评论

匿名网友

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

确定