Recent

Author Topic: convert char of ansistring to enum  (Read 5780 times)

toby

  • Sr. Member
  • ****
  • Posts: 251
convert char of ansistring to enum
« on: June 09, 2023, 08:02:03 pm »
if i create enums a and b  where the ord(a) gives 1  and ord(b) gives 2

is there a way to convert an 'a' char (or from an ansistring ab[1] which is 'a') to the enum a?

i was told i could do it in c with a 'struct' but don't know if fpc has this 'struct' capability or i've never used it as such


Red_prig

  • Full Member
  • ***
  • Posts: 143
Re: convert char of ansistring to enum
« Reply #1 on: June 09, 2023, 08:53:32 pm »
smth that:
Code: Pascal  [Select][+][-]
  1.  case str of
  2.   'a':enum_val:=enum_a;
  3.   'b':enum_val:=enum_b;
  4.  end;
  5.  

Roland57

  • Sr. Member
  • ****
  • Posts: 421
    • msegui.net
Re: convert char of ansistring to enum
« Reply #2 on: June 09, 2023, 09:52:36 pm »
You can do it like this:

Code: Pascal  [Select][+][-]
  1. uses
  2.   TypInfo;
  3.  
  4. type
  5.   TCharacter = (a, b, c);
  6.  
  7. var
  8.   s: ansistring;
  9.   v: TCharacter;
  10.  
  11. begin
  12.   s := 'b';
  13.   v := TCharacter(GetEnumValue(TypeInfo(TCharacter), s[1]));
  14.   WriteLn(v); // b
  15. end.
My projects are on Gitlab and on Codeberg.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5448
  • Compiler Developer
Re: convert char of ansistring to enum
« Reply #3 on: June 09, 2023, 10:01:23 pm »
is there a way to convert an 'a' char (or from an ansistring ab[1] which is 'a') to the enum a?

You can use ReadStr to convert a string to a enum value (and WriteStr for the opposite):

Code: Pascal  [Select][+][-]
  1. program tenum;
  2.  
  3. {$mode objfpc}
  4. {$scopedenums on}
  5.  
  6. type
  7.   TTestEnum = (a, b, c);
  8.  
  9. function StrToTestEnum(const aStr: String): TTestEnum;
  10. begin
  11.   ReadStr(aStr, Result);
  12. end;
  13.  
  14. begin
  15.   Writeln(StrToTestEnum('a'));
  16.   Writeln(StrToTestEnum('c'));
  17. end.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9794
  • Debugger - SynEdit - and more
    • wiki
Re: convert char of ansistring to enum
« Reply #4 on: June 09, 2023, 10:10:57 pm »
if i create enums a and b  where the ord(a) gives 1  and ord(b) gives 2

is there a way to convert an 'a' char (or from an ansistring ab[1] which is 'a') to the enum a?

It depends what you need it for.  If speed is a concern you can just use
Code: Pascal  [Select][+][-]
  1. MyEnumStartingAt1 := TMyEnum(ord(SomeChar)-$40);

DANGER DANGER
- Your enum must start at 1 (normally they start at 0), or you have another enum member before a)
- Your enum must have a value for each char that can be there. And they must be in the exact same order.
- This only works for Upper chars, A=0x41  but not a=0x61.

The compiler will do absolutely no checks.
This means you could assign invalid values to the enum. (and then get errors randomly later)



Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: convert char of ansistring to enum
« Reply #5 on: June 09, 2023, 10:17:06 pm »
You can simply use Val() for this (AFAIK you cannot do that in Delphi), and it will not crash upons wrong input like using ReadStr.
Code: Pascal  [Select][+][-]
  1. function TryStrToTestEnum(const aStr: String; out Value: TTestEnum): Boolean;
  2. var
  3.   Code: Integer;
  4. begin
  5.   Val(aStr, Value, Code);
  6.   Result := Code = 0;
  7. end;

Bart

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: convert char of ansistring to enum
« Reply #6 on: June 09, 2023, 10:48:44 pm »
My Version!
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. Type
  3.   TMyEnum = (A,B,C);
  4. begin
  5.   Caption := Byte(b).ToString;
  6. end;                                    
  7.  

I wanted to add that I just wanted to show easy it was to treat a ENUM like any other type But spitting out a text ID of th e ENUM is ok, but I've never found a use for it.
« Last Edit: June 09, 2023, 11:01:22 pm by jamie »
The only true wisdom is knowing you know nothing

toby

  • Sr. Member
  • ****
  • Posts: 251
Re: convert char of ansistring to enum
« Reply #7 on: June 09, 2023, 11:02:31 pm »
I actually tried the code methods Red_prig, PascalDragon and Bart gave but i had the variable getting the result value as a longint in all the code and it didn't even dawn on me that it should be a tenum - i didn't even try it as tenum even after all the searching and resulting pages and even youtube mp4s - i didn't even think it would be even a viable option
though i tried all the integer types and all the real types with no fixes - i took the error in the wrong direction to be fixed
enum.pas(26,16) Error: Incompatible types: got "tenum" expected "LongInt"

my enums are actually
agct a c g t      0 1 2 3 4   so i couldn't use Martin_fr's method as i think he is basing his code on the 'alphabet'

I will do timing testing on all and see which is fastest - but my money is on the case method

Thanks again - now to repair the huge dent in my desktop


toby

  • Sr. Member
  • ****
  • Posts: 251
Re: convert char of ansistring to enum
« Reply #8 on: June 10, 2023, 08:15:48 pm »
i've run into a real timing testing problem

using ord(a) as a index  into an array   arr[ord(a)]  or arr[byte(a)] causes significant excessive time and not worth considering as a method

writeln(ord(g)); // 3
si := '1234';
writeln(si[ord(g)]); // 3

is there a way to use enum g directly as an index ?

writeln(si[g]);    gives error enums.pas(104,12) Error: Incompatible types: got "tenum" expected "QWord"


Red_prig

  • Full Member
  • ***
  • Posts: 143
Re: convert char of ansistring to enum
« Reply #9 on: June 10, 2023, 09:44:37 pm »
create type:
Code: Pascal  [Select][+][-]
  1. type
  2.  TEnumType=(EnumA,EnumB,EnumC);
  3.  TEnumArray=array[TEnumType] of Char;  
  4.  
use array of enum:
Code: Pascal  [Select][+][-]
  1. var
  2.  A:TEnumArray;
  3.  g:TEnumType;
  4. begin
  5.  A:='321'; //The compiler allows you to assign a string to an array of characters
  6.  g:=EnumA;
  7.  writeln(A[g]);
  8. end;
  9.  

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: convert char of ansistring to enum
« Reply #10 on: June 10, 2023, 10:05:13 pm »
How about this?
Code: Pascal  [Select][+][-]
  1. Type
  2.   TTest = (TestA = 'A', TestB = 'B');
  3.  
  4. var
  5.   Test: TTest;
  6.   c: Char = 'B';
  7. begin
  8.   Test := TTest(c);
  9.   WriteLn(Test); // Writes TestB
  10. end.
« Last Edit: June 10, 2023, 10:07:40 pm by Warfley »

toby

  • Sr. Member
  • ****
  • Posts: 251
Re: convert char of ansistring to enum
« Reply #11 on: June 11, 2023, 08:08:21 pm »
thanks Red_prig and Warfley your code is much appreciated

i didn't realize char had to be the type of the array also?  not possible to mix with integer or ansistring?

using 'char' fixed my code

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: convert char of ansistring to enum
« Reply #12 on: June 11, 2023, 09:44:31 pm »
Note that an enum is basically just a set of constants of ordinal type. If you just write:
Code: Pascal  [Select][+][-]
  1. type
  2.   TTest = (T1, T2, T3);
Basically T1 is just the constant 0, T2 is 1 and T3 is 2. You can associate values with these constants directly, as in my example:
Code: Pascal  [Select][+][-]
  1. type
  2.   TTest = (TestA = 'A', TestB, TestD = 'D');
Because char is an ordinal datatype, TestA is basically just a constant for the char A, or in numeric values the value 65, TestB is the next value, so 'B' or numeric 66, and TestD would be the next value (which is 'C'), but because I specifically set it to 'D', it now "skips" 'C'.

So after all this enum is just a set of char (or int) constants, and you can simply convert between them with casts like TTest('A') is TestA, ord(TestA) is 65 and Char(TestA) is 'A'.

If you want to directly look up the name of the enum, you can do this with RTTI or other compiler Features (like ReadStr) as shown in the first few posts. But note that this is a runtime lookup table, while when you are just using ordinals as the underlying values (as shown above) no runtime code is required, as this is just compiletime typechecking. But you are not restricted to ordinals (i.e. char), but may also use full strings

toby

  • Sr. Member
  • ****
  • Posts: 251
Re: convert char of ansistring to enum
« Reply #13 on: June 12, 2023, 08:10:51 pm »
timing 10000 loops of 30000 ansistring comversion to enum
timing is relative as i am using a dual core computer for this

Red_prig (reply 1) case convert ansistring to enumi + byte
timing : 0:0.3.752 seconds

Roland57 (reply 2) typinfo convert ansistring to enum
timing : 0:0.17.61 seconds

PascalDragon (reply 3) readstr convert ansistring to enum
timing : 0:1.12.335   1 minute 12.235 seconds

correction :
i copied the wrong line for this coding method
the real timing is
Bart (reply 5) val convert ansistring to enum
timing : 0:0.14.749   seconds

incorrect timing
Bart (reply 5) val convert ansistring to enum
timing : 0:1.24.193   1 minute 24.193 seconds
« Last Edit: June 12, 2023, 11:46:57 pm by toby »

toby

  • Sr. Member
  • ****
  • Posts: 251
Re: convert char of ansistring to enum
« Reply #14 on: June 12, 2023, 08:16:15 pm »
this program has 3 issues - i hope someone can straighten me out here

Code: Pascal  [Select][+][-]
  1.  
  2. program e2;
  3.  
  4. type
  5.  
  6. // does not cause array index error
  7. tdb = (acgt, a, c, g, t); // zero based array
  8.  
  9. // using either of these  instead of above causes  e2.pas(12,17) Error: enums with assignments cannot be used as array index
  10. tdb = (acgt='0', a='a', c='c', g='g', t='t');
  11. //tdb = (acgt='0', a='1', c='2', g='3', t='4');
  12.  
  13. tdba = array[tdb] of char; // e2.pas(12,17) Error: enums with assignments cannot be used as array index
  14.  
  15. var
  16. //    db : tdb;
  17.     dba : tdba;
  18.     i : longint;
  19.  
  20. begin
  21.  
  22. writeln;
  23.  
  24. dba := '0321123';
  25. writeln('dba : ', dba);
  26. writeln('length(dba) : ', length(dba)); // why only displays 5
  27.  
  28. // uncommented causes Error: Incompatible types: got LongInt expected tdb
  29. //for i := 1 to length(dba) do write(dba[i], ' ');
  30.  
  31. writeln;
  32.  
  33. end.
  34.  
  35.  

 

TinyPortal © 2005-2018