CodeBlanks Logo Icon CodeBlanks

Meydan okuma 4 - CLI aracı

flag ile dosya işleyen bir CLI aracı yazarsın.

Meydan okuma: satır sayma aracı

Unix wc benzeri bir CLI aracı yazacaksın. Kurallar: -l verilirse yalnızca satır sayısını, verilmezse satır, kelime ve bayt sayısını yazdırır. Girdi stdin'den okunur; test edilebilmesi için tüm mantık run(args, in, out) fonksiyonunda olur.

printf "a b\nc\n" | ./say       # 2 3 6
printf "a b\nc\n" | ./say -l    # 2

Plan

1) FlagSet ile -l bool seçeneği. 2) veri, err := io.ReadAll(in). 3) Satır: bytes.Count(veri, []byte("\n")); kelime: len(strings.Fields(string(veri))); bayt: len(veri). 4) -l ise yalnızca satırı, değilse üçünü fmt.Fprintln(out, ...) ile yaz. 5) main'de hata olursa stderr'e yazıp os.Exit(1).

Uygulama Aracı yaz

Planı uygula. main içinde run(nil, strings.NewReader("a b\nc\n"), os.Stdout) ve run([]string{"-l"}, strings.NewReader("a b\nc\n"), os.Stdout) çağır.

Başlangıç kodu

main.go
package main

import (
    "bytes"
    "flag"
    "fmt"
    "io"
    "os"
    "strings"
)

func main() {
    // buraya yaz
}

Örnek çözüm

main.go
package main

import (
    "bytes"
    "flag"
    "fmt"
    "io"
    "os"
    "strings"
)

func run(args []string, in io.Reader, out io.Writer) error {
    fs := flag.NewFlagSet("say", flag.ContinueOnError)
    l := fs.Bool("l", false, "yalnızca satır sayısı")
    if err := fs.Parse(args); err != nil {
        return err
    }
    veri, err := io.ReadAll(in)
    if err != nil {
        return err
    }
    lines := bytes.Count(veri, []byte("\n"))
    if *l {
        _, err = fmt.Fprintln(out, lines)
        return err
    }
    _, err = fmt.Fprintln(out, lines, len(strings.Fields(string(veri))), len(veri))
    return err
}

func main() {
    for _, a := range [][]string{nil, {"-l"}} {
        if err := run(a, strings.NewReader("a b\nc\n"), os.Stdout); err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }
    }
}

Beklenen çıktı

2 3 6
2

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Bayt sayısını en doğru hangisiyle bulursun?

  • utf8.RuneCount
  • Girdinin tamamını okuyup len(veri) Doğru cevap
  • Satır uzunluklarını toplamak
  • Kelime sayısı × 5

Açıklama: Scanner satır sonlarını atar; satır uzunluklarını toplamak \n baytlarını kaçırır. RuneCount ise karakter sayar, bayt değil.

2 Satırları say

Soru
lines := bytes.____(veri, []byte("
"))
Cevap
lines := bytes.Count(veri, []byte("
"))

Açıklama: bytes.Count bir alt dizinin kaç kez geçtiğini sayar; satır sonu sayısı satır sayısıdır.

3 Ölçüm ve yöntem

Kavram Anlamı
Satır bytes.Count(\n)
Kelime strings.Fields
Bayt len(veri)
Karakter utf8.RuneCount

Orta seviye bölümündeki tüm dersler