21

I have used this scenario many times in nearly all my projects, when I'm doing some sort of data conversion, when it comes to booleans, I kinda get a little lost when it comes to making it simple. This statement below sticks out like a sore thumb all over my code:

if BoolVal then
  StrVal:= 'True'
else
  StrVal:= 'False';

I'm wondering if there's an easier way to perform this evaluation? Perhaps some use of the Case statement I don't know about? My actual implementation is more complex than just StrVal but it does consist of returning two different values depending on whether it's True or False. For example, here's some real code...

if fsBold in Can.Font.Style then
  ConvertTo(AddSomeOtherText + 'True')
else
  ConvertTo(AddSomeOtherText + 'False');

That's just to emphasize on how simple I'm hoping. I'm wondering if I can do something along the lines of this:

ConvertTo(AddSomeOtherText + BoolToStrCase((fsBold in Can.Font.Style), 'True', 'False'));

I'm sure that's not a real command, but I'm looking for that type of simplicity in one single line.

Jerry Dodge
  • 26,858
  • 31
  • 155
  • 327
  • Ok that wasn't really "real" code but just as an example that I hate duplicating code for each boolean evaluation. – Jerry Dodge Nov 06 '12 at 00:54
  • Does your language support the ternary operator? StrVal =: BoolVal ? 'True' : 'False' – vgoff Nov 06 '12 at 00:54
  • Strangely, I see that the exact previous question on StackOverflow related to Delphi is also asking how to make a Boolean comparison simple. Different question entirely with different answers, but both of them back-to-back... – Jerry Dodge Nov 06 '12 at 01:13

5 Answers5

45

In the unit StrUtils, there is ifthen()

StrVal := IfThen(BoolVal,'True','False');

And for this specific case you could even use:

StrVal := BoolToStr(BoolVal);
Wouter van Nifterick
  • 23,603
  • 7
  • 78
  • 122
  • BoolToStr has moved to SysUtils in my delphi version (XE4) – DamienD Dec 19 '13 at 15:06
  • 9
    Do be careful with `BoolToStr()`. Its output is `'-1'` and `'0'` when its `UseBoolStrs` parameter is false (the default), and is based on the `TrueBoolStrs` and `FalseBoolStrs` arrays when `UseBoolStrs` is true. So you may not always get `'True'` and `'False'` on all systems. `IfThen()` would be a better choice if you need predictable results. – Remy Lebeau Sep 08 '14 at 06:08
25

Ow com'on nobody ever heard of an array indexed by boolean?

const
  BOOL_TEXT: array[boolean] of string = ('False', 'True');
  YES_NO_TEXT: array[boolean] of string = ('No', 'Yes');
  ERROR_OR_WARNING_TEXT: array[boolean] of string = ('Warning', 'Error');

It is in fact what BoolToStr itself uses!

function BoolToStr(B: Boolean; UseBoolStrs: Boolean = False): string;
const
  cSimpleBoolStrs: array [boolean] of String = ('0', '-1');
Marjan Venema
  • 19,136
  • 6
  • 65
  • 79
7

For converting Boolean to string, there's BoolToStr, which has been around since at least Delphi 2007. You can use it in your last example like this:

TextVal := BoolToStr((fsBold in Can.Font.Style), True);

For going the other direction (string to Boolean), you'd have to do an actual function. Something like this should get you started:

function StringToBoolean(const Value: string): Boolean;
var
  TempStr: string;
begin
  TempStr := UpperCase(Value);
  Result := (TempStr = 'T') or 
            (TempStr = `TRUE`) or 
            (TempStr = 'Y');
end;

BoolVal := StringToBoolean('True');     // True
BoolVal := StringToBoolean('False');    // False
BoolVal := StringToBoolean('tRuE');     // True

Of course, this doesn't work if there's nonsense in Value, but...

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • Thanks, but Wouter's answer actually fills in the empty gap procedure in my question perfectly, my "BoolToStrCase" is really "IfThen" – Jerry Dodge Nov 06 '12 at 00:58
  • +another 1 on the edit but SO won't let me... I've built this already and it supports integers 0/1 or 0/>0 or 0/<>0 etc. – Jerry Dodge Nov 06 '12 at 01:01
  • @KenWhite is TempStr just for training fingers? ;o) - ok, now it makes sense :o) – Sir Rufo Nov 06 '12 at 01:02
  • @SirRufo: Thanks for the catch. :-) Of course, I used it because of the `UpperCase`, but then mistyped it in the code. Thanks again. – Ken White Nov 06 '12 at 01:06
  • @Jerry: Thanks. I'll leave it here in case it helps someone else in the future. – Ken White Nov 06 '12 at 01:07
  • ...Adding on to the fact that I built this already, I was looking for a solution built-in to Delphi so I don't have to always depend on my libraries. – Jerry Dodge Nov 06 '12 at 01:08
  • @Ken. There is a bunch of TryStrToBool etc functions in SysUtils. They work from two arrays of string: `TrueBoolStrs: array of String; FalseBoolStrs: array of String;`, with defaults of `'True'` and `'False'`. They are case-insensitive as well (use AnsiSameText) – Gerry Coll Nov 06 '12 at 03:32
  • @Gerry: Thanks. I'll have to find time to look through `SysUtils` again. :-) I try to write generic answers that are compatible back to D2007 when possible, and didn't notice that this was XE2-tagged. – Ken White Nov 06 '12 at 03:38
  • It is is D2007 - that's what I'm using at the moment! – Gerry Coll Nov 06 '12 at 03:46
  • The TrueBoolStrs/FalseBoolStrs are present in D2006. Maybe even earlier. – Marjan Venema Nov 06 '12 at 08:22
3

Try either of these. Both are way faster than default versions.

type
 TBooleanWordType = (bwTrue, bwYes, bwOn, bwEnabled, bwSuccessful, bwOK, bwBinary);

 BooleanWord: array [Boolean, TBooleanWordType] of String =
  (
    ('False', 'No',  'Off', 'Disabled', 'Failed',     'Cancel', '0'),
    ('True',  'Yes', 'On',  'Enabled',  'Successful', 'Ok',     '1')
  );

function BoolToStr(Value: boolean; const BooleanWordType: TBooleanWordType = bwTrue): String; inline;
begin
   Result := BooleanWord[Value, BooleanWordType];
end;

function StrToBool(const S: String): Boolean; inline;
begin
  Result := False;
  case Length(S) of
    4: Result := (LowerCase(S) = 'true');
    5: Result := not (LowerCase(S) = 'false');
  end;
end;
Eric Santos
  • 131
  • 2
  • 11
  • 1
    This would be converting a string to a boolean, but I'm doing the opposite, boolean to string. – Jerry Dodge Nov 23 '13 at 14:23
  • @JerryDodge Ah let me modify my answer :) I got a solution for that aswell. – Eric Santos Nov 23 '13 at 14:24
  • There's already more answers here than I need, I find it hard to believe there's yet another solution – Jerry Dodge Nov 23 '13 at 14:25
  • @JerryDodge Yes there is and way more flexible ;) – Eric Santos Nov 23 '13 at 14:27
  • The way the StrToBool() function is right now, you can remove the entire `5` case. When you provide 'false', it sets the result to false, but it's already false by default. Also, when you'd call StrToBool('xxxxx'), it's going to return `true`, while 'xxxx' or 'xxxxxx' would return false. I think something like this would be better here: `function StrToBool(const s:string):boolean; var b:TBooleanType; begin for b:=low(TbooleanWordType) to high(TbooleanWordType) do if SameText(BooleanWord[true,b],s) then Exit(True); Exit(False) end;` – Wouter van Nifterick Mar 16 '16 at 18:12
  • This answer helped me to solve an entirely different problem. – Nasreddine Galfout Jun 13 '19 at 18:29
3

If you're into obtuse code, here's a fun way to do it (especially of it's part of a larger Format statement), but be careful if you have more arguments following (or preceding), you will have to index the argument following the boolean explicitly (told you it was obtuse):

Format('The value of value is %*:s', [Integer(value)+1, 'False', 'True']);

Anyone caught using this in production code should be dealt with severely!

Wes
  • 420
  • 5
  • 6