Entwickler-Ecke

Sonstiges (Delphi) - Pos, Copy, LowerCase, UpperCase - String konvertieren


galagher - Fr 12.06.09 09:43
Titel: Pos, Copy, LowerCase, UpperCase - String konvertieren
Hallo!

Ich wende mich an die String-Spezialisten unter euch:
Ich möchte aus dem folgenden String

Quelltext
1:
aBc _@upper def _@lower GHI                    

das machen:

Quelltext
1:
aBc DEF ghi                    


Das schaffe ich nicht, ich erhalte immer nur

Quelltext
1:
aBc DEF _@LOWER GHI                    


Ich will also _@upper und _@lower aus dem String herausnehmen und je nachdem
- alles ab _@upper bis zum nächsten _@lower oder bis zum Stringende in Grossbuchstaben konvertieren
- alles ab _@lower bis zum nächsten _@upper oder bis zum Stringende in Kleinbuchstaben konvertieren.

Ich habe da mit Pos und Copy experimentiert, das Ergebnis ist aber nicht das, was ich will!


Xentar - Fr 12.06.09 09:50

Zeig uns doch mal den Code, wie du es bisher probierst. Vielleicht finden wir da den Fehler.


galagher - Fr 12.06.09 09:55

user profile iconXentar hat folgendes geschrieben Zum zitierten Posting springen:
Zeig uns doch mal den Code, wie du es bisher probierst. Vielleicht finden wir da den Fehler.

Naja, wenn ihr damit etwas anfangen könnt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
 {_@lower}
 if Pos('_@lower ', sParam) > 0 then
 begin
  if Pos(' not ', LowerCase(sParam)) > 0 then
   i := 3
  else
   i := 2;

  if (GetWord(LowerCase(sParam), i) = '_@lower'or
     (GetWord(LowerCase(sParam), i) = '''_@lower'then
  begin
   if Pos(LowerCase('_@upper '), sParam) > 0 then
    l := Pos(LowerCase('_@upper '), sParam)+8
   else
    l := Length(sParam);

   s := Copy(sParam, Pos(LowerCase('_@lower '), sParam), l);
   s1 := AnsiLowerCase(Copy(sParam, Pos(LowerCase('_@lower '), sParam)+8, l));
   sParam := StrReplace(sParam, s, s1, []);
  end;
 end;


 {_@upper}
 if Pos('_@upper ', sParam) > 0 then
 begin
  if Pos(' not ', LowerCase(sParam)) > 0 then
   i := 3
  else
   i := 2;

  if (GetWord(LowerCase(sParam), i) = '_@upper'or
     (GetWord(LowerCase(sParam), i) = '''_@upper'then
  begin
   if Pos(LowerCase('_@lower '), sParam) > 0 then
    l := Pos(LowerCase('_@lower '), sParam)+8
   else
    l := Length(sParam);

   s := Copy(sParam, Pos(LowerCase('_@upper '), sParam), l);
   s1 := AnsiUpperCase(Copy(sParam, Pos(LowerCase('_@upper '), sParam)+8, l));
   sParam := StrReplace(sParam, s, s1, []);
  end;
 end;


jfheins - Fr 12.06.09 10:14

Ich würds so in etwa machen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
function Convert(str: String): String;
var
i, j: Integer;
Flag: Integer;
const
  upperstart = '_@upper';
  lowerstart = '_@lower';
begin
setlength(Result, length(Str));
Flag := 0;
i := 0;
j := 0;
  while i < length(str) do
  begin
    inc(i);
    inc(j);

    if (copy(Str, i, length(upperstart)) = upperstart)
    begin
      i := i + length(upperstart);
      Flag := 1;
    end;

    if (copy(Str, i, length(lowerstart)) = lowerstart)
    begin
      i := i + length(lowerstart);
      Flag := -1;
    end;

    case Flag of
      1:
        Result[j] := AnsiUpperCase(Str[i]);
      -1:
        Result[j] := AnsiLowerCase(Str[i]);
      else
        Result[j] := Str[i];
  end;
end;
So in etwa - da sind bestimmt noch ein paar Fehler drin, aber das Vorgehen sollte sichtbar werden ;)


galagher - Fr 12.06.09 10:25

user profile iconjfheins hat folgendes geschrieben Zum zitierten Posting springen:
So in etwa - da sind bestimmt noch ein paar Fehler drin, aber das Vorgehen sollte sichtbar werden ;)

Ja, 2x then vergessen und Delphi meckert bei AnsiUpperCase(Str[i]) und AnsiLowerCase(Str[i]) - es muss (Str)[i] sein!

Ich wusste, dass es jemanden gibt, der weiss, wie's geht! :D

@user profile iconjfheins: Vielen Dank!


jaenicke - Fr 12.06.09 10:27

Und so wäre es allgemein für mehr Befehle: :mrgreen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
function ParseFormatString(const AText: String): String;
const
  Directives: array[0..1of string = ('_@upper ''_@lower ');
var
  CurrentText, EndPos: PChar;
  i, TempPos, CurrentDirType, NextDirPos: Integer;
begin
  Result := '';
  if AText = '' then
    Exit;
  CurrentText := PChar(AText);
  EndPos := CurrentText + Length(AText);
  CurrentDirType := -1;
  while CurrentText <= EndPos do
  begin
    NextDirPos := Length(AText) + 1;
    i := Low(Directives);
    while i <= High(Directives) do
    begin
      TempPos := Pos(Directives[i], CurrentText);
      if TempPos = 1 then
      begin
        CurrentDirType := i;
        i := Low(Directives);
        Inc(CurrentText, Length(Directives[i]));
        Continue;
      end
      else if (TempPos > 0and (TempPos <= NextDirPos) then
        NextDirPos := TempPos;
      Inc(i);
    end;
    case CurrentDirType of
      -1:
        Result := Result + Copy(CurrentText, 1, NextDirPos - 1);
      0:
        Result := Result + UpperCase(Copy(CurrentText, 1, NextDirPos - 1));
      1:
        Result := Result + LowerCase(Copy(CurrentText, 1, NextDirPos - 1));
    end;
    Inc(CurrentText, NextDirPos - 1);
  end;
end;


galagher - Fr 12.06.09 11:16

Danke euch! Habt mir sehr geholfen, vor allem auch, weil ich innerhalb ein und desselben Strings Gross- und Kleinschreibung beliebig oft wechseln kann!


Lannes - Fr 12.06.09 13:38

Hallo,

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Und so wäre es allgemein für mehr Befehle: :mrgreen:

gibt es noch MiddleCase ? :gruebel: :mrgreen:

hier mal meine Variante ohne Copy und Stringverkettungen, dürfte schneller sein:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
function ConvertUpLow(const s: String): String;
var x, i, ii, z, iStatus : Integer;
const U = '_@upper ';
      L = '_@lower ';
begin
  SetLength(Result,Length(s));
  i := 1;
  iStatus := -1;
  x := Length(s);
  z := 0;
  while i <= x do
    begin
    ii := 0;
    while (s[i+ii] = U[ii+1]) and (i+ii <= x) do
      inc(ii);
    if ii = Length(U) then
      begin
      iStatus := 0;
      inc(i,ii);
      end
      else
        begin
        ii := 0;
        while (s[i+ii] = L[ii+1]) and (i+ii <= x) do
          inc(ii);
        if ii = Length(L) then
          begin
          iStatus := 1;
          inc(i,ii);
          end;
        end;
    inc(z);
    case iStatus of
     -1 : Result[z] := s[i];
      0 : Result[z] := AnsiUpperCase(s[i])[1];
      1 : Result[z] := AnsiLowerCase(s[i])[1];
    end;
    inc(i);
    end;
  SetLength(Result,z);
end;


jaenicke - Fr 12.06.09 13:44

Naja, aber dafür greifst du die ganze Zeit auf die Buchstaben zu. Dabei wird jedesmal UniqueString intern aufgerufen. Das ist der Grund, dass ich in so einem Fall dann mit einem PChar direkt auf der Zeichenkette arbeite statt via Stringindex. ;-)