go學習之檔案讀取問題(需更新)
一,問題:
今天做一個GO廣度迷宮問題時,出現了一個奇怪的問題。
就是通過fmt.Fscanf()讀取檔案時,每行末尾多出一個0.
二,問題程式碼:
1,輸入檔案maze.in:
6 5
0 1 0 0 0
0 0 0 1 0
0 1 0 1 0
1 1 1 0 0
0 1 0 0 1
0 1 0 0 0
PS:第一行表示輸入檔案的row和col,下面的0表示可以通過,1表示無法通過。
2.讀取檔案函式readMaze:
func readMaze(filename string) [][]int {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
var row, col int
fmt.Fscanf(file, "%d %d", &row, &col)
maze := make([][]int, row)
for i := range maze {
maze[i] = make([]int, col)
for j := range maze[i] {
fmt.Fscanf(file, "%d", &maze[i][j])
}
}
return maze
}
PS:這段程式碼時從網上ccoume那裡剽過來的。
3.主函式main(只用於測試讀取功能):
func main() {
maze := readMaze("maze/maze.in")
for _, row := range maze {
for _, val := range row {
fmt.Printf("%d ", val)
}
fmt.Println()
}
}
三,問題程式碼執行的輸出:
0 1 0 0 0
0 0 0 1 0
0 1 0 1 0
1 1 1 0 0
0 1 0 0 1
0 1 0 0 0
四,分析錯誤:
1.改變輸入:
因為輸入檔案全是0與1,我們無法判斷問題出在哪裡,我就將輸入檔案改為下列方式:
6 5
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
同樣是6行,5列,但是內容卻是從1到30
2.測試輸出:
0 1 2 3 4
5 0 6 7 8
9 10 0 11 12
13 14 15 0 16
17 18 19 20 0
21 22 23 24 25
3.分析問題:
我們可以看到在原來每次換行前都多了一個0,但是考慮到輸入檔案還有第一行的6和5,所以應該是每行換行後多了一個0.
並且,每個數字都有按順序輸入。程式碼中的file是連續的。而輸出檔案符合我們規定的陣列形式。
所以程式碼本身沒有錯誤。而只是原本輸入檔案的換行都有一個0,而fmt.Fscanf並沒有處理。
五,解決方案:
1.改變輸入檔案:
可以通過將輸入檔案中所涉及到的換行都取消掉。這樣就可以不用修改程式碼了。而且也可以確保在處理類似檔案時,程式碼依舊不需要修改。
2.修改讀取函式:
很多時候,我們無法修改輸入檔案,那麼我們可以修改自己的讀取函式readMaze()。
既然,fmt.Fscanf()無法跳過0,那我們就多讀取一下0,但不輸入到我們的讀取結果陣列中。
程式碼如下:
func readMaze(filename string) [][]int {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
var row, col int
fmt.Fscanf(file, "%d %d", &row, &col)
maze := make([][]int, row)
for i := range maze {
maze[i] = make([]int, col)
fmt.Fscanf(file, "%d")
//用以解決換行帶來的0值問題。希望以後可以找到一個更好的解決方案。
for j := range maze[i] {
fmt.Fscanf(file, "%d", &maze[i][j])
}
}
return maze
}
PS:按照程式碼的可讀性以及邏輯來說,我應該在每次換行後新增
fmt.Fscanf(file, "%d")
即,應該寫成如下程式碼:
func readMaze(filename string) [][]int {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
var row, col int
fmt.Fscanf(file, "%d %d", &row, &col)
fmt.Fscanf(file, "%d")
maze := make([][]int, row)
for i := range maze {
maze[i] = make([]int, col)
for j := range maze[i] {
fmt.Fscanf(file, "%d", &maze[i][j])
}
fmt.Fscanf(file, "%d")
}
return maze
}
PS:這樣更為友好,但我只是寫一個小的廣度迷宮讀取,就偷懶了。。。
當然,前面讀取5與6那兩個fmt.Fsacnf是可以合起來,合為:
fmt.Fscanf(file, "%d %d ", &row, &col) //就是多了一個空格
3.自定義擴充套件fmt.Fscanf()函式:
之前的方法還是太有侷限性了。不可能每次讀取類似檔案,我都加一句吧。
所以為了一勞永逸,完全可以寫一個自定義的擴充套件函式。解決換行問題。
這裡就不做演示。
六,求解更好解決方案:
這樣的問題,肯定已經有了更為成熟的解決方案,只是作為小白的我沒有找到,我在這裡只是提供一個我自己想到的解決方法。
當然啦,更多的是一個找到問題,解決問題的路子吧。
如果有人知道更好的解決方案,可以告訴我。非常感謝。
另外,如果之後,我找到了更好的解決方法,我也會來更新的。