服務計算--使用 golang 開發 開發 Linux 命令列實用程式 中的 selpg作業3
本次實驗的內容是使用 golang 開發 selpg
程式設計
輸入指令的格式應該是selpg --s start_page --e end_page [--f | --l lines_per_page] [ --d print_dest] [file_name]
引數 | 要求 | 意義 |
---|---|---|
–s | 必需 | 起始頁 |
–e | 必需 | 結束頁 |
–f | 可選 | 根據分頁符翻頁 |
–l | 可選 | 根據行數翻頁,每頁的行數 |
–d | 可選 | 印表機地址 |
file_name | 必需 | 檔案路徑 |
備註:--f
和--l
是互斥的,如果同時出現將會報錯
根據上述情況,很容易想到利用一個結構體儲存所有內容:
type selpg_parm struct {
start_page int //開始頁數
end_page int //結束頁數
lines_per_page int //每頁行數
delimited_type string // 'l' for lines-delimited, 'f' for form-feed-delimited default is 'l'
print_dest string //印表機裝置
file_name string //輸入途徑,預設為鍵盤輸入
}
selpg的過程分三步走:結構體初始化(輸入)、檢查輸入、操作並輸出。也就是採取以下模式:
func main() {
inti()
check(pflag.NArg())
operation()
}
接下來是具體的實現過程
程式實現
一、結構體初始化(輸入)
首先要做的是將使用者的輸入,根據不同的引數,賦值到結構體中
var parm selpg_parm
var f_flag *bool
//繫結變數
pflag.IntVar(&parm.start_page, "s", -1, "the start Page")
pflag.IntVar(&parm.end_page, "e", -1, "the end Page")
pflag.IntVar(&parm.lines_per_page, "l", -1, "the number of lines per page")
f_flag = pflag.Bool("f", false, "")
pflag.StringVar(&parm.print_dest, "d", "", "")
pflag.Parse()
起始頁和結束頁的初始值都被設定為-1,這會被用於之後判斷輸入是否合法。預設使用line模式,也就是按行數翻頁,每頁的行數初始值為20。但是如果直接賦值20,就會導致允許使用者同時輸入–f和–l的情況發生, 所以暫時設定為-1,後面在判斷輸入是否合法的時候再加以判斷。一個全域性變數f_flag用於判斷使用者是否使用了引數--f
。最後使用pflag.Parse()
賦值
然後輸入檔名。利用pflag.NArg()得到沒有字首的引數數量。如果是1說明使用者輸入了檔案路徑,直接賦值即可
parm.file_name = ""
if pflag.NArg() == 1 {
parm.file_name = pflag.Arg(0)
}
二、檢查輸入
我判斷了以下幾種情況
錯誤 | 條件 |
---|---|
除檔案路徑外有多餘的引數 | NArgs > 1 |
起始頁大於終止頁 | parm.start_page > parm.end_page |
起始頁不是正數 | parm.start_page < 1 |
每頁的行數不是正數(在按行數翻頁模式的前提下) | parm.lines_per_page < 0 |
--l 和--f 衝突 | *f_flag && parm.lines_per_page != -1 |
關於最後一個錯誤我解釋一下。當*f_flag
為真時,說明使用者輸入了--f
;當parm.lines_per_page
不等於-1時,說明使用者輸入了’–l’,這就可以判斷是否衝突。如果不衝突,且是--l
,還需要判斷一下每頁的行數是否是初始值-1。如果是就賦值20(預設值)。這樣就既避免了允許衝突的錯誤,也可以給每頁的行數賦值20
程式碼:
func check(NArgs int) {
if NArgs < 1 {
fmt.Println("錯誤:沒有檔案路徑")
os.Exit(1)
}
if NArgs > 1 {
fmt.Println("錯誤:除檔案路徑外有多餘的引數")
os.Exit(1)
}
if parm.start_page > parm.end_page {
fmt.Println("錯誤:起始頁大於終止頁")
os.Exit(1)
}
if parm.start_page < 1 {
fmt.Println("錯誤:起始頁不是正數")
os.Exit(1)
}
if *f_flag && parm.lines_per_page != -1 {
fmt.Println("錯誤:--l和--f衝突")
os.Exit(1)
} else if parm.lines_per_page != -1 {
if parm.lines_per_page < 0 {
fmt.Println("錯誤:每頁的行數不是正數")
os.Exit(1)
} else {
parm.delimited_mode = "l"
}
} else if parm.lines_per_page == -1 {
parm.delimited_mode = "l"
parm.lines_per_page = 20
} else {
parm.delimited_mode = "f"
}
}
三、操作並輸出
首先讀取檔案:
fin := os.Stdin
fout := os.Stdout
var err error
if parm.file_name != "" {
fin, err = os.Open(parm.file_name)
if err != nil {
fmt.Println("錯誤:檔案路徑錯誤")
os.Exit(1)
}
defer fin.Close()
}
然後根據不同的翻頁模式,輸出。在f
模式下:
cur_page := 1 //當前頁
if parm.delimited_mode == "f" {
rd := bufio.NewReader(fin)
for {
page, ferr := rd.ReadString('\f')
if (ferr != nil || ferr == io.EOF) && ferr == io.EOF && cur_page >= parm.start_page && cur_page <= parm.end_page {
fmt.Fprintf(fout, "%s", page)
break
}
page = strings.Replace(page, "\f", "", -1)
cur_page++
if cur_page >= parm.start_page && cur_page <= parm.end_page {
fmt.Fprintf(fout, "%s", page)
}
}
}
在l
模式下:
cur_line := 0 //當前行
else {
line := bufio.NewScanner(fin)
for line.Scan() { //逐行讀入
if cur_page >= parm.start_page && cur_page <= parm.end_page {
fout.Write([]byte(line.Text() + "\n"))
}
cur_line++
if cur_line == parm.lines_per_page {
cur_page++
cur_line = 0
}
}
}
測試結果
首先使用go build selpg.go
進行部署。測試檔案test有30行,每一行的內容都是行號
1、預設情況下,輸出第2頁
可以看到第2頁從21行開始,到30行結束
2、每頁的行數為10,輸出第2頁
接下來,嘗試幾種錯誤情況
3、除檔案路徑外有多餘的引數
4、起始頁大於終止頁
5、起始頁不是正數
6、--l
和--f
衝突
7、每頁的行數不是正數
實驗心得
通過這次作業,我對go語言瞭解更深入了,學會了命令列實用程式開發,直觀地感受到了pflag工具的方便
相關文章
- 基於Golang的CLI 命令列程式開發Golang命令列
- 用Python開發實用程式 – 計算器Python
- 雲端計算和雲服務是一樣的嗎?計算機linux運維開發計算機Linux運維
- LibOpenCM3(一) Linux下命令列開發環境配置Linux命令列開發環境
- 用 Plumbum 開發 Python 命令列工具Python命令列
- 基於gin的golang web開發:服務間呼叫GolangWeb
- golang開發:Error的使用GolangError
- 開發函式計算的正確姿勢——OCR 服務函式
- golang開發:channel使用Golang
- 使用.NET開發搭建OpenAI模型的中間服務端OpenAI模型服務端
- IOS開發 製作簡單的計算器iOS
- golang開發 gorilla websocket的使用GolangWeb
- 區塊鏈應用baas系統開發,實體企業資料上鍊服務開發區塊鏈
- 十分鐘學會Golang開發gRPC服務GolangRPC
- 3D建模服務提供更高效、專業的3D製作能力,“築”力開發者3D
- 《Linux命令列與shell指令碼程式設計大全 第3版》Linux命令列---46Linux命令列指令碼程式設計
- Linux命令和開發工具Linux
- Linux中11個比較實用的命令列Linux命令列
- 如何開發同城生活服務小程式?
- 乾淨架構在 Web 服務開發中的實踐架構Web
- Linux作業系統的優勢官方開發App應用程式有哪些優缺點?Linux作業系統APP
- 雲開發與 WePY,快速實現 Linux 命令查詢小程式Linux
- 雲開發與WePY,快速實現Linux命令查詢小程式Linux
- Java開發必會的Linux命令JavaLinux
- 軟體開發中業務知識的啟用 - Feathers
- 普通開發者最常使用的linux命令和目錄Linux
- 【新加坡】Shopee: Golang服務端或者平臺開發內推Golang服務端
- TCP程式設計之服務端和客戶端的開發TCP程式設計服務端客戶端
- golang常用庫:cli命令列/應用程式生成工具-cobra使用Golang命令列
- [開源] LaravelPlus - 基於 Laravel 魔改,為方便實際業務使用 - 開發中Laravel
- [AI開發]Python+Tensorflow打造自己的計算機視覺API服務AIPython計算機視覺API
- 《Linux網路開發必學教程》2_服務端程式設計初體驗Linux服務端程式設計
- 函式計算-HelloWorld應用開發函式
- 雲端計算開發-RPC應用RPC
- 小程式初探 —— 使用Taro開發BMI體質計算器
- 使用 Calcurse 在 Linux 命令列中組織任務Linux命令列
- 通過 Samba 服務,建立 Linux 開發環境SambaLinux開發環境
- 透過 Samba 服務,建立 Linux 開發環境SambaLinux開發環境