diff --git a/od/main.go b/od/main.go index b12ac02..8439c8d 100644 --- a/od/main.go +++ b/od/main.go @@ -33,7 +33,6 @@ func parse_opts() (Opts) { if flag.NArg() == 0 { log.Fatal("USAGE: od [files]") - os.Exit(1) } if opts.Hex { diff --git a/wc/.gitignore b/wc/.gitignore new file mode 100644 index 0000000..61df787 --- /dev/null +++ b/wc/.gitignore @@ -0,0 +1,2 @@ +wc.exe +wc diff --git a/wc/Makefile b/wc/Makefile new file mode 100644 index 0000000..bea7546 --- /dev/null +++ b/wc/Makefile @@ -0,0 +1,4 @@ + + +build: + go build . diff --git a/wc/go.mod b/wc/go.mod new file mode 100644 index 0000000..664529c --- /dev/null +++ b/wc/go.mod @@ -0,0 +1,3 @@ +module MY/wc + +go 1.24.2 diff --git a/wc/main.go b/wc/main.go new file mode 100644 index 0000000..732a01b --- /dev/null +++ b/wc/main.go @@ -0,0 +1,113 @@ +package main + +import ( + "fmt" + "os" + "log" + "flag" + "bufio" + "strings" + "unicode/utf8" +) + +type Opts struct { + Bytes bool + Chars bool + Words bool + Lines bool +} + +type Counts struct { + Bytes int + Chars int + Words int + Lines int + Filename string +} + + +func parse_opts() (Opts, []string) { + var opts Opts + + flag.BoolVar(&opts.Bytes, "c", false, "Count bytes") + flag.BoolVar(&opts.Chars, "m", false, "Count chars") + flag.BoolVar(&opts.Words, "w", false, "Count words") + flag.BoolVar(&opts.Lines, "l", false, "Count lines") + + flag.Parse() + + if flag.NArg() == 0 { + log.Fatal("USAGE: wc [-l] [-w] [-m] [-c] ") + } + + if !opts.Bytes && !opts.Chars && !opts.Words && !opts.Lines { + opts.Lines = true + } + + return opts, flag.Args() +} + + +func count_file(opts *Opts, filename string) Counts { + var counts Counts + + in_file, err := os.Open(filename) + if err != nil { log.Fatal(err) } + defer in_file.Close() + + scan := bufio.NewScanner(in_file) + for scan.Scan() { + line := scan.Text() + + if opts.Lines { + counts.Lines++ + } + + if opts.Words { + counts.Words += len(strings.Fields(line)) + } + + if opts.Chars { + counts.Chars += utf8.RuneCountInString(line) + 1 + } + + if opts.Bytes { + counts.Bytes += len(line) + 1 + } + } + + if scan.Err() != nil { + log.Fatal(scan.Err()) + } + + return counts +} + +func print_count(opts *Opts, count *Counts, file string) { + if opts.Lines { + fmt.Print(count.Lines, " ") + } + + if opts.Words { + fmt.Print(count.Words, " ") + } + + if opts.Chars { + fmt.Print(count.Chars, " ") + } + + if opts.Bytes { + fmt.Print(count.Bytes, " ") + } + + fmt.Println(" ", file) +} + +func main() { + opts, files := parse_opts() + + for _, file := range files { + count := count_file(&opts, file) + print_count(&opts, &count, file) + } +}