英文:
strconv.ParseInt gives 0
问题
我正在尝试解析以下格式的文件:
12
0,1,2,3,1,2,3,4,2,3,4,5
1,0,1,2,2,1,2,3,3,2,3,4
2,1,0,1,3,2,1,2,4,3,2,3
3,2,1,0,4,3,2,1,5,4,3,2
1,2,3,4,0,1,2,3,1,2,3,4
2,1,2,3,1,0,1,2,2,1,2,3
3,2,1,2,2,1,0,1,3,2,1,2
4,3,2,1,3,2,1,0,4,3,2,1
2,3,4,5,1,2,3,4,0,1,2,3
3,2,3,4,2,1,2,3,1,0,1,2
4,3,2,3,3,2,1,2,2,1,0,1
5,4,3,2,4,3,2,1,3,2,1,0
0,5,2,4,1,0,0,6,2,1,1,1
5,0,3,0,2,2,2,0,4,5,0,0
2,3,0,0,0,0,0,5,5,2,2,2
4,0,0,0,5,2,2,10,0,0,5,5
1,2,0,5,0,10,0,0,0,5,1,1
0,2,0,2,10,0,5,1,1,5,4,0
0,2,0,2,0,5,0,10,5,2,3,3
6,0,5,10,0,1,10,0,0,0,5,0
2,4,5,0,0,1,5,0,0,0,10,10
1,5,2,0,5,5,2,0,0,0,5,0
1,0,2,5,1,4,3,5,10,5,0,2
1,0,2,5,1,0,3,0,10,0,2,0
其中第一行给出了矩阵的大小:n x n
接下来的n行是矩阵D,然后是接下来的n行是矩阵W。所以总共有2n + 1
行。
以下是解析并将其放入变量的代码:
func readFile(path string) (int64, Matrix, Matrix) {
// 打开文件
f, _ := os.Open(path)
defer f.Close()
// 初始化打开文件的新读取器
r := bufio.NewReader(f)
// 获取n的值
line, _ := r.ReadString('\n')
splitedLine := strings.Fields(line)
tmp, _ := strconv.ParseInt(splitedLine[0], 10, 64)
n := int64(tmp)
// 初始化矩阵W和D
D := Matrix{}
D.matrix = make([][]int64, n)
for i, _ := range D.matrix {
D.matrix[i] = make([]int64, n)
}
W := Matrix{}
W.matrix = make([][]int64, n)
for i, _ := range W.matrix {
W.matrix[i] = make([]int64, n)
}
// 循环处理前n个元素
iter := int64(0)
for iter < n {
// 获取接下来的n个元素
line, _ = r.ReadString('\n')
for index, ele := range strings.Split(line, ",") {
D.matrix[iter][index], _ = strconv.ParseInt(ele, 10, 64)
}
iter++
}
iter = 0
for iter < n {
// 获取接下来的n个元素
line, _ = r.ReadString('\n')
for index, ele := range strings.Split(line, ",") {
W.matrix[iter][index], _ = strconv.ParseInt(ele, 10, 64)
}
iter++
}
return n, W, D
}
W的结果应该是:
[ 0., 1., 2., 3., 1., 2., 3., 4., 2., 3., 4., 5.],
[ 1., 0., 1., 2., 2., 1., 2., 3., 3., 2., 3., 4.],
[ 2., 1., 0., 1., 3., 2., 1., 2., 4., 3., 2., 3.],
[ 3., 2., 1., 0., 4., 3., 2., 1., 5., 4., 3., 2.],
[ 1., 2., 3., 4., 0., 1., 2., 3., 1., 2., 3., 4.],
[ 2., 1., 2., 3., 1., 0., 1., 2., 2., 1., 2., 3.],
[ 3., 2., 1., 2., 2., 1., 0., 1., 3., 2., 1., 2.],
[ 4., 3., 2., 1., 3., 2., 1., 0., 4., 3., 2., 1.],
[ 2., 3., 4., 5., 1., 2., 3., 4., 0., 1., 2., 3.],
[ 3., 2., 3., 4., 2., 1., 2., 3., 1., 0., 1., 2.],
[ 4., 3., 2., 3., 3., 2., 1., 2., 2., 1., 0., 1.],
[ 5., 4., 3., 2., 4., 3., 2., 1., 3., 2., 1., 0.]
但是当我打印它时,结果是:
[0 1 2 3 1 2 3 4 2 3 4 0]
[1 0 1 2 2 1 2 3 3 2 3 0]
[2 1 0 1 3 2 1 2 4 3 2 0]
[3 2 1 0 4 3 2 1 5 4 3 0]
[1 2 3 4 0 1 2 3 1 2 3 0]
[2 1 2 3 1 0 1 2 2 1 2 0]
[3 2 1 2 2 1 0 1 3 2 1 0]
[4 3 2 1 3 2 1 0 4 3 2 0]
[2 3 4 5 1 2 3 4 0 1 2 0]
[3 2 3 4 2 1 2 3 1 0 1 0]
[4 3 2 3 3 2 1 2 2 1 0 0]
[5 4 3 2 4 3 2 1 3 2 1 0]
我不知道为什么会这样。谢谢你的回复。
英文:
I'm trying to parse a file of this forme:
12
0,1,2,3,1,2,3,4,2,3,4,5
1,0,1,2,2,1,2,3,3,2,3,4
2,1,0,1,3,2,1,2,4,3,2,3
3,2,1,0,4,3,2,1,5,4,3,2
1,2,3,4,0,1,2,3,1,2,3,4
2,1,2,3,1,0,1,2,2,1,2,3
3,2,1,2,2,1,0,1,3,2,1,2
4,3,2,1,3,2,1,0,4,3,2,1
2,3,4,5,1,2,3,4,0,1,2,3
3,2,3,4,2,1,2,3,1,0,1,2
4,3,2,3,3,2,1,2,2,1,0,1
5,4,3,2,4,3,2,1,3,2,1,0
0,5,2,4,1,0,0,6,2,1,1,1
5,0,3,0,2,2,2,0,4,5,0,0
2,3,0,0,0,0,0,5,5,2,2,2
4,0,0,0,5,2,2,10,0,0,5,5
1,2,0,5,0,10,0,0,0,5,1,1
0,2,0,2,10,0,5,1,1,5,4,0
0,2,0,2,0,5,0,10,5,2,3,3
6,0,5,10,0,1,10,0,0,0,5,0
2,4,5,0,0,1,5,0,0,0,10,10
1,5,2,0,5,5,2,0,0,0,5,0
1,0,2,5,1,4,3,5,10,5,0,2
1,0,2,5,1,0,3,0,10,0,2,0
Where the first line give us the size of the matrix: n x n
The n-following lines are the matrix D. Then the n-following lines are the matrix W. So there is 2n + 1
lines.
Here is the code to parse it and put it in variables.
func readFile(path string) (int64, Matrix, Matrix) {
// open the file
f, _ := os.Open(path)
defer f.Close()
// init the new reader on the opened file
r := bufio.NewReader(f)
// we get the n value
line, _ := r.ReadString('\n')
splitedLine := strings.Fields(line)
tmp, _ := strconv.ParseInt(splitedLine[0], 10, 64)
n := int64(tmp)
// we init the matrix W and D
D := Matrix{}
D.matrix = make([][]int64, n)
for i, _ := range D.matrix {
D.matrix[i] = make([]int64, n)
}
W := Matrix{}
W.matrix = make([][]int64, n)
for i, _ := range W.matrix {
W.matrix[i] = make([]int64, n)
}
// loop on the n first element
iter := int64(0)
for iter < n {
// we get the n following elements
line, _ = r.ReadString('\n')
for index, ele := range strings.Split(line, ",") {
D.matrix[iter][index], _ = strconv.ParseInt(ele, 10, 64)
}
iter++
}
iter = 0
for iter < n {
// we get the n following elements
line, _ = r.ReadString('\n')
for index, ele := range strings.Split(line, ",") {
W.matrix[iter][index], _ = strconv.ParseInt(ele, 10, 64)
}
iter++
}
return n, W, D
}
The resultat for W should be like:
[ 0., 1., 2., 3., 1., 2., 3., 4., 2., 3., 4., 5.],
[ 1., 0., 1., 2., 2., 1., 2., 3., 3., 2., 3., 4.],
[ 2., 1., 0., 1., 3., 2., 1., 2., 4., 3., 2., 3.],
[ 3., 2., 1., 0., 4., 3., 2., 1., 5., 4., 3., 2.],
[ 1., 2., 3., 4., 0., 1., 2., 3., 1., 2., 3., 4.],
[ 2., 1., 2., 3., 1., 0., 1., 2., 2., 1., 2., 3.],
[ 3., 2., 1., 2., 2., 1., 0., 1., 3., 2., 1., 2.],
[ 4., 3., 2., 1., 3., 2., 1., 0., 4., 3., 2., 1.],
[ 2., 3., 4., 5., 1., 2., 3., 4., 0., 1., 2., 3.],
[ 3., 2., 3., 4., 2., 1., 2., 3., 1., 0., 1., 2.],
[ 4., 3., 2., 3., 3., 2., 1., 2., 2., 1., 0., 1.],
[ 5., 4., 3., 2., 4., 3., 2., 1., 3., 2., 1., 0.]
But when I print it; it gives me :
[0 1 2 3 1 2 3 4 2 3 4 0]
[1 0 1 2 2 1 2 3 3 2 3 0]
[2 1 0 1 3 2 1 2 4 3 2 0]
[3 2 1 0 4 3 2 1 5 4 3 0]
[1 2 3 4 0 1 2 3 1 2 3 0]
[2 1 2 3 1 0 1 2 2 1 2 0]
[3 2 1 2 2 1 0 1 3 2 1 0]
[4 3 2 1 3 2 1 0 4 3 2 0]
[2 3 4 5 1 2 3 4 0 1 2 0]
[3 2 3 4 2 1 2 3 1 0 1 0]
[4 3 2 3 3 2 1 2 2 1 0 0]
[5 4 3 2 4 3 2 1 3 2 1 0]
I don't know why.
Thanks for your reply.
答案1
得分: 7
知道Reader.ReadString()
会返回带有分隔符的string
值。所以r.ReadString('\n')
会返回带有尾部换行符的字符串。
当你在逗号处拆分字符串时,最后一部分将包含换行符,尝试从中解析数字将失败,就像这个例子中所示:
line := "0,1,2\n"
for _, ele := range strings.Split(line, ",") {
fmt.Println(strconv.ParseInt(ele, 10, 64))
}
输出结果(在Go Playground上尝试):
0 <nil>
1 <nil>
0 strconv.ParseInt: parsing "2\n": invalid syntax
你一直忽略错误检查,不要这样做!正如你在上面的例子中看到的,立即检查和打印strconv.ParseInt()
返回的错误可以揭示错误和出错的原因。
你可以在尝试解析任何数字之前去掉尾部的换行符,例如:
strconv.ParseInt(strings.TrimSpace(ele), 10, 64)
或者使用bufio.Scanner
,它可以扫描行并自动去掉尾部的换行符。
英文:
Know that Reader.ReadString()
returns you a string
value with the delimieter. So r.ReadString('\n')
will return you a string with the trailing newline character.
And when you split the string at the commas, the last part will contain the newline character, and attempting to parse the number from it will fail, as shown in this example:
line := "0,1,2\n"
for _, ele := range strings.Split(line, ",") {
fmt.Println(strconv.ParseInt(ele, 10, 64))
}
Output (try it on the Go Playground):
0 <nil>
1 <nil>
0 strconv.ParseInt: parsing "2\n": invalid syntax
You religiously omit error checks, don't do that! As you can see in the above example, checking and printing the error returned by strconv.ParseInt()
immediately revealed the error and what's going wrong.
What you may do is cut the trailing newline character before attempting to parse any number from it, e.g.:
strconv.ParseInt(strings.TrimSpace(ele), 10, 64)
Or use the bufio.Scanner
which can scan lines and it cuts trailing newlines automatically.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论