Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2005-07

Something like "Is a number"?

16 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Thomas Zastrow

Hello,

I'm converting some strings with "strtoint" into integers. But sometimes the string can't be converted to a number. Is there a function which takes a string and tells me if it is possible or not to convert it into a number? Something like "IsANumber(string)"

Thank you very much!

Greetings,

Tom

Reply by email

John Coppens
to Thomas Zastrow
Show quoted text 7 lines
Hello, I'm converting some strings with "strtoint" into integers. But sometimes the string can't be converted to a number. Is there a function which takes a string and tells me if it is possible or not to convert it into a number? Something like "IsANumber(string)"

You can use val(str, int/real, err)

if err is 0, the string was converted to an integer or real (depending on the type of int/real.

John

Reply by email

Thomas Zastrow
to John Coppens
John Coppens wrote 22 lines
On Fri, 08 Jul 2005 16:39:05 +0200 Thomas Zastrow wrote: >Hello, > >I'm converting some strings with "strtoint" into integers. But >sometimes the string can't be converted to a number. Is there a >function which takes a string and tells me if it is possible or not to >convert it into a number? Something like "IsANumber(string)" > > > You can use val(str, int/real, err) if err is 0, the string was converted to an integer or real (depending on the type of int/real. John

Thank you, it's working!!!

Greetings,

Tom

Reply by email

Florian Klaempfl
to Thomas Zastrow
Thomas Zastrow wrote 25 lines
John Coppens wrote: > On Fri, 08 Jul 2005 16:39:05 +0200 > Thomas Zastrow wrote: > > > >> Hello, >> >> I'm converting some strings with "strtoint" into integers. But >> sometimes the string can't be converted to a number. Is there a >> function which takes a string and tells me if it is possible or not to >> convert it into a number? Something like "IsANumber(string)" >> >> > > You can use val(str, int/real, err) > > if err is 0, the string was converted to an integer or real (depending on > the type of int/real. > > John > > Thank you, it's working!!!

You can also use TryStrToInt from the sysutils unit.

Reply by email

A.J. Venter
to Thomas Zastrow: Thank you, it's working!!! Tom
Show quoted text 9 lines
>You can use val(str, int/real, err) > >if err is 0, the string was converted to an integer or real (depending on >the type of int/real. > >John Thank you, it's working!!!
Yes that's the old Pascal version of StrToInt :) and it had errorchecking :)
Just for the record, like everything it has more than one answer, you could
also have done:
try
 Int := strToInt(Str);
except
 Int := -1 {Or whatever error number}
end;

Or if you wanted to prepend exceptions rather than catch them, the following function could also work have worked (note you have to do a shortString cast, AnsiStrings don't like access by character)

Function IsANumber (InStr : String) : Boolean
Var TempBool : Boolean;
      Str : ShortString;
      I : Integer;
Begin
Str := ShortString(InStr);
TempBool := True;
I := 1;
While (I <= Length(Str)) and (TempBool = True) do
Begin
 TempBool := Str[I] in ['0'..'9'];
 Inc(I);
end;
IsANumber := TempBool
end;

Of course, that's a rather ugly way to do it, I don't suggest it in practice except for very special cases but I put it here to give an idea of the ways you can interact between types. One of Pascal's (and by inheritance object pascal's) greatest features is that it is not only strongly typed but has very strict type checking, which prevents a very large number of the problems C coders face. For starters you don't have to take measures against about a potential buffer overflow every time you use strings, it does mean though that getting data from one type to another is sometimes a little harder than a simple cast (like in say java), but if you understand the ways in which data types are actually implemented and how they relate to each other you can do not only everything you can do in untyped or weakly-typed languages but a great deal more.

Ciao
A.J.

Reply by email

L505
to A.J. Venter: Yes that's the old Pascal version of StrToInt :) and it had errorchecking :) Just for the…

|
| Or if you wanted to prepend exceptions rather than catch them, the following | function could also work have worked (note you have to do a shortString cast, | AnsiStrings don't like access by character)
|

I was under the same impression for a long time, but some of the FPC RTL sources use ansistrings and access by character. The findpart function for example uses ansistrings but accesses by string[n]

For example this compiles and runs.

var
 test:ansistring;
function IsANumber (InStr : AnsiString) : Boolean;
var
  TempBool: Boolean;
  Str: ansiString;
  I: Integer;
begin
 Str := InStr;
 TempBool := True;
 I := 1;
 while (I <= Length(Str)) and (TempBool = True) do
 begin
  TempBool := Str[I] in ['0'..'9'];
  Inc(I);
 end;
 IsANumber := TempBool
end;
begin
 test:='testing';
 test[1]:='p';
 writeln(test);
 test:='5453tyy';
 if IsANumber(test) then
   writeln('yes '+test+' is a number')
 else
   writeln('no, '+test+' is not a number');
 test:='545365';
 if IsANumber(test) then
   writeln('yes '+test+' is a number')
 else
   writeln('no, '+test+' is not a number');
 readln;
end.

So can someone shed the light? Is it just a rumor that ansistrings shouldn't be accessed by character? Only specific situations?

Reply by email

L505
to L505

When a function requires that more than one value must be returned, what are the advantages of returning one of these values in a paramater versus using a record that contains all the data?

Example:
A function needs to return an integer, string, and boolean. Why not just return a record containing an integer, string, and boolean?

Advantages of records:
Surely records are much more legible code design than parameters.

Disadvantages of records:
???
Are paramaters more portable than records, say if you were writing a library (.so or .dll, etc.)?
Can a c++ or c program deal with a pascal record?
How about speed and performance?

Reply by email

Anton Tichawa
to L505
L505 wrote 10 lines
When a function requires that more than one value must be returned, what are the advantages of returning one of these values in a paramater versus using a record that contains all the data? Example: A function needs to return an integer, string, and boolean. Why not just return a record containing an integer, string, and boolean?

When the integer, string, and boolean are logically related, and are typically assigned, copied, allocated, stored or else processed as a whole block, a record should be used anyway.

Show quoted text 5 lines
Advantages of records: Surely records are much more legible code design than parameters.

Yes, especially in function calls, as in your example.

Show quoted text 9 lines
Disadvantages of records: ??? Are paramaters more portable than records, say if you were writing a library (.so or .dll, etc.)? Can a c++ or c program deal with a pascal record? How about speed and performance?

I think the best way is to pass the record as a var parameter, e. g.:

type t_my_record = record
  a: integer;
  b: string;
  c: boolean;
end;
procedure my_procedure(var a_record: t_my_record);

In this case, a simple pointer is passed to my_procedure. This is also the way most C libraries work, passing a pointer to a structure.

When a function returns a record, an additional pointer parameter is passed to it, invisibly to the pascal programmer, and the function fills in the structure pointed to by that parameter.

For this reason, I personally tend to prefer a var-parameter: A function returning a record looks like creating or allocating that record, which is not true. A var-parameter shows, in pascal, a structure similar to what happens on the machine code level. But it's a matter of taste, and, of how the function result is used: When the result is often used as part of expressions, or as a parameter to other procedures, the "result" way is more legible than the "var-parameter" way.

Anton.

Reply by email

L505
to Anton Tichawa

| procedure my_procedure(var a_record: t_my_record); |
| In this case, a simple pointer is passed to my_procedure. This is also | the way most C libraries work, passing a pointer to a structure.

Would a C program be able to call a Pascal SO or DLL file and directly read a record from pascal, as a structure in C? i.e. no hassles required (presuming the record didn't contain strings of course.. let's just say three integers)

|
| When a function returns a record, an additional pointer parameter is | passed to it, invisibly to the pascal programmer, and the function fills | in the structure pointed to by that parameter.

some performance loss then. But not actually twice the memory used to make a copy?

|
| For this reason, I personally tend to prefer a var-parameter: A function | returning a record looks like creating or allocating that record, which | is not true. A var-parameter shows, in pascal, a structure similar to | what happens on the machine code level. But it's a matter of taste, and, | of how the function result is used: When the result is often used as | part of expressions, or as a parameter to other procedures, the "result" | way is more legible than the "var-parameter" way.

Maybe make it easier, a result prefix or something like so could be used:

procedure(integer, string, other, Result_Record);

or

function(integer, string, other, Result_Record): boolean;

or

function(integer, string, other, ResultRecord): boolean;

Researching this topic, I found some arguments and discussions from people using other languages coming across the same questions - such as Ada people questioning the Out keyword in their functions, and so on. I just want to clarify what the best way is.. I do like returning a record since the code appears more clear to me this way, but I suppose I'll use a parameter for performance reasons.

When teaching people Pascal or learning Pascal, I'm sure people will question how a parameter can possibly return a variable.. "isn't that what the result is supposed to do?" So it does feel sort of hackish to do that. It feels very win32api-ish too. In this case, I wish there were a way to make code clearer while still offering the same performance/benefits. I think Result_Record is somewhat of a hack too.. almost like a "workaround" to something that might be possible to improve.. but I'm not so sure if it can. It's real high priority though, since most people know you can return a value as a parameter.

Reply by email

L505

| possible to improve.. but I'm not so sure if it can. It's real high priority | though, since most people know you can return a value as a parameter.

Not real high priority, is what I meant to say.

Reply by email

Anton Tichawa
to L505: | procedure my_procedure(var a_record: t_my_record); | | In this case, a simple pointer…
L505 wrote 11 lines
| procedure my_procedure(var a_record: t_my_record); | | In this case, a simple pointer is passed to my_procedure. This is also | the way most C libraries work, passing a pointer to a structure. Would a C program be able to call a Pascal SO or DLL file and directly read a record from pascal, as a structure in C? i.e. no hassles required (presuming the record didn't contain strings of course.. let's just say three integers)

Yes. Hassles are still there:

1. The pascal record and the C structure have to allocate and pack data the same way, with the same data sizes and semantics (you mentioned strings, but also "int" and "integer" change their size every few years, bool / BOOL / boolean have different semantics, ...)

2. Calling conventions have to match. They can be set using procedure modifiers like "stdcall", "cdecl" etc. You have to check the docs here.

Show quoted text 10 lines
| | When a function returns a record, an additional pointer parameter is | passed to it, invisibly to the pascal programmer, and the function fills | in the structure pointed to by that parameter. some performance loss then. But not actually twice the memory used to make a copy?

No. Even no performance loss. The "additional pointer" is the same as the otherwise used "var parameter". The following two pascal procedure do essentially the same, they just differ in syntax:

function proc_1: t_record;
begin
  result.a := 1;
end;
procedure proc_2(var x: t_record);
begin
  x.a := 1;
end;

The first form, proc_1, is silently converted to the second form, by the compiler.

Show quoted text 30 lines
| | For this reason, I personally tend to prefer a var-parameter: A function | returning a record looks like creating or allocating that record, which | is not true. A var-parameter shows, in pascal, a structure similar to | what happens on the machine code level. But it's a matter of taste, and, | of how the function result is used: When the result is often used as | part of expressions, or as a parameter to other procedures, the "result" | way is more legible than the "var-parameter" way. Maybe make it easier, a result prefix or something like so could be used: procedure(integer, string, other, Result_Record); or function(integer, string, other, Result_Record): boolean; or function(integer, string, other, ResultRecord): boolean; Researching this topic, I found some arguments and discussions from people using other languages coming across the same questions - such as Ada people questioning the Out keyword in their functions, and so on. I just want to clarify what the best way is.. I do like returning a record since the code appears more clear to me this way, but I suppose I'll use a parameter for performance reasons.

At least for free pascal, there is no lack in performance when you "return a record".

Show quoted text 11 lines
When teaching people Pascal or learning Pascal, I'm sure people will question how a parameter can possibly return a variable.. "isn't that what the result is supposed to do?" So it does feel sort of hackish to do that. It feels very win32api-ish too. In this case, I wish there were a way to make code clearer while still offering the same performance/benefits. I think Result_Record is somewhat of a hack too.. almost like a "workaround" to something that might be possible to improve.. but I'm not so sure if it can. It's real high priority though, since most people know you can return a value as a parameter.

I'm not sure if I get your point right, especially concerning Ada ... Anyway, if people question how a parameter can possibly return a value, tell them a "var parameter" allows more than a function result. It allows the called procedure to -act- on the data, including both reading and writing. That would be "in out" in Ada. In Pascal, this is also known as "call by reference", and not necessarily hackish ... Think of a procedure that calculates and inserts the checksum in a telegram that already contains valid data:

procedure insert_checksum(var a_telegram: t_telegram_record);

This procedure reads the telegram data, calculates some sort of checksum and fills in the telegram's checksum field. This cannot be done with the "return a record" method, except when passing the parameter twice (= performance loss).

But, if you just have to return data, without reading it's previous contents, you may use the "return a record" method without performance loss.

Anton.

Reply by email

L505
to Anton Tichawa

| No. Even no performance loss. The "additional pointer" is the same as | the otherwise used "var parameter". The following two pascal procedure | do essentially the same, they just differ in syntax: |
| function proc_1: t_record;
| begin
| result.a := 1;
| end;
|
| procedure proc_2(var x: t_record);
| begin
| x.a := 1;
| end;
|
| The first form, proc_1, is silently converted to the second form, by the | compiler.

Thanks for clearing up that. Same amount of pointers in the end.

| At least for free pascal, there is no lack in performance when you | "return a record".
|
| I'm not sure if I get your point right, especially concerning Ada ... | Anyway, if people question how a parameter can possibly return a value, | tell them a "var parameter" allows more than a function result. It | allows the called procedure to -act- on the data, including both reading

Yes, and useful in recursive situations.. because you don't want to be re-copying the data to another var if it's just going to be re-used again and again anyway. Might as well just add on or modify the existing var over and over again.

| and writing. That would be "in out" in Ada. In Pascal, this is also | known as "call by reference", and not necessarily hackish ... Think of a | procedure that calculates and inserts the checksum in a telegram that | already contains valid data:

Well, confusing especially when you are using code completion/code insight - the vars inside brackets get confusing. You can't tell which vars inside the brackets are result parameters(dummy ones), and which are your working parameters. Unless they were prefixed with Result_ , or unless you really knew the function well (more time in the help docs).

If the variable is prefixed with result_ for example, you at least know while looking at code insight, that this is a result variable, (a dummy variable). It stops you from going into the help docs, or getting confused as much.

The other issue is that people are afraid of global variables or even partially global variables, and all sorts of people say to not use them.. but obviously they are very useful in some situations.

|
| procedure insert_checksum(var a_telegram: t_telegram_record); |
| This procedure reads the telegram data, calculates some sort of checksum | and fills in the telegram's checksum field. This cannot be done with the | "return a record" method, except when passing the parameter twice (= | performance loss).

Right, so definitely use the right tool for the right job. I've done this a few times where it makes sense to use the existing var to modify existing data. I just have failed to acknowledge those situations it seems (hehe).

One could go as far as never even using functions at all, and just using procedures. But definitely more readable if you utilize them in the right situations. I think for code insight and clarity purposes I'll stick to returning data as value where possible. But like you say, when modifying existing data, utilize the "passing a parameter" or "call by reference" way It will be more effiecient and offers less code noise and var copying.

Reply by email

L505
to L505

Anyone know what Jason Sage's current working email address is? His Hotmail appears to be down. I wanted to check the sage API and his files. If he doesn't' have FTP access I can upload his files to z505 ftp.

Also, if anyone else has files that have gone dead, let me know, send, and I'll put em up.

Regards.

Reply by email

Florian Klaempfl
to L505: | | Or if you wanted to prepend exceptions rather than catch them, the following |…
L505 wrote 57 lines
| | Or if you wanted to prepend exceptions rather than catch them, the following | function could also work have worked (note you have to do a shortString cast, | AnsiStrings don't like access by character) | I was under the same impression for a long time, but some of the FPC RTL sources use ansistrings and access by character. The findpart function for example uses ansistrings but accesses by string[n] For example this compiles and runs. var test:ansistring; function IsANumber (InStr : AnsiString) : Boolean; var TempBool: Boolean; Str: ansiString; I: Integer; begin Str := InStr; TempBool := True; I := 1; while (I <= Length(Str)) and (TempBool = True) do begin TempBool := Str[I] in ['0'..'9']; Inc(I); end; IsANumber := TempBool end; begin test:='testing'; test[1]:='p'; writeln(test); test:='5453tyy'; if IsANumber(test) then writeln('yes '+test+' is a number') else writeln('no, '+test+' is not a number'); test:='545365'; if IsANumber(test) then writeln('yes '+test+' is a number') else writeln('no, '+test+' is not a number'); readln; end. So can someone shed the light? Is it just a rumor that ansistrings shouldn't be accessed by character? Only specific situations?

Disadvantage:
- it's slow because it calls unique,i.e. ensures that the reference counter is 1

Reply by email

Marco van de Voort
to L505: | procedure my_procedure(var a_record: t_my_record); | | In this case, a simple pointer…
Show quoted text 8 lines
| procedure my_procedure(var a_record: t_my_record); | | In this case, a simple pointer is passed to my_procedure. This is also | the way most C libraries work, passing a pointer to a structure. Would a C program be able to call a Pascal SO or DLL file and directly read a record from pascal, as a structure in C? i.e. no hassles required (presuming the record didn't contain strings of course.. let's just say three integers)

Portability is more between specific compilers than between languages.

If the C compiler can be configured to match whatever recordlayout the Pascal compiler is using, then it works.

P.s. I'd recommend against using complex types as a parameter result. It is unoptimal. Unless there is a very good reason to pair them into a record, I'd simply use multiple var parameters, and use the return value for the success or failure indicator of the function.

Reply by email