有没有一种方法可以格式化输出的字符串?我正在尝试获得以下输出的美观视图
1: Ashley | 01033438392 | Wellington, New Zealand | 1987- 4-14
2: Aloha | 01087651234 | Hawaii, United States of America | 1988- 9-23
3: Jack | 01082840184 | Beijing, China | 1989- 6-19
如果我用C语言编程,我会这样做
printf("%10s | %11s | %20s | %4d-%2d-%2d\n",name,phone,address,year,month,day);
在Ada 05中可以进行这种格式设置吗?
PS请忽略姓名、电话号码、地址和生日。我在30秒内就编好了……
发布于 2011-05-18 02:11:40
这是可以做到的,但机制有点笨拙,而且相当冗长。
我通常会做的是编写单独的过程来处理更复杂的输出,例如日期,并将其与字符串处理的其余部分一起使用以保持清晰。
package Integer_IO is new Ada.Text_IO.Integer_IO (Integer);
procedure Output_Date ( Day : in Integer; Month: in Integer; Year: in Integer) is
begin
Integer_IO.Put(Item => Day, Width => 2);
Text_IO.Put("-");
Integer_IO.Put(Item => Month, Width => 2);
Text_IO.Put("-");
Integer_IO.Put(Item => Year, Width => 4);
end Output_Date;
procedure Output_String ( Item : in String;
Width : in Integer;
Separator : in String := "|";
Truncate : Boolean := False) is
Field_Index : Integer := Text_IO.Col;
begin
if Item'length > Width and Truncate then
Text_IO.Put(Item(1..Width) & Separator);
else
Text_IO.Put(Item) & Separator;
end if;
Text_IO.Set_Col ( Field_Index + Width + 1 );
end Output_String;
这将强制固定长度字段,这将可选地允许截断长字符串,或者将后续条目移动到下一行。Set_Col将为下一次写入设置行位置,如果当前写入位置已经超过请求的位置,则可能会将其放在下一行上。
我把字符串截断放在这里是为了使用数组切片和Text_IO的输出操作,但我通常不喜欢缺省截断,因为允许字符串超出请求的宽度或在下一行缩进会使格式错误更加明显。
因此,根据上面的代码,打印出类似于第一行的内容可能如下所示:
Name : String := "Ashley"
Phone : String := "01033438392"
Address: String := "Wellington, New Zealand"
Day : Integer := 14;
Month : Integer := 4;
Year : Integer := 1987;
Output_String(Item=> Name, Width => 10);
Output_String(Item=> Phone, Width => 11);
Output_String(Item=> Address, Width => 20);
Output_Date(Day,Month,Year);
Ada中的Text IO通常很麻烦,但通常具有使您正在做的事情相对清晰的优点。
发布于 2011-05-18 03:32:53
请注意,在如今的C++中,printf()
正处于被贬低的边缘,支持使用带有流格式化程序的流。它很方便,但非常不安全(至少在两种意义上)。如今,开发人员被鼓励使用C++ streams (及其分类的操纵器)来代替。
在Ada中,您可以使用字符串连接运算符&
以与C++ streams非常相似的方式操作字符串,而C++人员使用流插入运算符(<<
)。在某些方面,Ada的方法更好,因为您可以嵌套连接表达式,而流插入表达式无法做到这一点。
这里的问题是,像setfill()
、hex
和setw()
这样的C++格式化程序没有任何方便的等价物。确实应该有,而且(hex
除外)自己编写它们并不难,但现在它们还不存在。
例如,setw()/setfill()
等效项如下所示:
Fill_Char : Character := ' ';
function Set_Fill (New_Fill : Character) return String is
begin
Fill_Char := New_Fill;
return "";
end Set_Fill;
--// Dumb tail-recursive implementation.
function Set_Width(Source : in String; Width : in Positive) return String is
begin
if Width <= Source'length then --'
return Source;
else
return Fill_Char & Set_Width(Source, Width - 1);
end if;
end Set_Width;
Unfilled_String : constant String := "123456";
Filled_String : constant String := Set_Width(Unfilled_String & Set_Fill('0'), 8);
--// The above string should end up being "00123456"
如果你真的想要一个printf()
接口,printf()
当然可以从Ada中调用。您必须担心在Ada的大小字符串和C的nul终止字符串之间的转换,但这就是Ada.Interfaces.C.Strings
的作用所在。
发布于 2015-05-24 21:09:55
对于这种特殊的格式设置,有一些辅助工具。
procedure Put(Item : in Num; Width : in Field := Default_Width; Base : in Number_Base := Default_Base);
将Item
右对齐并将空白字符作为填充的字段放入。其中Width
是字段宽度,Base
是10作为默认值。
function Head (Source : in String; Count : in Natural; Pad : in Character := Space) return String;
function Tail (Source : in String; Count : in Natural; Pad : in Character := Space) return String;
返回带格式的字符串。其中Count
是字段宽度,Pad
是字段的填充值。Head
将字符串左对齐。Tail
将字符串向右对齐。
让列宽为8个字符,并使用破折号作为填充符。
Put_Line (Head ("Ashley", 8, '-'));
Put_Line (Head ("Aloha", 8, '-'));
Put_Line (Head ("Jack", 8, '-'));
Put_Line (Tail ("Ashley", 8, '-'));
Put_Line (Tail ("Aloha", 8, '-'));
Put_Line (Tail ("Jack", 8, '-'));
输出
Ashley--
Aloha---
Jack----
--Ashley
---Aloha
----Jack
Attribute discrete_type'Width
返回离散类型需要表示为文本的长度。
示例
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Calendar; use Ada.Calendar;
procedure Test is
subtype Index is Positive range 95 .. 1223;
procedure Put_Line ( I : in out Index; Name : String; Phone : Natural; Address : String; T : in out Time ) is
begin
Put (I, Index'Width);
Put (": ");
Put (Head (Name, 10, ' '));
Put (" | ");
Put (Tail (Phone'Img (Phone'Img'First + 1 .. Phone'Img'Last), 13, '0'));
Put (" | ");
Put (Head (Address, 20, ' '));
Put (Year (T), Year_Number'Width);
Put ("-");
Put (Month (T), Month_Number'Width);
Put ("-");
Put (Day (T), Day_Number'Width);
I := Positive'Succ (I);
T := T + Duration (60 * 60 * 24 * 3);
New_Line;
end;
I : Index := Index'First;
Now : Time := Clock;
begin
Put_Line (I, "Ashley", 1033438392, "Wellington, New Zealand", Now);
Put_Line (I, "Aloha", 01087651234, "Hawaii, United States of America", Now);
Put_Line (I, "Jack", 01082840184, "Beijing, China", Now);
I := Index'Last - 3;
Put_Line (I,"Ashley", 1033438392, "Wellington, New Zealand", Now);
Put_Line (I,"Aloha", 01087651234, "Hawaii, United States of America", Now);
Put_Line (I,"Jack", 01082840184, "Beijing, China", Now);
end;
输出
95: Ashley | 0001033438392 | Wellington, New Zeal 2015- 5- 24
96: Aloha | 0001087651234 | Hawaii, United State 2015- 5- 27
97: Jack | 0001082840184 | Beijing, China 2015- 5- 30
1220: Ashley | 0001033438392 | Wellington, New Zeal 2015- 6- 2
1221: Aloha | 0001087651234 | Hawaii, United State 2015- 6- 5
1222: Jack | 0001082840184 | Beijing, China 2015- 6- 8
我建议为电话号码创建一个类型,我不知道它应该是字符串还是带有标题零的数字,我猜电话号码可以有不同的长度。
https://stackoverflow.com/questions/6032210
复制相似问题