Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Assembling Complex Strings Containing Carriage Returns Prior to Using Ada.Text_IO.Put?

416 views
Skip to first unread message

NiGHTS

unread,
Oct 22, 2014, 1:57:39 AM10/22/14
to
I am converting some code from C to Ada which involves building a complex string containing '\n' characters which would eventually be displayed on the standard output console using the printf() function.

I tried to copy the same strategy of building the string in Ada like this:


Complex_String : Ada.Strings.Unbounded.Unbounded_String;
EOL : String := ASCII.CR'Img;

...

Ada.Strings.Unbounded.Append (Complex_String,
"Menu Title" & EOL &
"-------------------------------------" & EOL
);

...

Ada.Text_Io.Put (
Ada.Strings.Unbounded.To_String( Complex_String ) );


Instead of breaking the line in the places where EOL has been inserted, it seems to show the letters "CR" in its place. Due to the complexity of the final displayed text, I cannot print the text to console before I have run through the entire code which generates the text. The code I am converting involves many "Complex_Strings" which are later printed in a specific order depending on certain criteria only known after the fact. Therefore I need to assemble these generated strings along with the carriage returns before displaying them to the user.

The searches I performed on Google seem to be void of any hints on how to get this working. I can't imagine that I am the only one with this requirement in Ada.


Thanks in advance for your advice.

mockturtle

unread,
Oct 22, 2014, 2:20:35 AM10/22/14
to
On Wednesday, October 22, 2014 7:57:39 AM UTC+2, NiGHTS wrote:
> I am converting some code from C to Ada which involves building a complex string containing '\n' characters which would eventually be displayed on the standard output console using the printf() function.
>
>
>
> I tried to copy the same strategy of building the string in Ada like this:
>
>
>
>
>
> Complex_String : Ada.Strings.Unbounded.Unbounded_String;
>
> EOL : String := ASCII.CR'Img;
>
>
>
> ...
>
>
>
> Ada.Strings.Unbounded.Append (Complex_String,
>
> "Menu Title" & EOL &
>
> "-------------------------------------" & EOL
>
> );
>
>
>
> ...
>
>
>
> Ada.Text_Io.Put (
>
> Ada.Strings.Unbounded.To_String( Complex_String ) );
>
> Instead of breaking the line in the places where EOL has been inserted, it seems to show the letters "CR" in its place.
>
> The searches I performed on Google seem to be void of any hints on how to get this working. I can't imagine that I am the only one with this requirement in Ada.
>
> Thanks in advance for your advice.

Do not use 'Img (that, by the way, I guess it is a GNAT extension). Just do this

EOL : String := "" & ASCII.CR;

or this

EOL : String(1..1) := (1 => ASCII.CR);

These funny syntaxes are necessary if you want EOL to be a string, since CR is a character.

I think that in your case this would work too

EOL : constant Character := ASCII.CR;

Jeffrey Carter

unread,
Oct 22, 2014, 2:25:25 AM10/22/14
to
On 10/21/2014 10:57 PM, NiGHTS wrote:
>
> Complex_String : Ada.Strings.Unbounded.Unbounded_String;
> EOL : String := ASCII.CR'Img;

I presume you're using GNAT; this gives you the image of the enumeration value
CR; I suspect you want the enumeration value (character) itself. Try using

EOL : constant Character := Ada.Characters.Latin_1.CR;

'Img is a non-standard, vendor-dependent attribute; you should not use it in
production code if you have any interest in portability. ASCII is an obsolete
unit and should not be used.

What system uses CR for line terminators these days? I suspect the result will
not be what you expect, which is why a better approach would be to actually
convert this to Ada and simply use a series of Put_Line statements, rather than
trying to copy the mistakes of C in Ada.

> The searches I performed on Google seem to be void of any hints on how to get this working. I can't imagine that I am the only one with this requirement in Ada.

That's because this is not the Ada Way.

--
Jeff Carter
"We call your door-opening request a silly thing."
Monty Python & the Holy Grail
17

Ludovic Brenta

unread,
Oct 22, 2014, 2:28:48 AM10/22/14
to
mockturtle <frame...@gmail.com> writes:
> On Wednesday, October 22, 2014 7:57:39 AM UTC+2, NiGHTS wrote:
>> I am converting some code from C to Ada which involves building a
>> complex string containing '\n' characters which would eventually be
>> displayed on the standard output console using the printf()
>> function.
[...]
>> EOL : String := ASCII.CR'Img;
[...]
> EOL : constant Character := ASCII.CR;

'\n' is not ASCII.CR, it is ASCII.LF, by the way. And on some
nonstandard platforms, the C compiler translates '\n' into a sequence of
two characters, ASCII.CR & ASCII.LF.

--
Ludovic Brenta.

mockturtle

unread,
Oct 22, 2014, 4:12:29 AM10/22/14
to
Oops! touché...

>
> --
>
> Ludovic Brenta.

Björn Lundin

unread,
Oct 22, 2014, 7:15:12 AM10/22/14
to
On 2014-10-22 07:57, NiGHTS wrote:
> I am converting some code from C to Ada which involves building a complex string containing '\n' characters which would eventually be displayed on the standard output console using the printf() function.
>
> I tried to copy the same strategy of building the string in Ada like this:
>
>
> Complex_String : Ada.Strings.Unbounded.Unbounded_String;
> EOL : String := ASCII.CR'Img;
>
> ...
>
> Ada.Strings.Unbounded.Append (Complex_String,
> "Menu Title" & EOL &
> "-------------------------------------" & EOL
> );
>
> ...
>
> Ada.Text_Io.Put (
> Ada.Strings.Unbounded.To_String( Complex_String ) );
>

I use

EOL : constant Character := Ada.Characters.Latin_1.LF;

successfully on unix and on windows, with gnat.

As many pointed out, you want Line_Feed, not Carriage_Return

--
Björn

Maciej Sobczak

unread,
Oct 22, 2014, 10:36:33 AM10/22/14
to

> '\n' is not ASCII.CR, it is ASCII.LF, by the way. And on some
> nonstandard platforms, the C compiler translates '\n' into a sequence of
> two characters, ASCII.CR & ASCII.LF.

What are those nonstandard platforms where the C compiler translates a single character '\n' into a sequence of two characters?
In particular, what happens in the following statement:

const char c = '\n';

?

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com

Dmitry A. Kazakov

unread,
Oct 22, 2014, 10:55:39 AM10/22/14
to
On Wed, 22 Oct 2014 07:36:32 -0700 (PDT), Maciej Sobczak wrote:

>> '\n' is not ASCII.CR, it is ASCII.LF, by the way. And on some
>> nonstandard platforms, the C compiler translates '\n' into a sequence of
>> two characters, ASCII.CR & ASCII.LF.
>
> What are those nonstandard platforms where the C compiler translates a
> single character '\n' into a sequence of two characters?

Maybe I/O library was meant? E.g. when opening file in text mode with fopen
LF will be translated into CR-LF on Windows, or into the physical record
end on VMS.

> In particular, what happens in the following statement:
>
> const char c = '\n';

Considering some crazy platform where char is 2-bytes long, one could say
that C compiler would translate '\n' and all other characters into two
"proper" characters.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Shark8

unread,
Oct 22, 2014, 12:01:05 PM10/22/14
to
On 10/22/2014 12:28 AM, Ludovic Brenta wrote:
> And on some
> nonstandard platforms, the C compiler translates '\n' into a sequence of
> two characters, ASCII.CR & ASCII.LF.

Ah, but CRLF *is* standard for a new line, just look at RFC-822!
So it's the *nix environs that are non-standard! ;)

Jeffrey Carter

unread,
Oct 22, 2014, 12:50:26 PM10/22/14
to
On 10/22/2014 09:01 AM, Shark8 wrote:
>
> Ah, but CRLF *is* standard for a new line, just look at RFC-822!
> So it's the *nix environs that are non-standard! ;)

CR & LF come to us from the Good Old Days of teletypes. CR returned the
mechanism so the next character would print in the 1st column; LF advanced the
paper a line. The 2 were separate so that a CR by itself could be used to
overprint a line.

In my early computing experience we didn't deal with ASCII, much less with
non-graphic control characters. (I'm not even sure if the CDC-6400's 6-bit
character set had those.) Input was either on 80-column punched cards, or in
record-oriented disk files that mimicked punched cards. Output went to 600-LPM
line printers, with paper motion controlled by the 1st character of each line
(space to advance to the next line, '+' to overprint the current line, and '1'
for a form feed).

--
Jeff Carter
"C++ is like giving an AK-47 to a monk, shooting him
full of crack and letting him loose in a mall and
expecting him to balance your checking account
'when he has the time.'"
Drew Olbrich
52

NiGHTS

unread,
Oct 22, 2014, 1:16:46 PM10/22/14
to
Thank you for your help. This is the version that eventually worked for me:

EOL : String(1..2) := (1 => Ada.Characters.Latin_1.CR, 2 => Ada.Characters.Latin_1.LF) ;

Adam Beneschan

unread,
Oct 22, 2014, 1:32:29 PM10/22/14
to
On Tuesday, October 21, 2014 11:28:48 PM UTC-7, Ludovic Brenta wrote:

> '\n' is not ASCII.CR, it is ASCII.LF, by the way. And on some
> nonstandard platforms, the C compiler translates '\n' into a sequence of
> two characters, ASCII.CR & ASCII.LF.

Only when the character is processed for output, I think (to standard output or to a file). Is there really a C compiler which will output 5 for this?

char str[] = "abc\n";
printf("%d\n", strlen(str));

-- Adam

NiGHTS

unread,
Oct 22, 2014, 1:39:02 PM10/22/14
to
Do keep in mind that the strategy of buffering output before sending it to screen is not "old", its "smart". I did consider what you suggested for this particular project, but then I realized that rewriting the code in question to use Put_Line would actually make the code both less readable and far less efficient, both things which are not the Ada way.

While using Put_Line is safer in its portability, its avoidance in this particular instance is comparable to favoring "goto" for a specific section of code after determining the alternative as being more complex or otherwise less desirable.

Thank you for your response.

Adam Beneschan

unread,
Oct 22, 2014, 1:44:30 PM10/22/14
to
On Tuesday, October 21, 2014 10:57:39 PM UTC-7, NiGHTS wrote:
> I am converting some code from C to Ada which involves building a complex string containing '\n' characters which would eventually be displayed on the standard output console using the printf() function.

> I tried to copy the same strategy of building the string in Ada like this:

> Complex_String : Ada.Strings.Unbounded.Unbounded_String;
>
> EOL : String := ASCII.CR'Img;

As others have pointed out, 'Img is a GNAT-defined attribute; it depends on the Ada-defined attribute 'Image. 'Image is not intended to convert a Character to a one-character String. If you say

C : Character := 'x';
S : String := Character'Image (C);

S will have length 3 and will be "'x'".

Character is an enumeration type in Ada, although it's somewhat special. But the rules for 'Image (and its converse, 'Value) are the same as for other enumeration types: they give you (or expect) a string that looks like what the enumeration value would look like in the enumeration declaration. For example, with this enumeration type:

type Color is (RED, GREEN, BLUE);

the 'Image attribute will produce "RED", "GREEN", or "BLUE". (It's always upper-case for identifiers.) And for an enumeration type that has character literals mixed in:

type Whatsit is (This, That, '?');

'Image will produce "THIS", "THAT", or "'?'". (What makes Character special is that if you give it a non-printable character, there are special rules for what 'Image returns; in your case it returned "CR".)

-- Adam

Adam Beneschan

unread,
Oct 22, 2014, 1:47:14 PM10/22/14
to
On Wednesday, October 22, 2014 10:44:30 AM UTC-7, I wrote:

> S will have length 3 and will be "'x'".

In case this is unreadable in your font, it's supposed to be double-quote, single-quote, x, single-quote, double-quote. The three characters inside the double quotes are the characters that make up the string S. Same here:


> 'Image will produce "THIS", "THAT", or "'?'".

The last one is a three-character string.

-- Adam

NiGHTS

unread,
Oct 22, 2014, 1:55:46 PM10/22/14
to
I can make a C compiler right now that will output 5 for that.

But I believe the standard for a non wide string escape character is that it occupies one byte of memory since the standard describes "char" as being one byte wide.

It would not surprise me if printf() would indirectly process \n as \x0A\x0D, perhaps via the stream target driver (stdout). I don't think printf() itself would be written to interpret this character as a two byte in itself.

NiGHTS

unread,
Oct 22, 2014, 2:01:43 PM10/22/14
to
This is clear to me now. I will try to avoid 'Img now that I know its GNAT-specific, or at the very least move it to a file specifically named to be compiled only in gnat. Thank you for your help.

Simon Wright

unread,
Oct 22, 2014, 2:59:30 PM10/22/14
to
Jeffrey Carter <spam.jrc...@spam.not.acm.org> writes:

> CR & LF come to us from the Good Old Days of teletypes. CR returned
> the mechanism so the next character would print in the 1st column; LF
> advanced the paper a line. The 2 were separate so that a CR by itself
> could be used to overprint a line.

And you needed to do it in that order, because CR could take much longer
than LF; do it in the wrong order and the first character of the next
line would be a flying smudge in the middle of the line as the printing
head glanced off the paper.

Shark8

unread,
Oct 22, 2014, 6:34:33 PM10/22/14
to
On 10/22/2014 12:01 PM, NiGHTS wrote:
> This is clear to me now. I will try to avoid 'Img now that I know its GNAT-specific,
> or at the very least move it to a file specifically named to be compiled only in
> gnat. Thank you for your help.

Well, there /are/ places you might want to use it: quick-and-dirty
debugging -- where when you find/fix the problem you remove the 'Img --
and/or if your codebase is going to stay in GNAT. (In its own
self-hosted code would, I imagine, be acceptable.)

But the main thing is to understand that it's non-portable.

Adam Beneschan

unread,
Oct 22, 2014, 7:32:34 PM10/22/14
to
On Wednesday, October 22, 2014 11:01:43 AM UTC-7, NiGHTS wrote:

> This is clear to me now. I will try to avoid 'Img now that I know its GNAT-specific, or at the very least move it to a file specifically named to be compiled only in gnat. Thank you for your help.

If you're concerned about portability, just use 'Image. X'Img is the same as T'Image(X) where T is the type of X.

-- Adam
Message has been deleted

G.B.

unread,
Oct 23, 2014, 7:38:17 AM10/23/14
to
On 23.10.14 01:45, Dennis Lee Bieber wrote:
> On Wed, 22 Oct 2014 19:59:29 +0100, Simon Wright <si...@pushface.org>
> declaimed the following:
> Practice when I first learned BASIC (on an ASR-33 time-share dial-up
> system) was to use the sequence <cr><lf><rubout> to add additional
> buffering time (especially when reading from the paper tape).

My machine had an ingenious mechanism: at the end of line, you did
push a lever which would first move the carriage in such a way
that the head would return to the beginning of the line, and then,
as an effect of some finely tuned resisting mechanism based on
fuzzy logic, it would transform the mechanical force into a
rotary motion. This motion would advance the head downwards
by some distance, allowing the head to continue writing more
characters on the 2-dimensional tape storage.

The distance downwards could be set to a number of discrete
quanta, like 'Small. In effect, this was an easy and flexible
way to adjust memory storage density. It worked in the horizontal
dimension, too, allowing e m p h a s i s of certain important
memory locations at the cost of some tape storage.

Shark8

unread,
Oct 23, 2014, 12:22:38 PM10/23/14
to
And some people found "NOT A TYPEWRITER" to be amusing.

Keith Thompson

unread,
Oct 23, 2014, 9:35:36 PM10/23/14
to
"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> writes:
> On Wed, 22 Oct 2014 07:36:32 -0700 (PDT), Maciej Sobczak wrote:
>>> '\n' is not ASCII.CR, it is ASCII.LF, by the way. And on some
>>> nonstandard platforms, the C compiler translates '\n' into a sequence of
>>> two characters, ASCII.CR & ASCII.LF.
>>
>> What are those nonstandard platforms where the C compiler translates a
>> single character '\n' into a sequence of two characters?
>
> Maybe I/O library was meant? E.g. when opening file in text mode with fopen
> LF will be translated into CR-LF on Windows, or into the physical record
> end on VMS.

Yes. Specifically, that mapping occurs when writing to an output stream
in text mode. The reverse translation happens when reading from an
input stream in text mode.

>> In particular, what happens in the following statement:
>>
>> const char c = '\n';

That sets c to the value of '\n', which is a single byte. It typically
has the value 10, which is the ASCII code of the LF character (but C
doesn't specify ASCII, so it could be something else).

> Considering some crazy platform where char is 2-bytes long, one could say
> that C compiler would translate '\n' and all other characters into two
> "proper" characters.

In C, the type char is exactly one byte. That's the definition of the
word "byte" in C. The constant CHAR_BIT specifies the number of bits in
a byte; it's required to be at least 8 (and is usually exactly 8).

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Randy Brukardt

unread,
Oct 23, 2014, 10:45:25 PM10/23/14
to
"NiGHTS" <nig...@unku.us> wrote in message
news:eaa49258-a9e9-4541...@googlegroups.com...
On Wednesday, October 22, 2014 1:44:30 PM UTC-4, Adam Beneschan wrote:
...
> As others have pointed out, 'Img is a GNAT-defined attribute; it depends
> on the Ada-defined attribute 'Image.

Ah, but Ada 2012.5 :-) will have Object'Image as a language-defined
attribute. AI12-0124-1 was approved for inclusion in the upcoming
Corrigendum at the recent Portland ARG meeting.

This is a case where we (the ARG) decided that including existing practice
in the Standard made sense. (Note that we used 'Image for this purpose;
AdaCore couldn't do that because extending language-defined attributes is
prohibited, but the ARG has no such problems.)

Randy.


0 new messages