Pascal - C (2)

C

CBFalconer

.... snip ...


It's strncpy that doesn't give a terminating '\0'; strncat copies
at most count characters from the source string to the end of the
dest string and then adds a '\0'. (I *did* say that it was
confusing. I had to check the man page to see which strncat was.
I just checked N1124, and it agrees with the man page (7.21.3.2).)

I suggest ignoring strncpy and its nuisances, and using strlcpy and
strlcat. These names are reserved, but you can change them.
Source code in standard C, and full documentation, are all
available at:

<http://cbfalconer.home.att.net/download/strlcpy.zip>
 
L

Lew Pitcher

Oops. My apologies to Keith Thompson and the rest of comp.lang.c

I meant to post my reply, but I hit "mail to" instead.
Here's my reply, posted.


Lew Pitcher said:
On November 1, 2008 17:43, in comp.lang.c, Ruud ([email protected])
wrote: [...]
2) In Pascal there exists the "in" function. Example:

if (c in ['A'..'F', '0'..'9']) then { c is hexadecimal }

This can be translated like:

if ( ((c >= 'A') && (c <= 'Z'))
|| ((c >= '0') && (c <= '9'))) .... // c is hexadecimal

Actually, no it can't.
[...]

*But*, your C "translation" of the Pascal code is incorrect. In C, the
only "target characterset" characters required to be in ascending,
sequential order are the values from '0' to '9'. The target characterset
is /not/ obliged to support ascending sequential 'A' to 'Z', and indeed,
some target charactersets (notably all the EBCDIC variants) insert
additional characters /between/ various alphabetics. On an EBCDIC-US
machine, your code would accept as alphabetic about a dozen unprintable
characters, along with '}' and '\', between 'A' and 'Z' inclusive.

You're assuming that Pascal does require the letters 'A'-'Z' to have
sequential codes.

Not really. I know (with support from a couple of my old PASCAL
books: "Algorithms + Data Structures = Programs" by Nicklaus Wirth,
and "Microcomputer Problem Solving using PASCAL" by Kenneth L. Bowles) that
the PASCAL set ['A'..'F'] enumerates out to 'A', 'B', 'C', 'D', 'E', 'F'.
Similarly, the PASCAL set ['A'..'Z'] enumerates out to all the uppercase
characters from 'A' to 'Z' inclusive, and nothing else.

In any case, I was talking C, not PASCAL.

Can we agree that the C expression
((c >= 'A') && (c <= 'Z'))
(for a char c) is platform and characterset specific, and that in some
target charactersets, the expression /will not/ result in a "false" value
for some non-alphabetic characters?
I don't know whether it does or not, but my guess
is that it doesn't,

It doesn't matter. We're not talking about PASCAL handling a range of
characters. Instead we're talking about the equivalence of a PASCAL "set"
to a /C/ range of characters. And, there are some times when the
PASCAL "set" and the C range do not match.
any more than C does. I'm sure there have been
Pascal implementations for EBCDIC-based systems.

True, but beside the point.
--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
D

dj3vande

CBFalconer said:
I suggest ignoring strncpy and its nuisances, and using strlcpy and
strlcat.

The case I was commenting on was one of the (admittedly few) cases
where strncat makes it *easier* to do The Right Thing than strlcat
would.


dave
 
P

Pilcrow

Ruud wrote:
Sorry, no. One alternative is to use a regular expression library if
you have a lot of these.

Please. Point me to a regular expression library for C. Please.
 
K

Keith Thompson

Lew Pitcher said:
Lew Pitcher said:
On November 1, 2008 17:43, in comp.lang.c, Ruud ([email protected])
wrote: [...]
2) In Pascal there exists the "in" function. Example:

if (c in ['A'..'F', '0'..'9']) then { c is hexadecimal }

This can be translated like:

if ( ((c >= 'A') && (c <= 'Z'))
|| ((c >= '0') && (c <= '9'))) .... // c is hexadecimal

Actually, no it can't.
[...]

*But*, your C "translation" of the Pascal code is incorrect. In C, the
only "target characterset" characters required to be in ascending,
sequential order are the values from '0' to '9'. The target characterset
is /not/ obliged to support ascending sequential 'A' to 'Z', and indeed,
some target charactersets (notably all the EBCDIC variants) insert
additional characters /between/ various alphabetics. On an EBCDIC-US
machine, your code would accept as alphabetic about a dozen unprintable
characters, along with '}' and '\', between 'A' and 'Z' inclusive.

You're assuming that Pascal does require the letters 'A'-'Z' to have
sequential codes.

Not really. I know (with support from a couple of my old PASCAL
books: "Algorithms + Data Structures = Programs" by Nicklaus Wirth,
and "Microcomputer Problem Solving using PASCAL" by Kenneth L. Bowles) that
the PASCAL set ['A'..'F'] enumerates out to 'A', 'B', 'C', 'D', 'E', 'F'.
Similarly, the PASCAL set ['A'..'Z'] enumerates out to all the uppercase
characters from 'A' to 'Z' inclusive, and nothing else.

In any case, I was talking C, not PASCAL.

When I learned Pascal (<NAMEDROP>from Ken Bowles</NAMEDROP>), that was
the assumption, but then we were using ASCII-based systems.

I just grabbed a copy of iso7185.pdf, ISO 7185:1990. My reading is
that ['A'..'Z'] specifies the set of all char values >='A' and <='Z';
on a system where the representation of type char is EBCDIC, it would
include all the uppercase letters *plus* several other characters.
Can we agree that the C expression
((c >= 'A') && (c <= 'Z'))
(for a char c) is platform and characterset specific, and that in some
target charactersets, the expression /will not/ result in a "false" value
for some non-alphabetic characters?
Certainly.


It doesn't matter. We're not talking about PASCAL handling a range of
characters. Instead we're talking about the equivalence of a PASCAL "set"
to a /C/ range of characters. And, there are some times when the
PASCAL "set" and the C range do not match.


True, but beside the point.

See above.

Yes, Pascal is off-topic, but the original question was how to write C
equivalent to a certain chunk of Pascal code, so we need to understand
what the Pascal means; we could (and do) as easily discuss nuances of
English grammar when the problem is described in English.
 
K

Keith Thompson

Pilcrow said:
Please. Point me to a regular expression library for C. Please.

A Google search for "C regular expression library" gets about 441,000
hits; many of the first few appear to be quite relevant.
 
N

Nick Keighley

jacob navia wrote:

Then please be a good man and tell me what level I should have before
I can attend this group?

Jacob was talking rubbish

Chuck wrote:


The book isn't the problem, see next.

Richard wrote:

Ruud, you use an odd quoting convention doesn't your
news software support the more usual conventions
(all the attributions at the top)?
The problem is not knowing all those available functions.

yes, I remember all those functions and headers looked pretty
forbidding when I started learning C (also from pascal).
It didn't help that my implementation didn't distinguish
non-standard from standard headers.
And knowing
another language is a disavantage as well: instead of reading the book
line by line, one tends to look just at "how is this done in C".

K&R is pretty good for getting C idioms over. It really is
worth ploughing through K&R and doing the exercises. It's
not a big book (though information dense).

And even reading the book line by line isn't a guarantee for success:

there are no guarantees!
I justed searched the book "C in 21 days"

"xyz in small number days" isn't usually a promising title.
Really, give K&R a try.

I've got a book that promises to teach me to ride a horse in
a weekend...
for 'isdigit' and only found
one source file using this function. OTOH, this source file also
mentioned the function 'isspace' and this function does exactly what
one of my own made function does; detecting white space.


Not mentioned at all "C in 21 days"

oh dear. sprintf() is *really* useful.
:( Because 'printf' was well
explained, I never used the help function of Borland C to give it a
better look. I wish I had because I just did: I learned nothing new
about 'printf' but the page also mentioned 'sprintf' and many more
other functions.
strncat(Str1, &Str3[5], 1);

Here I have no excuse, it is mentioned very clearly in the book.


--
Nick Keighley

"ALGOL 60 was a language so far ahead of its time that it
was not only an improvement on its predecessors but also
on nearly all its successors".
--C.A.R. Hoare
 
N

Nick Keighley

(e-mail address removed) wrote:
[Copying a single character into a string]
This is also a case where strncat's (generally confusing)
interpretation of its count argument turns out to be useful:
    strcpy(Str1,Str2);
    strncat(Str1,Str3+5,1);
(But be careful using this one in code that has to be maintained.)
    ... and now you need to tack on the terminating '\0'
that strncat() didn't give you.
It's strncpy that doesn't give a terminating '\0'; strncat copies at
most count characters from the source string to the end of the dest
string and then adds a '\0'.  (I *did* say that it was confusing.  I
had to check the man page to see which strncat was.  I just checked
N1124, and it agrees with the man page (7.21.3.2).)

     (Sigh.)  Not my day, is it?  I must have forgotten not
to take my stupid pills ...

I have a reflex, as soon as I see a string of the form strn* in a post
I start to post my standard "strncpy() may not do what you expect"
reply. I had it all composed and ready to send when I noticed he
was using strncat(). So I pressed Discard instead of Send.
But it was close :)
 
A

Antoninus Twink

I suggest ignoring strncpy and its nuisances, and using strlcpy and
strlcat.  These names are reserved, but you can change them.
Source code in standard C, and full documentation, are all
available at:

  <http://[spam snipped]>

So you bash powerful functions like asprintf(), but advocate trivial,
ten-liner functions like strlcpy() and strlcat()?

Yes, funny how that works, isn't it?

I often wonder what motivates CBF to post his spamming crap about
strlcpy, ggets, etc. time and time again. Maybe he makes ad revenue from
his site, or maybe it's just the ego trip of looking at his logs and
counting the number of people he manages to gull into making the mistake
of downloading his unreadable garbage.
 
A

Antoninus Twink

Jacob was talking rubbish

No, he wasn't.

He was clearly addressing Collins' arrogance in wading into a
conversation with an air of authority and spouting nonsense. Jacob was
clearly criticizing people who pretend to be C experts while in fact
talking nonsense, not newbies with genuine questions.
 
C

CBFalconer

.... snip ...


So you bash powerful functions like asprintf(), but advocate
trivial, ten-liner functions like strlcpy() and strlcat()?

Definitely. Especially functions whose complete action is easily
described. Above all when they replace variadic (and thus error
prone) functions.
 
R

robertwessel2

       strcpy(Str1, Str2);
       Str1[ strlen(Str2) ] = Str3[5];
       Str1[ strlen(Str2) ] = '\0';
That last line looks wrong to me; I think you want to add 1 to
strlen(Str2) before you use it as an index into Str1.

     Right you are.  Thanks.


Actually you need to save the result of the strlen() in the second
line, since the assignment in the second line will eliminate the NUL
in Str1.
 
D

dj3vande

strcpy(Str1, Str2);
Str1[ strlen(Str2) ] = Str3[5];
Str1[ strlen(Str2) ] = '\0';
That last line looks wrong to me; I think you want to add 1 to
strlen(Str2) before you use it as an index into Str1.

Right you are. Thanks.

Actually you need to save the result of the strlen() in the second
line, since the assignment in the second line will eliminate the NUL
in Str1.

Look more closely.
He's giving strlen one string, and modifying a different one.


dave
(made the same mistake on the first reading)
 
R

robertwessel2

(e-mail address removed) wrote:
       strcpy(Str1, Str2);
       Str1[ strlen(Str2) ] = Str3[5];
       Str1[ strlen(Str2) ] = '\0';
That last line looks wrong to me; I think you want to add 1 to
strlen(Str2) before you use it as an index into Str1.
     Right you are.  Thanks.
Actually you need to save the result of the strlen() in the second
line, since the assignment in the second line will eliminate the NUL
in Str1.

     Having made two mistakes already in this thread, it is with
some trepidation that I maintain you're wrong here.  Look again
at the function argument ...


Ugh. My mistake. Too much string copying going on in this thread!
 
P

Paul Hsieh

Hallo allemaal,

During the conversion of my program from Pascal to C, I was more
or less able to find the C equivalent of most Pascal functions so
far. Only four gave me some real trouble. I solved them but it
could be I overlooked something.

1) In Pascal you can declare functions inside a function. AFAIK
this is not possible with C. Or am I wrong?

Correct. C does not support the concept of locally scoped or
anonymous functions. That said, locally scoped functions are rarely a
serious issue.
2) In Pascal there exists the "in" function. Example:

   if (c in ['A'..'F', '0'..'9']) then { c is hexadecimal }

This can be translated like:

   if (   ((c >= 'A') && (c <= 'Z'))
       || ((c >= '0') && (c <= '9'))) .... // c is hexadecimal

I just wonder if there is a more simpler solution.

The above C translates to:

if (isalnum (c)) { ... }

The Pascal is doing something different, more like:

if (isdigit (c) || (isalpha(c) && c == toupper(c))) { ... }

Except of course none of this is strictly true since in C your program
may launch nuclear missiles towards Russia if the variable c is non-
ASCII.
3) In Pascal I can "add" lines:

  Line1 = 'File size:' + sSize + ' bytes.';

My solution:

  strcpy(Line1, "File size:");
  strcat(Line1, sSize);
  strcat(Line1, " bytes.);

Again, I just wonder if there is a more simpler solution.

C sucks for strings. You can try something like sprintf (Line1, "File
size:" "%s" " bytes", sSize); and hope you don't buffer overflow, but
you really don't have Pascal's self managed string semantics in the
core language.

Have no fear, though. You can use string libraries such as mine
http://bstring.sf.net/ to make life a whole lot better:

bformata (Line1 = bfromcstr ("File size:"), "%s bytes", sSize);

This has almost exactly the same semantic behavior as Pascal.
4) In Pascal I can "add" just one character of another string:

  Str1 = Str2 + Str3[5];

Unfortunately  strcat(Str1, Str3[5]);  doesn't work, I get an
error message. My solution:

  Str4[0] = Str3[5];
  Str4[1] = 0;
  strcpy(Str1, Str2};
  strcat(Str1, Str4};

It works but in this case I'm certainly not happy with the
solution. Is there a better way?

Well using the Better String library its just:

bconchar (Str1 = bfromcstr (bdata (Str2)), bchare (Str3, 5));

But your questions are well motivated. Bare C is just really weak for
really simple fundamental things which is trivial in most programming
languages. To learn how do this right in straight C correctly you
just have to learn all of C's weaknesses. Libraries such as mine help
tremendously just for strings, but you still kind of have to learn the
C way of doing things.
 
D

dj3vande

Nick Keighley said:
I have a reflex, as soon as I see a string of the form strn* in a post
I start to post my standard "strncpy() may not do what you expect"
reply.

strncpy does exactly what I expect; it's just not usually what I want,
so I either use something else instead or use strncpy followed by some
fixup code.
I had it all composed and ready to send when I noticed he
was using strncat(). So I pressed Discard instead of Send.
But it was close :)

Yep. strncat is the one I always have to look up; the way it
interprets its count argument is about as unlikely as it could possibly
be without looking like it was deliberately designed to be confusing.
(But writing that post did shed some light on what it might've been
designed for.)


dave
 
D

David Thompson

Lew Pitcher said:
On November 1, 2008 17:43, in comp.lang.c, Ruud ([email protected])
wrote: [...]
2) In Pascal there exists the "in" function. Example:

if (c in ['A'..'F', '0'..'9']) then { c is hexadecimal }

This can be translated like:

if ( ((c >= 'A') && (c <= 'Z'))
|| ((c >= '0') && (c <= '9'))) .... // c is hexadecimal
Corrected elsethread to 'F'.
Actually, no it can't.
[...]

*But*, your C "translation" of the Pascal code is incorrect. In C, the
only "target characterset" characters required to be in ascending,
sequential order are the values from '0' to '9'. The target characterset
is /not/ obliged to support ascending sequential 'A' to 'Z', <snip>

You're assuming that Pascal does require the letters 'A'-'Z' to have
sequential codes. I don't know whether it does or not, but my guess
is that it doesn't, any more than C does. I'm sure there have been
Pascal implementations for EBCDIC-based systems.

<Spock> Indeed. </> ISO 7185-1990 6.4.2.2 d:
1) The subset of character values representing the digits 0 to 9 shall
be numerically ordered
and contiguous.
2) The subset of character values representing the upper case letters
A to Z, if available,
shall be alphabetically ordered but not necessarily contiguous.
3) The subset of character values representing the lower case letters
a to z, if available, shall
be alphabetically ordered but not necessarily contiguous.

For EBCDIC, A-F are contiguous, though A-Z aren't.
So the particular case wanted here would in fact work;
but other cases wouldn't, making it a poor habit.

- formerly david.thompson1 || achar(64) || worldnet.att.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Pascal -> C 16
Beginner at c 0
Help with C negative indexes 2
C++ vs Pascal 38
Getting an exception.., 10
Is there a Lazarus equivalent for C++ available? 4
Using multiple files in (Borland) C 13
strcat and three strings 1

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,194
Latest member
KarriWhitt

Latest Threads

Top