Goの学習でA Tour of Goをさらっています。
Methods and interfacesの章でExercise: rot13Readerをやったのでメモです。
解答
やったこと
やったことは下記です
- 状況把握
- Readメソッドの返り値とReadメソッド中で変換するための文字列を取得する
- Readメソッド内でROT13の処理をする
1. 状況把握
"Lbh penpxrq gur pbqr!"をROT13という変換方法を利用して文字列変換したものを出力する。
初期状態として下記が与えられている。このまま実行するとrot13Readerにio.Reader(Readメソッド)がないと言われます。
package main
import (
"io"
"os"
"strings"
)
type rot13Reader struct {
r io.Reader
}
func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r) // ここで標準出力するためにrot13ReaderにReadメソッドを追加する
}
2. Readメソッドの返り値とReadメソッド中で変換するための文字列を取得する
返り値の文字数、errorは、rot13Readerの構造体中のio.ReaderのReadメソッドの返り値をそのまま利用すればいい。
また、rot13Readerの構造体中のio.ReaderのReadメソッドを呼び出した際に、byte配列bにLbh penpxrq gur pbqr!
を入れてくれている。
func (r rot13Reader) Read(b []byte) (int, error) {
n, err := r.r.Read(b) // ここで、rot13Readerの構造体中のio.Readerを利用し、返り値と文字列をゲットする
if err != nil {
return n, err // n, errをそのまま返せる
}
...
return n, nil // nをそのまま返せる
}
3. Readメソッド内でROT13の処理をする
やり方は色々あると思いますが、
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
を
NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm
に変換できればok
大文字と小文字に分けて13個ローテーションさせました。
func (r rot13Reader) Read(b []byte) (int, error) {
n, err := r.r.Read(b)
if err != nil {
return n, err
}
// bに入れていく
for i := 0; i < len(b); i++ {
if b[i] >= 'A' && b[i] <= 'Z' {
b[i] = (b[i]-'A'+13)%26 + 'A' // 大文字の場合、13個ローテーションする
} else if b[i] >= 'a' && b[i] <= 'z' {
b[i] = (b[i]-'a'+13)%26 + 'a' // 小文字の場合、13個ローテーションする
}
}
return n, nil
}