今天看到朋友代码时,发现一个小问题,fmt.Fscanf()读取数据老是不正常,总体,可以看出来是,多读了一个0。这个现象有点问题。

Fscanf的注释:

1
2
3
4
5
6
7
// Fscanf scans text read from r, storing successive space-separated
// values into successive arguments as determined by the format. It
// returns the number of items successfully parsed.
// Newlines in the input must match newlines in the format.

Fscanf扫描从r读取的文本,将连续的以空格分隔的值存储到由格式确定的连续的参数中。它返回成功解析的项目数。
输入中的换行符必须与format中的换行符匹配。

使用的代码是:

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
func read1(filename string) [][]int {
file, err := os.Open(filename)

if err != nil {
panic(err)
}
var rows, cols int
fmt.Fscanf(file, "%d %d", &rows, &cols)

maze := make([][]int, rows)

for i := range maze {
maze[i] = make([]int, cols)

for j := range maze[i] {
fmt.Fscanf(file, "%d", &maze[i][j])
}
fmt.Println()
}

return maze
}

文件:
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

运行读出来的数据:
0 0 1 0 0
0 0 0 0 0
1 0 0 0 1
0 1 0 0 1
1 1 0 0 0
0 1 0 0 1

没有找到解释该现象的博客,golang fmt.Fscanf()遇到换行返回值为0,这里有看到同样是碰到这个问题的人。

1
2
3
Scan,Fscan,Sscan treat newlines in the input as spaces.
fmt
这就是他工作的机制,了解了原理,要继续采用这个方式的话,可以先格式化一下,把换行替换成空格,在交给Fscanf

但我并不喜欢这种操作方式,虽然管用,可这样的话,就得将数据格式化一遍,然后才能读,感觉麻烦了些。

遇到换行会读取多一个0,这很奇怪,但这里我很巧合的联想到了文件格式是否是造成此问题的原因,因为CRLF和LF,分别是两种换行符,属于不同的操作系统,一个是\r\n,一个是\n,刚好会多出一个符号。

果然,在更改文件格式后,结果正常,看来就是文件格式的问题了,需要将文件格式修改为LF,这里Fscanf默认换行符看来识别的是\n,在其注释中的输入中的换行符必须与format中的换行符匹配,看来就是留下的一个引子,怎么修改识别这个换行符标志,我就没有深入研究了,如果有后续可以跟我留言,告诉我详情。