A Tour of Go の Exercise を実施したときのメモ。
- rot13 のルールどおり素直にコーディング
- アルファベット以外は変換しないので、別のバッファ(
cc
)を用意して詰め直すのは非効率かも
exercise-rot-reader.go
package main
import (
"io"
"os"
"strings"
)
type rot13Reader struct {
r io.Reader
}
func (r *rot13Reader) Read(b []byte) (int, error) {
cc := make([]byte, len(b))
n, err := r.r.Read(cc)
for i := 0; i < n; i++ {
c := cc[i]
switch {
case 'A' <= c && c <= 'M':
c += 13
case 'a' <= c && c <= 'm':
c += 13
case 'N' <= c && c <= 'Z':
c -= 13
case 'n' <= c && c <= 'z':
c -= 13
default:
}
b[i] = c
}
return n, err
}
func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}
- 最初は以下のように実装していた。
- だが、これでは Read の引数
b []byte
のサイズを越えて代入してしまうのでNG - それに、1バイトずつ読むのは非効率かな
exercise-rot-reader.go
func (r *rot13Reader) Read(b []byte) (int, error) {
cc := make([]byte, 1)
i := 0
var err error = nil
for {
_, err = r.r.Read(cc)
if err == io.EOF {
break
}
c := cc[0]
switch {
case 'A' <= c && c <= 'M':
c += 13
case 'a' <= c && c <= 'm':
c += 13
case 'N' <= c && c <= 'Z':
c -= 13
case 'n' <= c && c <= 'z':
c -= 13
default:
}
b[i] = c
i++
}
return i, err
}