Rot13 Reader – avec solutions
Un utilisation courante d’un io.Reader et d’enveloper autre io.Reader, et qui modifie le flux d’une certaine manière.
Par exemple, la fonction gzip.NewReader prend un io.Reader (un flux de données compressées) en paramètre et retourne un *gzip.Reader qui implémente également un io.Reader (un flux de données décompressées).
Implémentez rot13Reader qui implémente io.Reader et lit à partir d’un io.Reader, modifiant
le flux en appliquant le chiffrement de substitution rot13
à tous les caractères alphabétiques.
Le type rot13Reader est déjà donné dans le code ci-dessous. Faites-en un io.Reader en implémentant sa méthode 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)
}
Solution
package main
import (
"io"
"os"
"strings"
)
const (
alphabetLength = 'Z' - 'A' + 1
)
type rot13Reader struct {
r io.Reader
}
func rot13(b byte) byte {
// The function is called "rot13", so I assume that it is OK to hardcode the
// rotation to 13 without defining a constant for it.
switch {
case b >= 'A' && b <= 'Z':
b = (b-'A'+13)%alphabetLength + 'A'
case b >= 'a' && b <= 'z':
b = (b-'a'+13)%alphabetLength + 'a'
}
return b
}
func (r rot13Reader) Read(b []byte) (int, error) {
// We use the buffer `b` to read the data from the underlying reader
// and then we modify the data in place.
n, err := r.r.Read(b)
for i := 0; i < n; i++ {
b[i] = rot13(b[i])
}
return n, err
}
func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}