Go语言Learntris挑战:Scanner读取stdin遇空数组问题求助
解决Go中Scanner读取Learntris网格内容为空的问题
我之前做Learntris入门项目的时候也踩过这个Scanner的坑!你遇到的空数组问题,大概率是Scanner的换行符处理或者分割模式用错了,尤其是单字符命令和多行内容衔接的地方容易出问题。
先给你拆解下常见的错误原因和对应的解决办法:
最可能的问题:错误使用了字符分割模式
很多人为了读取单个字符命令,会把Scanner的分割方式改成bufio.ScanRunes,但这样会把换行符也当作一个独立的字符来读取。比如输入是:
g
line1
line2
...
当你用ScanRunes读取到'g'后,下一次Scan()会读取到换行符(\n),这时候你开始循环读22行,第一行就会是空字符串,后续如果输入不足22行,还会出现更多空元素,最终看起来像是得到了空数组。
解决办法:放弃ScanRunes,用Scanner默认的ScanLines分割模式(也就是不修改Split)。因为Learntris的输入本来就是换行分隔的,每个命令单独占一行,'g'命令本身就是一行完整的输入,直接读取整行判断是否为"g"就可以了。
正确的代码实现示例
package main import ( "bufio" "fmt" "os" ) func main() { scanner := bufio.NewScanner(os.Stdin) // 循环处理每行命令 for scanner.Scan() { cmd := scanner.Text() switch cmd { case "g": grid := make([]string, 0, 22) // 读取22行网格内容 for i := 0; i < 22; i++ { // 必须检查Scan的返回值,避免EOF或IO错误导致空内容 if !scanner.Scan() { fmt.Printf("警告:网格内容不足22行,仅读取到%d行\n", len(grid)) break } grid = append(grid, scanner.Text()) } // 验证读取结果 fmt.Printf("成功读取%d行网格内容:\n", len(grid)) for idx, line := range grid { fmt.Printf("%d: %s\n", idx+1, line) } // 处理其他命令,比如'q'退出之类的 case "q": fmt.Println("退出程序") return default: fmt.Printf("未知命令:%s\n", cmd) } } // 处理Scanner的错误 if err := scanner.Err(); err != nil { fmt.Fprintf(os.Stderr, "读取输入时出错:%v\n", err) } }
关键注意点
- 必须检查
Scan()的返回值:如果Scan()返回false,说明已经到达EOF或者发生了IO错误,这时候Text()会返回空字符串,一定要提前处理,避免把空值塞进数组。 - 不要手动处理换行符:默认的
ScanLines会自动去掉每行末尾的换行符(包括\n和\r\n),直接用Text()就能得到干净的行内容。 - 提前预分配数组容量:用
make([]string, 0, 22)可以避免数组扩容的性能损耗,虽然对于22行来说影响不大,但这是Go的最佳实践。
如果你之前确实用了ScanRunes,也可以在读取到'g'后,额外调用一次Scan()来跳过换行符,再读取22行,但这种方式不如默认的行分割模式直观,容易踩坑,所以更推荐用上面的方法。
内容的提问来源于stack exchange,提问作者paumanok
相关产品推荐
相关产品推荐

