Golang中如何进行语言转换的实践与探讨
Golang中如何进行语言转换的实践与探讨 我知道有很多更简单的方法可以实现我正在尝试做的事情(即将C代码转换为Go),比如直接在代码中添加C库,但根据Coursera的练习要求,我不被允许这样做。
我正在尝试转换以下C程序:
#include <stdio.h>
main()
{
int input; /* User defined integer */
int loc[14][14]; /* Array holding all */
/* input*input values. */
int row; /* Determines row of matrix */
int col; /* Determines col of matrix */
int value; /* Integer between 1 and */
/* input*input */
int otherdiag; /* Total of one matrix diagonal*/
printf("\nMagic Squares: This program produces an NxN matrix where\n");
printf("N is some positive odd integer. The matrix contains the \n");
printf("values 1 to N*N. The sum of each row, each column, and \n");
printf("the two main diagonals are all equal. Not only does this \n");
printf("program produces the matrix, it also computes the totals for\n");
printf("each row, column, and two main diagonals.\n");
printf("\nBecause of display constraints, this program can work with\n");
printf("values up to 13 only.\n\n");
printf("Enter a positive, odd integer (-1 to exit program):\n");
while (scanf("%d",&input) == 1)
{
/* */
/* If input = -1, then exit program. */
/* */
if (input == -1)
break;
/* */
/* Validity check for input: Must be a positive odd integer < 13. */
/* */
if (input <= 0)
{
printf("Sorry, but the integer has to be positive.\n");
printf("\nEnter a positive, odd integer (-1 to exit program):\n");
continue;
}
if (input > 13)
{
printf("Sorry, but the integer has to be less than 15.\n");
printf("\nEnter a positive, odd integer (-1 to exit program):\n");
continue;
}
if (input%2 == 0)
{
printf("Sorry, but the integer has to be odd.\n");
printf("\nEnter a positive, odd integer (-1 to exit program):\n");
continue;
}
/* */
/* Initialize matrix, row, col, and otherdiag */
/* */
for (row = 0; row <= input; row++) /* Initialize matrix with */
for (col = 0; col <= input; col++) /* all zeroes. */
loc[row][col] = 0; /* Values will reside within */
/* rows 1 to input*input and */
/* columns 1 to input*input. */
/* Row totals will reside in */
/* loc[row][0], where row is */
/* the row number, while the */
/* column totals will reside */
/* in loc[0][col], where col */
/* is the column number. */
row = 1; /* First value gets to sit on */
col = input/2 + 1; /* 1st row, middle of matrix.*/
otherdiag = 0;
/* */
/* Loop for every value up to input*input, and position value in matrix*/
/* */
for (value = 1; value <= input*input; value++)
{ /* Loop for all values. */
if (loc[row][col] > 0) /* If some value already */
{ /* present, then */
row += 2; /* move down 1 row of prev. */
if (row > input) /* If exceeds side, then */
row -= input; /* go to other side. */
col--; /* move left 1 column. */
if (col < 1) /* If exceeds side, then */
col = input; /* go to other side. */
}
loc[row][col] = value; /* Assign value to location. */
loc[0][col] += value; /* Add to its column total. */
loc[row][0] += value; /* Add to its row total. */
if (row == col) /* Add to diagonal total if */
loc[0][0] += value; /* it falls on the diagonal. */
if (row+col == input+1) /* Add to other diagonal if */
otherdiag += value; /* it falls on the line. */
/* */
/* Determine where new row and col are */
/* */
row--;
if (row < 1) /* If row exceeds side then */
row = input; /* goto other side. */
col++;
if (col > input) /* If col exceeds side then */
col = 1; /* goto other side. */
} /* End of getting all values. */
/* */
/* Print out the matrix with its totals */
/* */
printf("\nThe number you selected was %d",input);
printf(", and the matrix is:\n\n");
for (row = 1; row <=input; row++) /* Loop: print a row at a time*/
{
printf(" "); /* Create column for diag.total*/
for (col = 1; col <=input; col++)
printf("%5d",loc[row][col]); /* Print values found in a row*/
printf(" = %5d\n",loc[row][0]); /* Print total of row. */
}
/* */
/* Print out the totals for each column, starting with diagonal total. */
/* */
for (col = 0; col <=input; col++) /* Print line separating the */
printf("-----"); /* value matrix and col totals*/
printf("\n%5d",otherdiag); /* Print out the diagonal total*/
for (col = 1; col <=input; col++)
printf("%5d",loc[0][col]); /* Print out the column totals*/
printf(" %5d\n",loc[0][0]); /* Print out the other diagonal*/
/* total */
printf("\nEnter a positive, odd integer (-1 to exit program):\n");
} /* End of while input>-1 loop */
printf("\nBye bye!\n");
}
将其转换为Golang,我做了以下工作:
package main
import (
"fmt"
"os"
)
var otherdiag int
var loc [][]int
var row, col int
func main() {
var input int /* User defined integer */
for input != -1 {
fmt.Printf("\nMagic Squares: This program produces an NxN matrix where\n")
fmt.Printf("N is some positive odd integer. The matrix contains the \n")
fmt.Printf("values 1 to N*N. The sum of each row, each column, and \n")
fmt.Printf("the two main diagonals are all equal. Not only does this \n")
fmt.Printf("program produces the matrix, it also computes the totals for\n")
fmt.Printf("each row, column, and two main diagonals.\n")
fmt.Printf("\nBecause of display constraints, this program can work with\n")
fmt.Printf("values up to 13 only.\n\n")
fmt.Printf("Enter a positive, odd integer (-1 to exit program):\n")
fmt.Scan(&input)
/* */
/* If input = -1, then exit program. */
/* */
if input == -1 {
fmt.Println("Bye Bye!")
os.Exit(0)
} else if input <= 0 {
fmt.Printf("Sorry, but the integer has to be positive.\n")
fmt.Printf("\nEnter a positive, odd integer (-1 to exit program):\n")
continue
} else if input > 13 {
fmt.Printf("Sorry, but the integer has to be less than 13.\n")
fmt.Printf("\nEnter a positive, odd integer (-1 to exit program):\n")
continue
} else if input%2 == 0 {
fmt.Printf("Sorry, but the integer has to be odd.\n")
fmt.Printf("\nEnter a positive, odd integer (-1 to exit program):\n")
continue
}
displayMatrix(input, loc)
}
}
func createMatrix(matrixSize int) (loc [][]int) {
// Use make to create two dimensional array
// allocate memory for 1-dimensional array of size matrixSize
// within for loop allocate memory for 2-dimension array
loc = make([][]int, matrixSize)
for i := range loc {
loc[i] = make([]int, matrixSize)
}
return loc
}
func initMatrix(arraySize int, loc [][]int) {
// Create nested for loop to initialize array
loc = createMatrix(arraySize)
for i := 0; i < arraySize; i++ {
for j := 0; j < arraySize; j++ {
loc[i][j] = 0
}
}
}
func calculateMatrix(userVal int, loc [][]int) {
loc = createMatrix(userVal) //declare loc
initMatrix(userVal, loc) //initialize loc to a matrix of all zeroes
// Convert C code calculation without changing the logic.
row = 1 /* First value gets to sit on */
col = (userVal / 2) + 1 /* 1st row, middle of matrix.*/
//otherdiag := 0
/* */
/* Loop for every value up to input*input, and position value in matrix*/
/* */
for value := 1; value <= userVal*userVal; value++ {
/* Loop for all values. */
if loc[row][col] > 0 { /* If some value already */
/* present, then */
row += 2 /* move down 1 row of prev. */
if row > userVal { /* If exceeds side, then */
row -= userVal /* go to other side. */
}
col-- /* move left 1 column. */
if col < 1 { /* If exceeds side, then */
col = userVal
} /* go to other side. */
}
loc[row][col] = value /* Assign value to location. */
/* */
/* Add to totals */
/* */
loc[0][col] += value /* Add to its column total. */
loc[row][0] += value /* Add to its row total. */
if row == col { /* Add to diagonal total if */
loc[0][0] += value
} /* it falls on the diagonal. */
if row+col == userVal+1 { /* Add to other diagonal if */
otherdiag += value /* it falls on the line. */
}
/* */
/* Determine where new row and col are */
/* */
row--
if row < 1 { /* If row exceeds side then */
row = userVal /* goto other side. */
}
col++
if col > userVal { /* If col exceeds side then */
col = 1 /* goto other side. */
}
} /* End of getting all values. */
}
func displayMatrix(userVal int, loc [][]int) {
// Create nested for loop to read each array element and display
// matrix with column totals and row totals
loc = createMatrix(userVal)
initMatrix(userVal, loc)
calculateMatrix(userVal, loc)
fmt.Printf("\nThe number you selected was %d", userVal)
fmt.Printf(", and the matrix is:\n\n")
for row := 1; row <= userVal; row++ { /* Loop: print a row at a time*/
fmt.Printf(" ") /* Create column for diag.total*/
for col := 1; col <= userVal; col++ {
fmt.Printf("%5d", loc[row][col])
} /* Print values found in a row*/
fmt.Printf(" = %5d\n", loc[row][0]) /* Print total of row. */
}
/* */
/* Print out the totals for each column, starting with diagonal total. */
/* */
for col := 0; col <= userVal; col++ { /* Print line separating the */
fmt.Printf("-----") /* value matrix and col totals*/
fmt.Printf("\n%5d", otherdiag)
} /* Print out the diagonal total*/
for col := 1; col <= userVal; col++ {
fmt.Printf("%5d", loc[0][col]) /* Print out the column totals*/
fmt.Printf(" %5d\n", loc[0][0]) /* Print out the other diagonal*/
} /* total */
}
我在编译时遇到以下运行时错误,不确定原因:
panic: runtime error: index out of range
goroutine 1 [running]:main.calculateMatrix(0x3, 0xc420082190, 0x3, 0x3) /home/Documents/CourseraCourse/Assignment1/hw1.go:97 +0x263main.displayMatrix(0x3, 0xc4200820f0, 0x3, 0x3)
/home/Documents/CourseraCourse/Assignment1/hw1.go:142 +0xb0
main.main() /home/Documents/CourseraCourse/Assignment1/hw1.go:55 +0x278
exit status 2
第97行是以下代码行:if loc[row][col] > 0
第142行调用了calculateMatrix()函数
第55行调用了displayMatrix()函数。
我觉得我在计算函数中做错了什么。任何建议都将不胜感激。谢谢!
更多关于Golang中如何进行语言转换的实践与探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感谢提供的信息。我现在正在处理这个问题。
更多关于Golang中如何进行语言转换的实践与探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在C语言版本中,你将二维数组loc[][]声明为14x14的整型数组。当我输入3运行程序时,计算数组内容的部分访问的是loc的索引1-3,而不是0-2。它使用了14x14数组中的3x3部分,访问的是第2到第4行和列,而不是第1到第3行和列。
如果声明为:
int loc[3][3]
程序将无法正常工作。
在Go版本中,你将loc分配为与输入数字相同的大小。当用户输入3时,loc被分配为3x3大小,你可以使用0到2的row和col。但Go版本中的row和col范围也是从1到3。在第97行,程序尝试访问不存在的loc[3][3]。
结果就是你遇到的运行时错误,index out of range表明row或col的值过大。
你可以在calculateMatrix()函数的循环每次迭代中使用fmt.Printf()语句来显示row和col的值。
fmt.Printf("row: %d, col: %d\n",row,col)
将此代码放在第97行,紧接在
if loc[row][col] > 0 { /* 如果已有值 */
之前,你就能看到我描述的行为。
在转换C代码到Go时,数组索引的处理存在几个关键问题。以下是修正后的代码:
package main
import (
"fmt"
)
func main() {
var input int
fmt.Printf("\nMagic Squares: This program produces an NxN matrix where\n")
fmt.Printf("N is some positive odd integer. The matrix contains the \n")
fmt.Printf("values 1 to N*N. The sum of each row, each column, and \n")
fmt.Printf("the two main diagonals are all equal.\n\n")
for {
fmt.Printf("Enter a positive, odd integer (-1 to exit program): ")
_, err := fmt.Scan(&input)
if err != nil {
fmt.Println("Invalid input")
continue
}
if input == -1 {
fmt.Println("Bye bye!")
break
}
if input <= 0 {
fmt.Println("Sorry, but the integer has to be positive.")
continue
}
if input > 13 {
fmt.Println("Sorry, but the integer has to be less than 15.")
continue
}
if input%2 == 0 {
fmt.Println("Sorry, but the integer has to be odd.")
continue
}
displayMatrix(input)
}
}
func createMatrix(matrixSize int) [][]int {
loc := make([][]int, matrixSize+1)
for i := range loc {
loc[i] = make([]int, matrixSize+1)
}
return loc
}
func calculateMatrix(userVal int) ([][]int, int) {
loc := createMatrix(userVal)
otherdiag := 0
row := 1
col := userVal/2 + 1
for value := 1; value <= userVal*userVal; value++ {
if loc[row][col] > 0 {
row += 2
if row > userVal {
row -= userVal
}
col--
if col < 1 {
col = userVal
}
}
loc[row][col] = value
loc[0][col] += value
loc[row][0] += value
if row == col {
loc[0][0] += value
}
if row+col == userVal+1 {
otherdiag += value
}
row--
if row < 1 {
row = userVal
}
col++
if col > userVal {
col = 1
}
}
return loc, otherdiag
}
func displayMatrix(userVal int) {
loc, otherdiag := calculateMatrix(userVal)
fmt.Printf("\nThe number you selected was %d", userVal)
fmt.Printf(", and the matrix is:\n\n")
for row := 1; row <= userVal; row++ {
fmt.Printf(" ")
for col := 1; col <= userVal; col++ {
fmt.Printf("%5d", loc[row][col])
}
fmt.Printf(" = %5d\n", loc[row][0])
}
for col := 0; col <= userVal; col++ {
fmt.Printf("-----")
}
fmt.Printf("\n%5d", otherdiag)
for col := 1; col <= userVal; col++ {
fmt.Printf("%5d", loc[0][col])
}
fmt.Printf(" %5d\n", loc[0][0])
}
主要修正的问题:
-
数组大小问题:在
createMatrix函数中,数组应该是matrixSize+1而不是matrixSize,因为C代码中数组索引从0到input(包含边界) -
全局变量问题:移除了全局变量
loc、row、col、otherdiag,改为函数局部变量和返回值 -
函数参数传递:修正了函数间的数据传递方式,
calculateMatrix现在返回计算后的矩阵和对角线和 -
数组初始化:移除了不必要的
initMatrix函数,因为Go的make已经将切片初始化为零值 -
输入循环逻辑:简化了主循环结构,使其更符合Go的惯用法
这些修改解决了数组越界的问题,并保持了与原始C代码相同的算法逻辑。


