TGDZcalc by Ada (43th)

今日再研究了一下Ada,这个语言有不少Pascal的特点,让我见面就有不少好感.但安装过程中走了点误区,装了最新的gnat pro,但它没有带Ada编译器.后来还是用2021年的版本(500M)安装,效果还是理想的.
这个IDE有比较好的功能提示,也有一些调试功能(不过没学会).
它比较强调软件工程,因此即使是简单的代码,也要有一个包文件(ads),一个源码文件(adb)
写出来的代码是这样的.

点击查看代码
--File0: 项目文件,注意下面引用了具体的实现包.
with Ada.Text_IO; with Ada.Integer_Text_IO;
with  TGDZpackage;  use TGDZpackage;


procedure Main is
	akey:Character;
begin
	Test(1900);
	Test(1924);
	Test(1976);
	Test(-361);
	Ada.Text_IO.Get_Immediate(aKey); --pause
   null;
end Main;


---------------------------------------------
--File1:TGDZpackage.ads
--有点像C++的头文件,定义基本的结构
package TGDZpackage is
function CalcBaseYear(year:integer) return Integer;
function YearToTGDZ(year:integer) return Wide_String;
function TGDZtoYear(tgdz:Wide_String; baseYear:Integer) return Integer;
procedure Test(y:integer);
end TGDZpackage;


------------------------------------------------
--File2: TGDZPackage.adb,主要过程定义在此中
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Wide_Text_IO; use Ada.Wide_Text_IO;
with Ada.Strings.Wide_Fixed;
with Ada.Text_IO; 

package body TGDZpackage is

	function CalcBaseYear(year:integer) return Integer is
	b:integer;
	begin
		if year>0 then
			b:=4;
		else
			b:= -57;
		end if;

		while b>year loop
			b:=b-60;
		end loop;

		while b+60<=year loop
			b:=b+60;
		end loop;
		return b;
	end CalcBaseYear;

	function YearToTGDZ(year:integer) return Wide_String is
		strTG:constant Wide_String(1..30):="甲乙丙丁戊已庚辛壬癸"; --注意这个长度设置.
		strDZ:constant Wide_String(1..36) :="子丑寅卯辰巳午未申酉戌亥";
		tmpY:Integer; ti,di:integer;
		t:Wide_String(1..3):="   ";
		d:Wide_String(1..3):="   ";
		Restgdz:wide_string(1..6);

	begin
		
  if  year=0 then
  	return "";
  end if;
  
  tmpY:=year;
  if tmpY>0 then
  	tmpY:=tmpY-4;
  else
  	tmpY:=tmpY-3;
  end if;
  
  while tmpY<0 loop
  	tmpY:=tmpY+60;
  end loop;
  ti:=tmpY mod 10; 
  di:=tmpY mod 12; 
   ti:=ti*3+1; di:=di*3+1; --配合宽字符的特点调整,上面已经限定了序数从1开始.
  t:=strTG(ti..ti+2);
  d:=strDZ(di..di+2);
 Restgdz:=t & d;
	--	Restgdz:="甲子";
		return Restgdz ; 
	end YearToTGDZ;


	function TGDZtoYear(tgdz:Wide_String; baseYear:Integer) return Integer is
			strLen:Natural :=tgdz'Length;
			strTG:constant Wide_String:="甲乙丙丁戊已庚辛壬癸";
			strDZ:constant Wide_String:="子丑寅卯辰巳午未申酉戌亥";
			charTG:Wide_String(1..3);
			charDZ:Wide_String(1..3);
			ti:Natural; di:Natural;
			m:Integer; Result:Integer;
		firstIndexOfTGDZ:Integer:=tgdz'First;
		lastIndexofTGDZ:Integer:=tgdz'Last;
		begin
			if (strLen/=6) then  --在Ada中,汉字是每个字符三个字节
				return 0; 
		       end if;
		charTG:=tgdz(firstIndexOfTGDZ..firstIndexOfTGDZ+2); --第一个索引用First,实际是第一个字节而非第一个 字符(=3字节 inUTF8)
		charDZ:=tgdz(lastIndexofTGDZ-2..lastIndexofTGDZ); --由于Ada中第一个字节的系数可自定义,此处用变量较为安全.
		ti:=Ada.Strings.Wide_Fixed.Index(strTG,charTG);
		di:=Ada.Strings.Wide_Fixed.Index(strDZ,charDZ);
		ti:=(ti-1)/3; --wide_string的搜索,其结果要减1除3,才是汉字序的顺序.
		di:=(di-1)/3;

			if ti >= di then
				m:=ti-di;
			else
				m:=12+ti-di;
			end if;
			Result:= baseYear + m*5 + ti;
			return Result;
	end TGDZtoYear;




	procedure Test(y:integer) is
		by:Integer;
		tgdz:Wide_string(1..6);
		recalY:Integer;
	begin
		Ada.Text_IO.Put("Year: ");	Put(y); 
		by:=CalcBaseYear(y);
		Ada.Text_IO.Put("->  BaseYear ");Put(by);
		Put(",   TGDZ ");
		tgdz:=YeartoTGDZ(y);
		put(tgdz);
		Ada.Text_IO.Put(", RecalBack to Year: ");
		recalY:=TGDZtoYear(tgdz,by);
		Put(recalY);
		New_Line;
		end Test;

end TGDZpackage;

代码在这个IDE显示的效果相当不错,值得截个图记录一下.

源码1

源码2

主要代码(源码2)

IDE gnat pro的控制台对中文支持不好,汉字显示出来变成了⬜⬜.
编译好的文件在cmd下运行,且运行之前把代码页修改为65001以应对UTF8格式的字串输出,效果就正常了.见下图

运行结果

posted @ 2026-02-27 23:09  dingxianghuan  阅读(1)  评论(0)    收藏  举报