Making a character variable equal to a nill value

2019-08-28 16:39发布

问题:

I am creating a programme where I am searching for vowels within a string, and after they have been found, the vowels need to be removed from the string.

 mystring := 'August'   ;

{if mystring[1] IN ['A','E','I','O','U'] ;}
for k := 1 to length(mystring) DO
BEGIN
if mystring[K] IN ['a','e','i','o','u']
then mystring[k] := ''

but the error

Incompatible types: 'Char' and 'String' " appears

What can i do to delete the vowels from my string?

回答1:

What you are looking for is a null character value. You are trying to use the empty string, which is an entity with zero length. But there is no character than has zero length. The null character value that you are looking for simply does not exist.

Another way to see this is to consider what Length(mystring) is at the end of your loop. No matter what characters you assign with mystring[k] := ..., the length of mystring is never modified.

So, you could make a new string instead of modifying the existing one. For example:

var 
  new: string;
  len: Integer;
....
SetLength(new, Length(mystring));
len := 0;
for i := 1 to Length(mystring) do
begin
  if not (mystring[i] in ['a','e','i','o','u']) then
  begin
    inc(len);
    new[len] := mystring[i];
  end;
end;
SetLength(new, len);
mystring := new;

Or you could make repeated calls to StringReplace:

mystring := StringReplace(mystring, 'a', '', [rfReplaceAll]);
mystring := StringReplace(mystring, 'e', '', [rfReplaceAll]);
//etc. 

This version using StringReplace is slower than the first approach.

Yet another approach would be to operate in place:

var 
  len: Integer;
....
len := 0;
for i := 1 to Length(mystring) do
begin
  if not (mystring[i] in ['a','e','i','o','u']) then
  begin
    inc(len);
    mystring[len] := mystring[i];
  end;
end;
SetLength(mystring, len);


回答2:

Or this one:

VAR
  I : Cardinal;

BEGIN
  I:=1;
  WHILE I<=LENGTH(MyString) DO
    IF MyString[I] IN ['a','e','i','o','u','A','E','I','O','U'] THEN
      DELETE(MyString,I,1)
    ELSE
      INC(I)
END;

David's code is probably faster, but this one doesn't need any additional string. Also, this one also takes care of upper-case vowels (if that's what you want).



回答3:

Just another suggestion for your evaluation:

for i := 1 to Length(mystring) do
  if mystring[i] in ['a', 'e', 'i', 'o', 'u'] then
    mystring[i] := #1;
mystring := StringReplace(mystring, #1, '', [rfReplaceAll]);

The ideia is to replace all the vowels by the character #1 (#0 doesn't work). The loop does that. Then, all #1 in the string are removed by replacing them by an empty string, what is achieved by the function StringReplace.



回答4:

You can do it like :

localStr:=mystring;
mystring:='';
if ... then mystring:=mystring+localStr[i];

example

mystring:= 'August';
...

var
localStr: string;
i       : Integer;
begin
localStr:=mystring;
mystring:='';
for i := 1 to Length(localStr) do if NOT ((localStr[i] in ['a','e','i','o','u'])) then
              mystring:=mystring+localStr[i];
end;

Result mystring : Agst


For the experts :

Never thought the StringReplace with only one sign, is so slow.
If string is 474000 bytes. This test takes 2 minutes and 5 seconds.

User        Code in short
--------------------------------------------

David       inc(len) | new[len] := mystring[i] | SetLength(new, len)
David 2.    inc(len) | mystring[len] := mystring[i] | SetLength(mystring, len)
TLama       if not (C^ in CharSet) then | localStr[I] := C^ | Inc(I)
Me          localStr:=mystring | mystring:='' | mystring:=mystring+localStr[i]
AlexSc      mystring := StringReplace(mystring, #1, '', [rfReplaceAll])
HeartWare   I := 1                  | WHILE I<=LENGTH(MyString) DO  | DELETE(MyString,I,1) | INC(I)
 " DEC(I)   I := LENGTH(MyString)   | WHILE I > 0 DO                | DELETE(MyString,I,1) | DEC(I)

HeartWare DEC(I) is only to show that delete downto is faster

The Test in seconds.

            length(mystring)--MB--------------------
            0.474       1.049       4.002       7.995       15.358      56.948
----------------------------------------------------                
Delphi 5 on XP
----------------------------------------------------            
TLama   :   0.003       0.016       0.047       0.078       0.172       0.687
David   :   0.003       0.016       0.047       0.093       0.192       0.765
David 2.:   0.003       0.016       0.063       0.109       0.219       0.875

Me      :   0.125       0.281       1.109       2.192       4.203
HeartWare:  27.284      131.057
 " DEC(I):  21.793      108.406
AlexSc  :   143.723     break > 8 min.

Rad XE4 on vista
----------------------------------------------------            
TLama   :   0.003       0.032       0.068       0.139       0.194
David   :   0.003       0.032       0.068       0.146       0.203
Me      :   0.094       0.172       0.481       0.921       1.576
HeartWare:  23.056      119.076
 " DEC(I):  17.519      103.319
AlexSc  :   125.082     break > 8 min.


标签: delphi char