Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
procedure TMainWin.AgeEBKeyPress(Sender: TObject; var Key: Char);
procedure ProcessInput(Sender:Tobject);
var age : byte;
begin
Age := StrToInt(AgeEB.Text);
Age := Age+2;
AnsLbl.visible := True //it's here, where there is a mistake
AnsLbl.Caption := 'Bad luck, I"m' + IntTostr(Age) + '-Years old'
if not (Key in ['0'..'9' , chr(vk_return), chr(vk_back)]) then begin
key := #0;
exit
end
This is the code, there is some thing wrong with it, but
Statements need to be separated using the separator symbol, ;.
In the following code, you fail to do this:
AnsLbl.visible := True
AnsLbl.Caption := 'Bad luck, I"m' + IntTostr(Age) + '-Years old'
if ...
You must place separators between these three statements. Typically they are placed at the end of each line like so:
AnsLbl.visible := True;
AnsLbl.Caption := 'Bad luck, I"m' + IntTostr(Age) + '-Years old';
if ...
But they need not be. You could equally write this as:
AnsLbl.visible := True
; AnsLbl.Caption := 'Bad luck, I"m' + IntTostr(Age) + '-Years old'
; if ...
That would be very weird and I am not advocating that you do so. The documentation says this:
Tokens
On the simplest level, a program is a sequence of tokens delimited by
separators. A token is the smallest meaningful unit of text in a
program. A separator is either a blank or a comment. Strictly
speaking, it is not always necessary to place a separator between two
tokens; for example, the code fragment:
Size:=20;Price:=10;
is perfectly legal. Convention and readability, however, dictate that
we write this in two lines, as:
Size := 20;
Price := 10;
Tokens are categorized as special symbols, identifiers, reserved
words, directives, numerals, labels, and character strings. A
separator can be part of a token only if the token is a character
string. Adjacent identifiers, reserved words, numerals, and labels
must have one or more separators between them.
The documentation also has this to say about compound statements:
Compound Statements
A compound statement is a sequence of other (simple or structured)
statements to be executed in the order in which they are written. The
compound statement is bracketed by the reserved words begin and end,
and its constituent statements are separated by semicolons. For
example:
begin
Z := X;
X := Y;
X := Y;
end;
The last semicolon before end is optional. So this could have been
written as:
begin
Z := X;
X := Y;
Y := Z
end;
Compound statements are essential in contexts where Delphi syntax
requires a single statement. In addition to program, function, and
procedure blocks, they occur within other structured statements, such
as conditionals or loops. For example:
begin
I := SomeConstant;
while I > 0 do
begin
...
I := I - 1;
end;
end;
You can write a compound statement that contains only a single
constituent statement; like parentheses in a complex term, begin and
end sometimes serve to disambiguate and to improve readability. You
can also use an empty compound statement to create a block that does
nothing:
begin
end;
It has been a while since i did any Delphi coding but I think you need ; semicolon at the end of each line.
Like for instance this line:
AnsLbl.visible := True
should be:
AnsLbl.visible := True;
Related
I have found that this code compiles both with and without a semicolon at the places pointed out below.
What is the correct way to use semicolons here?
try
try
if MyBoolean = True then
begin
DoSomething;
end
else
begin
DoSomethingElse;
end <<<--- Semi colon here?
except
;
end <<<--- Semi colon here?
finally
;
end;
This is documented behavior:
Declarations and Statements (Delphi): Compound Statements
A compound statement is a sequence of other (simple or structured) statements to be executed in the order in which they are written. The compound statement is bracketed by the reserved words begin and end, and its constituent statements are separated by semicolons. For example:
begin
Z := X;
X := Y;
X := Y;
end;
The last semicolon before end is optional. So this could have been written as:
begin
Z := X;
X := Y;
Y := Z
end;
And also:
Delphi's Object Pascal Style Guide: Statements
Statements are one or more lines of code followed by a semicolon. Simple statements have one semicolon, while compound statements have more than one semicolon and therefore consist of multiple simple statements.
Here is a simple statement:
A := B;
If you need to wrap the simple statement, indent the second line two spaces in from the previous line. Here is a compound, or structured, statement:
begin
B := C;
A := B;
end;
Compound Statements always end with a semicolon, unless they immediately precede an end keyword, in which case the semicolon is optional but recommended by this style guide.
An "end keyword" in your example would include except and finally.
This question already has an answer here:
Delphi check if character is in range 'A'..'Z' and '0'..'9'
(1 answer)
Closed 5 years ago.
for counter := 1 to lengthofpassword do
begin
currentletter:=password[counter];
currentascii:=Ord(currentletter);
if (96<currentascii<123) OR (64<currentascii<91) OR (47<currentascii<58) then
Writeln('valid')
else
asciicheck:=false;
end;
I know this code is wrong but I did it to explain what I want to ask. How can you specify ranges for an if statement? Before, I messed around with lots of if statements and my code wasn't working the way I wanted it to. Basically, I am making a procedure which checks the user input for anything other than uppercase and lowercase alphabet and numbers. This question is different because I was looking for how this problem could be solved using a Case Of statement.
for counter := 1 to lengthofpassword do
begin
currentletter:=password[counter];
currentascii:=Ord(currentletter);
if (currentascii<48) AND (currentascii>57) then
asciipoints:=asciipoints+1;
if (currentascii<65) AND (currentascii>90) then
asciipoints:=asciipoints+1;
if (currentascii<97) AND (currentascii>122) then
asciipoints:=asciipoints+1;
Writeln(asciipoints);
end;
I also tried to do it like this but then realised this wouldn't work because if one statement was satisfied, the others wouldn't be and the points based system wouldn't work either.
Glad you found the answer yourself.
Another way to make sure the password only contains upper and lower case characters and numbers is what I tried to point to: define a set of characters that are valid and check if each character in your password is in these valid characters.
So with a set defined like this:
const
ValidChars = ['A'..'Z', 'a'..'z', '0'..'9'];
you can use statements like
if password[I] in ValidChars then
This statement will however generate a compiler warning in Unicode Delphi, as the type in a set is limited to 256 possible values, and their ordinalities must fall between 0 and 255. This isn't the case for WideChar with 65.536 values. So the set of char defined is in fact a set of AnsiChar. For this task this is acceptable, as every character that needs to be checked is ASCII, so using the function CharInSet will not generate a compiler warning and have a defined behavior - returning False - if the password contains Unicode characters.
This is the resulting code:
const
ValidChars = ['A'..'Z', 'a'..'z', '0'..'9'];
var
I: Integer;
begin
for I := 1 to passwordlength do
begin
if CharInSet(password[I], ValidChars) then
Writeln('valid') // more likely to do nothing and invert the if statement
else
begin
asciicheck := False;
Break; // No need to look further, the check failed
end;
end;
end;
Multiple ranges is best expressed in a case statement:
begin
for counter := 1 to lengthofpassword do
begin
case Ord(password[counter]) of
48..57,
65..90,
97..122 :
Writeln('valid')
else
asciicheck:=false;
end;
end;
end;
Now, this works for characters < #128. If you are working in a unicode application and don't want the restriction of characters being the english alphabet, it is possible to use TCharHelper.IsLetterOrDigit.
if password[counter].IsLetterOrDigit then ...
Thanks to a comment up above, I have found a solution. I ended up using a Case Of statement like this:
for counter := 1 to lengthofpassword do
begin
currentletter:=password[counter];
currentascii:=Ord(currentletter);
case currentascii of
97..122 : asciicheck:=true;
65..90 : asciicheck:=true;
48..57 : asciicheck:=true;
else asciicheck:=false;
end;
end;
Thanks once again.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I need to make a comma separated string which would have multiple string values and each of these value should be in single quote.
When I am using QuotedStr, it is quoting with double-quote,instead of single.
I even tried using single-quote but still it is having same issue.
I tried googling but didn't get any resulting info.
Any other ways to make it ?
Regards.
Vishal
QuotedStr adds a single quotation mark at the beginning and at the end of the string, passed as argument.
What may be misleading is how the debugger shows strings.
For example, the following code
procedure TForm1.Button2Click(Sender: TObject);
var
a, b, c, r: string;
begin
a := 'A';
b := 'B';
c := 'C';
r := QuotedStr(a) + ',' +
QuotedStr(b) + ',' +
QuotedStr(c);
Label2.Caption := r; // breakpoint here
end;
with a break point on the last line shows this in the Local Variables pane:
but the actual label caption looks like this:
The debugger encloses strings in single quotes for display, and because your strings already contains single quotes, it looks like there would be double quotes.
The code that you posted in a comment ...
procedure TForm9.Button2Click(Sender: TObject);
var MyString : String;
begin
//#44
MyString := QuotedStr('String1');
MyString := MyString + ',' + QuotedStr('String2');
ShowMessage(MyString);
end;
... produces this result:
and if the message is expanded with showing the length, like this:
ShowMessage(MyString + ' Length: ' + IntToStr(Length(MyString)));
... it produces this:
Single quotes, length is as expected.
So I'm trying to determine if two different strings are the same with
if DerobModel.ConstructionCount > 22 then
begin
for i := 22 to DerobModel.ConstructionCount-1 do
begin
ConstructionName[i] := DerobModel.Constructions[i].Name;
ShowMessage(ConstructionName[i]);
ShowMessage(DerobModel.HouseProperties.StringValue['NWall']);
if ConstructionName[i]=DerobModel.HouseProperties.StringValue['NWall'] then
begin
ShowMessage('Hej');
igSurf[0]:=idWallCon[i];
end;
LayerCount[i] := DerobModel.Constructions[i].LayerCount;
idWallCon[i] := i+1;
end;
end;
The ShowMessage for both of the strings returns the same string but somehow it won't go in the if statement. Any ideas?
The = operator for strings is known to work. When strings s1 and s2 are equal, s1 = s2 evaluates true. Otherwise it evaluates false. The = operator has been known to work correctly in all versions of Delphi.
The conclusion to draw is that if the body of your if does not execute, then the two strings are not equal. Now that you know that the two strings are not equal, you can debug the program to work out why two things that you believed to be equal are in fact not equal.
Note that equality testing with = is exact. Letter case is significant. Whitespace is significant. And so on.
Your strings are different, simple as that.
If you want to figure out what exactly is different, you could write an else block portion to compare the strings in detail and show you exactly what is different.
if ConstructionName[i]=DerobModel.HouseProperties.StringValue['NWall'] then
begin
ShowMessage('Hej');
igSurf[0]:=idWallCon[i];
end
else
begin
if (Length(ConstructionName[i]) <>
Length(DerobModel.HouseProperties.StringValue['NWall'])) then
begin
ShowMessage('Length('+IntToStr(Length(ConstructionName[i]))+') <> Length('+
IntToStr(Length(DerobModel.HouseProperties.StringValue['NWall']))+')');
end
else
begin
for LCharPos := 1 to Length(ConstructionName[i]) do
begin
if (ConstructionName[i][LCharPos] <>
DerobModel.HouseProperties.StringValue['NWall'][LCharPos]) then
begin
//Here you might need to rather show the ordinal values of the
//characters to see the difference if they **look** the same due
//to the font of the message.
ShowMessage('Pos['+IntToStr(LCharPos)+'] "'+
ConstructionName[i][LCharPos]+'" <> "'+
DerobModel.HouseProperties.StringValue['NWall'][LCharPos]+'"');
end;
end;
end;
end;
The only thing I can think of that might unexpectedly cause "same" strings to be reported as different is: if they are different string types. E.g. if one is WideString and the other AnsiString, then:
There would have to be an implicit conversion to do the comparison.
And this means one of the strings would be changed.
The change could cause two strings that look the same to actually be different.
I'm doing some work with code generation, and one of the things I need to do is create a function call where one of the parameters is a function call, like so:
result := Func1(x, y, Func2(a, b, c));
TStringList.CommaText is very useful for generating the parameter lists, but when I traverse the tree to build the outer function call, what I end up with looks like this:
result := Func1(x, y, "Func2(a, b, c)");
It's quoting the third argument because it contains commas, and that produced invalid code. But I can't do something simplistic like StringReplace all double quotes with empty strings, because it's quite possible that a function argument could be a string with double quotes inside. Is there any way to make it just not escape the lines that contain commas?
You could set QuoteChar to be a space, and you'd merely get some extra spaces in the output, which is generally OK since generated code isn't usually expected to look pretty. String literals would be affected, though; they would have extra spaces inserted, changing the value of the string.
Free Pascal's TStrings class uses StrictDelimiter to control whether quoting occurs when reading the DelimitedText property. When it's true, quoting does not occur at all. Perhaps Delphi treats that property the same way.
Build an array of "unlikely characters" : non-keyable like †, ‡ or even non-printable like #129, #141, #143, #144.
Verify you don't have the 1st unlikely anywhere in your StringList.CommaText. Or move to the next unlikely until you get one not used in your StringList.CommaText. (Assert that you find one)
Use this unlikely char as the QuoteChar for your StringList
Get StringList.DelimitedText. You'll get the QuoteChar around the function parameters like: result := Func1(x, y, †Func2(a, b, c)†);
Replace the unlikely QuoteChar (here †) by empty strings...
What about using the Unicode version of AnsiExtractQuotedStr to remove the quotes?
Write your own method to export the contents of your TStringList to a string.
function MyStringListToString(const AStrings: TStrings): string;
var
i: Integer;
begin
Result := '';
if AStrings.Count = 0 then
Exit;
Result := AStrings[0];
for i := 1 to AStrings.Count - 1 do
Result := Result + ',' + AStrings[i];
end;
Too obvious? :-)
Alternatively, what would happen if you set StringList.QuoteChar to #0 and then called StringList.DelimitedText?
We have written a descendant class of TStringList in which reimplemented the DelimitedText property. You can copy most of the code from the original implementation.
var
LList: TStringList;
s, LOutput: string;
begin
LList := TStringList.Create;
try
LList.Add('x');
LList.Add('y');
LList.Add('Func2(a, b, c)');
for s in LList do
LOutput := LOutput + s + ', ';
SetLength(LOutput, Length(LOutput) - 2);
m1.AddLine('result := Func1(' + LOutput + ')');
finally
LList.Free;
end;
end;
Had the same problem, here's how I fixed it:
s := Trim(StringList.Text)
that's all ;-)