英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论