前言
在AcWing刷题,是要自己负责数据的读取与输出,有时没选择好合适的读写方法,也会导致自己的程序TEL(超时),因此要掌握一些好的写法
基础
import "fmt"
var n int
fmt.Scanf("%d", &n) // 读, 存到n
fmt.Println(n) // 把n输出(=答案),而且自带“\n”
进阶1 bufio + os
比基础版速度快上不少,在大数值时提速效果每次明显
import (
"bufio"
"os"
"fmt"
)
var (
n int
in = bufio.NewReader(os.Stdin)
out = bufio.NewWriter(os.Stdout)
)
fmt.Fscan(in, &n) // 读, 存到n
fmt.Fprint(out, n) // 把n输出(=答案)
out.Flush() // 从缓存中读出答案
进阶2 bufio + os + strings + strconv,需要自己手搓函数
适用场景比进阶1更广的写法, 更重要的事,她能整行读
其思路是,把输入当成整行string,用strings的方法按空格分段,把每段string转成int(strconv的方法),存成数组返回
import (
"bufio"
"fmt"
"os"
"strings"
"strconv"
)
var (
scanner = bufio.NewScanner(os.Stdin)
bs := make([]byte, 20000 * 1024)
readLine = func() (res []int) { // 读整行函数
scanner.Scan()
l := strings.Split(scanner.Text(), " ")
res = make([]int, len(l))
for i, s := range l {
x, _ := strconv.Atoi(s)
res[i] = x
}
return
}
out = bufio.NewWriter(os.Stdout)
)
scanner.Buffer(bs, len(bs)) // 这句要放在main函数里
cur := readLine() // 整行输入读起来,存成数组cur
fmt.Fprint(out, cur) // 输出数组cur
out.Flush() // 从缓存中读出答案
进阶2的变种,读取整行输出整行没空格的string
当输入中是带空格,但是在解题中不能要这些空格,因此要在输入时去掉这些空格
import (
"bufio"
"fmt"
"os"
"strings"
"strconv"
)
var (
scanner = bufio.NewScanner(os.Stdin)
bs := make([]byte, 20000 * 1024)
readLine = func() (res string) { // 读整行函数
scanner.Scan()
l := strings.Split(scanner.Text(), " ")
var res string
for _, s := range l { res += s } // 去掉输入中的空格
return
}
out = bufio.NewWriter(os.Stdout)
)
scanner.Buffer(bs, len(bs)) // 这句要放在main函数里
cur := readLine() // 整行输入读起来,存成数组cur
fmt.Fprint(out, cur) // 输出数组cur
out.Flush() // 从缓存中读出答案
特殊场合:当一次输入超大时
比如这题:3302. 表达式求值
看到这里就要敲响警钟了,因为你有可能会遇到以下的变态样例(输入)
而返回的错误提示信息基本是这个:
到这里相信大家都会认真去检查代码中的数组,但其实,是输入爆了
这里只要把bufio的输入缓存设到20000 * 1024,就行了
in = bufio.NewScanner(os.Stdin)
bs = make([]byte, 20000 * 1024)
in.Buffer(bs, len(bs))
特殊场合:直接将一次(可能超长的)输入整行读取存成一个数组
关键是对readLine函数修改
readLine = func() []int {
in.Scan()
l := strings.Split(in.Text(), " ")
res := make([]int, N) // 返回数组的空间也要注意,至少别整出个动不动就越界的数组
for i, s := range l {
x, _ := strconv.Atoi(s)
res[i + 1] = x // 产生从1开始的数组
}
return res
}
特殊场合:初始化某个数组
func memset(a []int, v int) {
if len(a) == 0 {return}
a[0] = v
for i := 1; i < len(a); i *= 2 {copy(a[i:], a[:i])}
}
特殊场合:当输入的单个数字很大
import (
"fmt"
"os"
"bufio"
"strconv"
)
var in = bufio.NewWriter(os.Stdin)
var bs = make([]byte, 2000 * 1024)
func scanInt() int { // 输入函数
in.Scan()
a, _ := strconv.Atoi(in.Text())
return a
}
func main() {
in.Buffer(bs, len(bs))
n := scanInt() // 输入
}
特殊场合:当题目有多次输入时
当题目有多次输入时,使用readLine时最好每次使用不一样的变量名。
示例:1488. 最短距离