go學習之檔案讀取問題(需更新)

weixin_34104341發表於2020-04-07

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()函式:

之前的方法還是太有侷限性了。不可能每次讀取類似檔案,我都加一句吧。

所以為了一勞永逸,完全可以寫一個自定義的擴充套件函式。解決換行問題。

這裡就不做演示。

 

 

六,求解更好解決方案:

這樣的問題,肯定已經有了更為成熟的解決方案,只是作為小白的我沒有找到,我在這裡只是提供一個我自己想到的解決方法。

當然啦,更多的是一個找到問題,解決問題的路子吧。

如果有人知道更好的解決方案,可以告訴我。非常感謝。

另外,如果之後,我找到了更好的解決方法,我也會來更新的。

 

轉載於:https://www.cnblogs.com/Tiancheng-Duan/p/9015235.html

相關文章