1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
)
// Student struct for student info
type Student struct {
ID int `json:"id"`
Name string `json:"name"`
}
var students = make(map[string]Student)
func main() {
var line, cmd, name string
var id int
saved := true
f := bufio.NewReader(os.Stdin)
for {
fmt.Print("> ")
line, _ = f.ReadString('\n')
line = strings.Replace(line, "\n", "", 1)
_, err := fmt.Sscan(line, &cmd, &name, &id)
// EOF for no enough space-separated values, like `list` cmd
if err != nil && err != io.EOF {
fmt.Println(" + parse cmd or info err:", err)
continue
}
switch cmd {
case "add":
if addStu(name, id) {
saved = false
}
case "list":
listStu()
case "load":
if loadStu(name, saved) {
saved = true
}
case "save":
if saveStu(name) {
saved = true
}
case "exit":
exitStu(saved)
case "":
// no show usage() when ENTER
continue
default:
usage()
}
line, cmd, name = "", "", ""
}
}
func exitStu(s bool) {
if s || checkYes("exit with saving stu info") {
os.Exit(0)
}
return
}
func saveStu(name string) (rt bool) {
var err error
var fd *os.File
// file existed and override
if checkFileExist(name) {
if !checkYes(fmt.Sprintf("override file %s", name)) {
fmt.Println(" + cancel save to", name)
return
}
if fd, err = os.OpenFile(name, os.O_RDWR|os.O_TRUNC, 0644); err != nil {
fmt.Printf(" + open file error of %s\n", name)
return
}
defer fd.Close()
}
// save to new file
if fd, err = os.Create(name); err != nil {
fmt.Printf(" + open new file error of %s\n", name)
return
}
defer fd.Close()
if buf, err := json.Marshal(students); err != nil {
fmt.Println(" + marshal stu info error")
return
} else if _, err := fd.Write(buf); err == nil {
fmt.Println(" + save success")
return true
} else {
fmt.Println(" + save error")
return
}
}
// check file f exist or not
func checkFileExist(f string) bool {
if _, err := os.Stat(f); err == nil {
return true
} else if os.IsNotExist(err) {
return false
}
return false
}
// check yes or no for the give question
func checkYes(f string) bool {
var s string
for {
fmt.Printf(" + %s, y or n? :", f)
fmt.Scanf("%s", &s)
if string(s[0]) == "y" || string(s[0]) == "Y" {
return true
} else if string(s[0]) == "n" || string(s[0]) == "N" {
return false
}
}
}
func loadStu(name string, saved bool) (rt bool) {
var err error
var buf []byte
if !checkFileExist(name) {
fmt.Printf(" + file : %s not existed!\n", name)
return
}
if !saved && !checkYes("clear up stu info in mem for load") {
fmt.Println(" + give up load!")
return
}
if buf, err = ioutil.ReadFile(name); err != nil {
fmt.Printf("read from file error of %s\n", name)
return
}
if err = json.Unmarshal(buf, &students); err != nil {
fmt.Print(err)
return
}
fmt.Println(" + load success")
return true
}
func addStu(name string, id int) (rt bool) {
if _, ok := students[name]; ok {
fmt.Printf(" + duplicated name: %s\n", name)
return
}
students[name] = Student{ID: id, Name: name}
if _, ok := students[name]; ok {
fmt.Println(" + add success!")
return true
}
return
}
func listStu() {
if len(students) == 0 {
fmt.Println(" + no student info here")
return
}
fmt.Println(" + Id\tName:")
for _, val := range students {
fmt.Printf(" + %d\t%s\n", val.ID, val.Name)
}
}
func usage() {
fmt.Println(" + cli usage:")
fmt.Println(" + add name id -- add student info")
fmt.Println(" + list \t-- list student info")
fmt.Println(" + load file \t-- load student from file")
fmt.Println(" + save file \t-- save student info file")
fmt.Println(" + exit \t-- exit the cli")
}
|