[Info-vax] C limitations, was: Re: VMS process communication
Arne Vajhøj
arne at vajhoej.dk
Sun Apr 16 13:33:05 EDT 2023
On 4/16/2023 1:26 PM, Arne Vajhøj wrote:
> On 4/12/2023 9:33 PM, Johnny Billquist wrote:
>> On 2023-04-12 16:44, Arne Vajhøj wrote:
>>> On 4/12/2023 10:41 AM, Arne Vajhøj wrote:
>>>> On 4/7/2023 4:58 PM, Johnny Billquist wrote:
>>>>> On 2023-04-03 14:31, bill wrote:
>>>>>> On 4/2/2023 8:50 PM, Johnny Billquist wrote:
>>>>>>> On 2023-03-29 19:51, bill wrote:
>>>>>>>> Weird? What about under Primos where chars always have the high
>>>>>>>> order
>>>>>>>> bit turned on? It was called "mark memory parity" but it never
>>>>>>>> made any
>>>>>>>> sense to me when I had to work with it. :-)
>>>>>>>
>>>>>>> I think/suspect that this goes outside the scope of C...
>>>>>>
>>>>>> Of course it does. But it affects C a lot more than other languages
>>>>>> if for no other reason than programming style. How many Unix C
>>>>>> programs
>>>>>> have you seen where parsing is done by looking at the value of a
>>>>>> letter
>>>>>> as opposed to just comparing chars? Even with Primix porting a Unix
>>>>>> program to a Pr1me was a serious task and often not even possible.
>>>>>
>>>>> I don't understand what you mean. Are you just talking about some
>>>>> people assuming you have ASCII, and looking at the decimal values,
>>>>> instead of the character representation. Basically writing 65
>>>>> instead of 'A'?
>>>>> If so, that is certainly something I've seen in lots of languages,
>>>>> and are in fact much more an issue in most other languages that
>>>>> I've used, since they do not consider a thing like 'A' to be a
>>>>> numeric value. C doing that really helps in this context.
>>>>>
>>>>> I'd say it's more common to see C code using the characters instead
>>>>> of their numeric representation just because it is so easy to do in C.
>>>>
>>>> I believe there are basically two groups of languages:
>>>>
>>>> A) those where one can write both c=='A' and c==65
>>>> B) those where one can write c=='A' but c==65 gives a compile error
>>>> and has to be written as ord(c)==65
>>>>
>>>> I find it more likely that group A will use 65 than group B.
>>>
>>> Examples of code:
>>
>> [...lots of code deleted...]
>>
>> The problem with this is that it is very artificial, and designed to
>> prove your point.
>
> Testing if a char is in the digit range is not an artificial problem.
>
> Yes - the example was showing my point - it would have
> been pretty weird if I had produced an example that did
> not show my point.
>
>> I can just as well give a counter example.
>>
>> Let's say you have a character that you know is a digit, and you want
>> to convert it nicely to an integer.
>>
>> In C, you'd do that like this:
>>
>> x = c - '0';
>>
>> In FORTRAN, BASIC, and god knows what else, you'd see:
>>
>> x = ord(c) - 48;
>>
>> Now, I'd say I've seen plenty more of that than your type of example.
>> And I've *never* seen:
>>
>> x = ord(c) - ord('0');
>>
>>
>> And yes, of course, you can also in C do:
>>
>> x = c - 48;
>>
>> but I'd say that is less common, and a bad programmer will always
>> manage to write bad code, no matter what language. That don't mean the
>> language is bad. It is just more unclear, and in C there is no
>> performance reason, or anything else giving any reason why you would
>> write 48, when '0' is so much clearer what the intent is. And then it
>> also works if you use another character set, as long as all the digits
>> have consecutive code points.
>
> I suspect that you are correct that x = c - '0' is more common
> than x = c - 48 in C and x = ord(c) - ord('0') is less common
> than x = ord(c) - 48 in more type safe languages.
>
> But the construct should be very rare overall as most languages
> has easy to use and efficient builtin methods for that.
>
> (and no it is not quite the same for checking if in digit range
> as doing conversion and check for error and regex are a bit
> heavy tools for the task).
And the usual code example to illustrate what I am talking
about.
$ type toint.c
#include <stdio.h>
#include <string.h>
int toint(const char *s)
{
int res;
sscanf(s, "%d", &res);
return res;
}
int tointx(const char *s)
{
int res, i;
res = 0;
for(i = 0; i < strlen(s); i++)
{
res = 10 * res + (s[i] - '0');
}
return res;
}
int tointxx(const char *s)
{
int res, i;
res = 0;
for(i = 0; i < strlen(s); i++)
{
res = 10 * res + (s[i] - 48);
}
return res;
}
void test(const char *s)
{
printf("\"%s\" : %d\n", s, toint(s));
printf("\"%s\" : %d\n", s, tointx(s));
printf("\"%s\" : %d\n", s, tointxx(s));
}
int main(int argc, char *argv[])
{
test("1");
test("12");
test("123");
return 0;
}
$ cc toint
$ link toint
$ run toint
"1" : 1
"1" : 1
"1" : 1
"12" : 12
"12" : 12
"12" : 12
"123" : 123
"123" : 123
"123" : 123
$ type toint.pas
program main(input,output);
type
string = varying [255] of char;
function toint(s : string) : integer;
var
res : integer;
begin
readv(s, res);
toint := res;
end;
function tointx(s : string) : integer;
var
res, i : integer;
begin
res := 0;
for i := 1 to length(s) do begin
res := 10 * res + (ord(s[i]) - ord('0'));
end;
tointx := res;
end;
function tointxx(s : string) : integer;
var
res, i : integer;
begin
res := 0;
for i := 1 to length(s) do begin
res := 10 * res + (ord(s[i]) - 48);
end;
tointxx := res;
end;
procedure test(s : string);
begin
writeln('"', s, '" : ', toint(s):1);
writeln('"', s, '" : ', tointx(s):1);
writeln('"', s, '" : ', tointxx(s):1);
end;
begin
test('1');
test('12');
test('123');
end.
$ pas toint
$ link toint
$ run toint
"1" : 1
"1" : 1
"1" : 1
"12" : 12
"12" : 12
"12" : 12
"123" : 123
"123" : 123
"123" : 123
$ type toint.for
program main
call test('1')
call test('12')
call test('123')
end
c
subroutine test(s)
character*(*) s
integer*4 toint, tointx, tointxx
write(*,'(1x,a,3h : ,i3)') s, toint(s)
write(*,'(1x,a,3h : ,i3)') s, tointx(s)
write(*,'(1x,a,3h : ,i3)') s, tointxx(s)
end
c
integer*4 function toint(s)
character*(*) s
integer*4 res
read(s,'(i)') res
toint = res
end
c
integer*4 function tointx(s)
character*(*) s
integer*4 res, i
res = 0
do 100 i = 1, len(s)
res = 10 * res + (ichar(s(i:i)) - ichar('0'))
100 continue
tointx = res
end
c
integer*4 function tointxx(s)
character*(*) s
integer*4 res, i
res = 0
do 100 i = 1, len(s)
res = 10 * res + (ichar(s(i:i)) - 48)
100 continue
tointxx = res
end
$ for toint
$ link toint
$ run toint
1 : 1
1 : 1
1 : 1
12 : 12
12 : 12
12 : 12
123 : 123
123 : 123
123 : 123
$ type toint.bas
program main
external sub test(string)
call test("1")
call test("12")
call test("123")
end program
!
sub test(string s)
external integer function toint(string)
external integer function tointx(string)
external integer function tointxx(string)
print using '"' + s + '" : ###', toint(s)
print using '"' + s + '" : ###', tointx(s)
print using '"' + s + '" : ###', tointxx(s)
end sub
!
function integer toint(string s)
declare integer res
res = integer(s)
toint = res
end function
!
function integer tointx(string s)
declare integer res, i
res = 0
for i = 1 to len(s)
res = 10 * res + (asc(mid(s,i,1)) - asc("0"))
next i
tointx = res
end function
!
function integer tointxx(string s)
declare integer res
res = 0
for i = 1 to len(s)
res = 10 * res + (asc(mid(s,i,1)) - 48)
next i
tointxx = res
end function
$ bas toint
$ link toint
$ run toint
"1" : 1
"1" : 1
"1" : 1
"12" : 12
"12" : 12
"12" : 12
"123" : 123
"123" : 123
"123" : 123
$ type ToInt.java
public class ToInt {
public static int toInt(String s) {
int res = Integer.parseInt(s);
return res;
}
public static int toIntX(String s) {
int res = 0;
for(int i = 0; i < s.length(); i++) {
res = 10 * res + (s.charAt(i) - '0');
}
return res;
}
public static int toIntXX(String s) {
int res = 0;
for(int i = 0; i < s.length(); i++) {
res = 10 * res + (s.charAt(i) - '0');
}
return res;
}
public static void test(String s) {
System.out.printf("\"%s\" : %d\n", s, toInt(s));
System.out.printf("\"%s\" : %d\n", s, toIntX(s));
System.out.printf("\"%s\" : %d\n", s, toIntXX(s));
}
public static void main(String[] args) throws Exception {
test("1");
test("12");
test("123");
}
}
$ javac ToInt.java
$ java "ToInt"
"1" : 1
"1" : 1
"1" : 1
"12" : 12
"12" : 12
"12" : 12
"123" : 123
"123" : 123
"123" : 123
$ type toint.py
def toint(s):
res = int(s)
return res
def tointx(s):
res = 0
for c in s:
res = 10 * res + (ord(c) - ord('0'))
return res
def tointxx(s):
res = 0
for c in s:
res = 10 * res + (ord(c) - 48)
return res
def test(s):
print('"%s" : %d' % (s, toint(s)))
print('"%s" : %d' % (s, tointx(s)))
print('"%s" : %d' % (s, tointxx(s)))
test('1')
test('12')
test('123')
$ python toint.py
"1" : 1
"1" : 1
"1" : 1
"12" : 12
"12" : 12
"12" : 12
"123" : 123
"123" : 123
"123" : 123
Arne
PS: For the C code I guess that atoi or strtol would actually
be a lot more efficient than sscanf, but there are certainly
functions available.
More information about the Info-vax
mailing list