Ada95中‘类型转换参数必须为单个表达式’错误修复咨询
嘿,作为Ada新手碰到这些类型相关的错误太正常了——Ada的类型系统确实严格,咱们一步步拆解你的问题,把这些错误逐个解决掉:
1. 核心类型定义错误
你写的type Checkers_Piece is ("b", "BK", "RK", "BC", "RC");是非法的,Ada里的枚举类型不能直接用字符串字面量,得用标识符(不带引号的名字)。这是导致后续大部分类型转换错误的根源。
咱们把它改成合法的枚举类型,再添加转换函数来对应你需要的字符串表示:
type Checkers_Piece is (Blank, Black_King, Red_King, Black_Checker, Red_Checker); -- 把枚举值转成对应字符串 function To_String(P : Checkers_Piece) return String is begin case P is when Blank => return "b"; when Black_King => return "BK"; when Red_King => return "RK"; when Black_Checker => return "BC"; when Red_Checker => return "RC"; end case; end To_String; -- 把字符串转成对应枚举值 function To_Piece(S : String) return Checkers_Piece is begin if S = "b" then return Blank; elsif S = "BK" then return Black_King; elsif S = "RK" then return Red_King; elsif S = "BC" then return Black_Checker; elsif S = "RC" then return Red_Checker; else raise Constraint_Error with "Invalid piece string: " & S; end if; end To_Piece;
2. 混淆了类型和变量
你直接用类型名Checkers_Board来赋值(比如Checkers_Board(I, J) := ...),这完全错误——类型是模板,你需要声明一个该类型的变量来存储数据:
type Checkers_Board is array (1..8, 1..8) of Checkers_Piece; Board : Checkers_Board; -- 声明具体的棋盘变量
之后所有操作都用Board这个变量,而不是类型名,这也解决了你遇到的invalid use of subtype mark错误。
3. 输入到棋盘的赋值逻辑错误
你的输入是64个字符的Checkers_String,但棋子有单字符和双字符两种,这逻辑矛盾:如果每个格子用1个字符,没法表示BK这类双字符棋子;如果用2个字符,输入应该是128位。
假设你坚持用双字符表示棋子,修改赋值逻辑:
for I in 1..8 loop for J in 1..8 loop declare Start_Idx : constant Integer := ((I-1)*8 + (J-1))*2 + 1; Piece_Str : String := Checkers_String(Start_Idx .. Start_Idx+1); begin Board(I, J) := To_Piece(Piece_Str); end; end loop; end loop;
之前直接把单个字符赋值给枚举类型变量,类型不匹配,自然会报类型转换错误。
4. Print_Board过程的修复
你原来的打印逻辑试图把多字符棋子塞进单个字符串位置,还直接用类型名操作,完全不可行。修改后的打印过程可以正确显示枚举对应的字符串:
procedure Print_Board (Object: in Checkers_Board) is begin Put_Line("-----------------------------"); for X in 1..8 loop Put("|"); for Y in 1..8 loop Put(" " & To_String(Object(X,Y)) & " |"); end loop; New_Line; Put_Line("-----------------------------"); end loop; end Print_Board;
调用时记得传变量:Print_Board(Board);,你原来的Print_Board;没传参数也是错误。
5. 黑格检查与计数逻辑的修正
跳棋黑格的判断规则是:左下角(1,1)为黑格,此时(X+Y)为偶数的格子是黑格,白格必须为空。同时,你不能直接用字符串和枚举值比较,得用枚举常量:
for Y in 1..8 loop for X in 1..8 loop -- 检查白格是否有棋子 if (X + Y) mod 2 = 1 then -- 白格 if Board(Y, X) /= Blank then Put_Line("Error: Piece on white space at (" & Integer'Image(X) & "," & Integer'Image(Y) & ")"); invalid := invalid + 1; end if; end if; -- 计数各类棋子 case Board(Y, X) is when Black_King => BK_Count := BK_Count + 1; BC_Count := BC_Count + 1; when Red_King => RK_Count := RK_Count + 1; RC_Count := RC_Count + 1; when Black_Checker => BC_Count := BC_Count + 1; when Red_Checker => RC_Count := RC_Count + 1; when Blank => b_Count := b_Count + 1; end case; end loop; end loop;
修复后的完整代码
整合所有修复后的代码如下:
with Ada.Text_IO, Ada.Integer_Text_IO; use Ada.Text_IO, Ada.Integer_Text_IO; procedure Checker_Checker is type Checkers_Piece is (Blank, Black_King, Red_King, Black_Checker, Red_Checker); function To_String(P : Checkers_Piece) return String is begin case P is when Blank => return "b"; when Black_King => return "BK"; when Red_King => return "RK"; when Black_Checker => return "BC"; when Red_Checker => return "RC"; end case; end To_String; function To_Piece(S : String) return Checkers_Piece is begin if S = "b" then return Blank; elsif S = "BK" then return Black_King; elsif S = "RK" then return Red_King; elsif S = "BC" then return Black_Checker; elsif S = "RC" then return Red_Checker; else raise Constraint_Error with "Invalid piece: " & S; end if; end To_Piece; type Checkers_Board is array (1..8, 1..8) of Checkers_Piece; Board : Checkers_Board; Checkers_String: String(1..128); -- 每个格子2字符,共8*8*2=128位 invalid, BK_Count, RK_Count, RC_Count, BC_Count, b_Count : Integer := 0; procedure Print_Board (Object: in Checkers_Board) is begin Put_Line("-----------------------------"); for X in 1..8 loop Put("|"); for Y in 1..8 loop Put(" " & To_String(Object(X,Y)) & " |"); end loop; New_Line; Put_Line("-----------------------------"); end loop; end Print_Board; begin Put_Line("Enter 128-character board string (each cell 2 chars):"); Get(Checkers_String); -- 填充棋盘 for I in 1..8 loop for J in 1..8 loop declare Start : constant Integer := ((I-1)*8 + (J-1))*2 + 1; Piece_Str : String := Checkers_String(Start .. Start+1); begin Board(I, J) := To_Piece(Piece_Str); end; end loop; end loop; -- 检查棋盘规则 for Y in 1..8 loop for X in 1..8 loop -- 检查白格是否有棋子 if (X + Y) mod 2 = 1 then -- 白格(确保左下角(1,1)为黑格) if Board(Y, X) /= Blank then Put_Line("Error: Piece on white space at (" & Integer'Image(X) & "," & Integer'Image(Y) & ")"); invalid := invalid + 1; end if; end if; -- 计数各类棋子 case Board(Y, X) is when Black_King => BK_Count := BK_Count + 1; BC_Count := BC_Count + 1; when Red_King => RK_Count := RK_Count + 1; RC_Count := RC_Count + 1; when Black_Checker => BC_Count := BC_Count + 1; when Red_Checker => RC_Count := RC_Count + 1; when Blank => b_Count := b_Count + 1; end case; end loop; end loop; -- 打印棋盘 Print_Board(Board); -- 检查数量限制 if RK_Count > 7 then Put_Line("Error: More than 7 Red Kings."); invalid := invalid +1; end if; if BK_Count > 7 then Put_Line("Error: More than 7 Black Kings."); invalid := invalid +1; end if; if RC_Count > 12 then Put_Line("Error: More than 12 Red Checkers."); invalid := invalid +1; end if; if BC_Count > 12 then Put_Line("Error: More than 12 Black Checkers."); invalid := invalid +1; end if; if b_Count < 32 then Put_Line("Error: Too many pieces on the board."); invalid := invalid +1; end if; -- 输出最终结果 if invalid = 0 then Put_Line("This is a valid checker board."); else Put_Line("This is an invalid checker board."); end if; exception when Constraint_Error => Put_Line("Error: Invalid character in input string."); Put_Line("This is an invalid checker board."); end Checker_Checker;
内容的提问来源于stack exchange,提问作者Andrea

