Entwickler-Ecke

Sonstiges (Delphi) - Erstes Wort aus String


Mister Riös - Mi 20.01.10 21:33
Titel: Erstes Wort aus String
Hi,
ich habe eine Konsolenanwendung die nach Eingabe eines Satzes das erste Wort aus diesem Satz bestimmen soll. Ich hab zwar schon Lösungen mit Arrays gelesen, würde die aber gerne darauf verzichten, weil ich mit denen noch nie gearbeitet hab.

Also sieht mein Lösungsansatz so aus:
Der Algorithmus liest solange vom ersten Zeichen anfangend die Zeichen nacheinander auszulesen. Wenn ein Leerzeichen kommt bricht der Algorithmus ab, wenn ein Buchstabe kommt wird dieser an das ende eines anderen Strings angehangen. Danach wird dieser String ausgegeben.

Mein Code:

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:
program erstes_wort;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  wort, frage:string;
  i:integer;

begin
  readln(frage);

  i := 1;
  frage := '';
  while frage[i] <> ' ' do
  begin
    wort := wort + frage[i];
    i := i + 1;
  end;                                                                          
  writeln(wort);
 readln;
end.

I ist eine Zählvariable damit das Programm weiß bei welchem Buchstaben es grade ist.
Wort ist das erste Wort.
Frage ist der eingegebene Satz.

Das Problem:
Es gibt zwar keine Compilermeldungen, aber wenn ich im Programm den Satz eingegeben habe und Enter drücke, schließt sich das Programm nur. Hat jemand eine Ahnung was nicht stimmt?

Danke!


trm - Mi 20.01.10 21:37

Huhu :)

Warum setzt Du in Zeile 16 den abgefragten String auf eine Länge von 0 ?


Hidden - Mi 20.01.10 21:41

Hi :)

Du setzt Frage ja auch zurück auf '', nachdem du den wert eingelesen hast. Sagt da der Compiler ncihts zu? Etwas wie "Warning: Value assigned to Frage is never used."? Oder hast du Warnungen abgestellt, dass solltest du dann in den Compileroptionen umstellen.

Darüber hinaus solltest du eigentlich bei ''[1] <> ' '? eine Zugriffsverletzung bekommen. Aber das Programm sollte nicht beenden, am Ende steht ja noch ein ReadLn. Merkwürdig :gruebel:

mfG,


jaenicke - Mi 20.01.10 21:44

Zudem fehlt die Abbruchbedingung, wenn das Ende des Strings erreicht ist. (Was durch die Leerung des Strings hier ja wie schon gesagt wurde sofort der Fall wäre.)


Mister Riös - Mi 20.01.10 21:48

:D
Oh shit, da sollte eigentlich "wort" stehen! Peinlich :oops: Ich hab als ich zu schreiben angefangen hab ein bisschen rumgesaut, da muss mir das entgangen sein^^

Tjah, ähm, damit wäre das geklärt, das Programm läuft genau so wie es soll. Ich verstehe zwar nicht ganz warum das Programm sich einfach geschlossen hat aber jetzt klappt alles. Danke!

@Hidden & jaenicke:
Keine Ahnung was ihr meint was da falsch wäre, das Programm läuft jetzt indem ich einfach in Zeile 16 "frage" durch "wort" ausgetauscht habe.

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:
program erstes_wort;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  wort, frage:string;
  i:integer;

begin
  readln(frage);

  i := 1;
  wort := '';
  while frage[i] <> ' ' do
  begin
    wort := wort + frage[i];
    i := i + 1;
  end;
  writeln(wort);
 readln;
end.


jaenicke - Mi 20.01.10 21:50

Wenn frage aber leer ist, dann greifst du auf nicht existierenden Speicher zu. Denn schließlich ist der String leer und frage[i] = frage[1] existiert nicht...
Ungleich einem Leerzeichen ist es aber trotzdem, so dass die Schleife ggf. trotzdem weiterläuft (gilt auch wenn kein Leerzeichen vorkommt)...


Boldar - Mi 20.01.10 21:52

Wenn der String nun aber keine Leerzeichen enthält, knallt es.
Denn dann kommt deine Schleife nie zum Ende.
Deshalb solltest du die Bedingung noch modifizieren und zusätzlich die Länge des Strings prüfen.


Mister Riös - Mi 20.01.10 22:01

Hey, gute Ideen, das werde ich auf jeden Fall berücksichtigen, aber das sollte eigentlich ganz einfach sein mit einer Repeat unti-Schleife.


elundril - Mi 20.01.10 22:03

geht auch mit ein wenig umbauten mit dem vorhandenen konstrukt


Delphi-Quelltext
1:
2:
3:
4:
while i < length(frage) do begin
  if frage[i]' ' then
   {...}
end;


lg elundril


Mister Riös - Mi 20.01.10 22:11

user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
geht auch mit ein wenig umbauten mit dem vorhandenen konstrukt


Delphi-Quelltext
1:
2:
3:
4:
while i < length(frage) do begin
  if frage[i]' ' then
   {...}
end;


lg elundril


Hmm, aber dann würde der Algorithmus doch bis zum Ende des Satzes laufen und auch den ganzen Satz wieder wieder in "Wort" speichern. Oder meinst du, dass man dann im Else-Zweig der IF-Anweisung irgendwie aus der WHILE-Schleife rausgeht?


elundril - Mi 20.01.10 22:16

break ist das zauberwort das man dann verwenden kann. ;) so springt er dann aus einer schleife raus. eventuell gehts auch folgendes wenn man den compilerschalter aktiviert der regelt das bei der ersten bedingung abgebrochen wird:


Delphi-Quelltext
1:
2:
3:
4:
while (i < length(frage)) AND (frage[i] <> ' 'do begin
  wort := wort + frage[i];
  inc(i);
end;


lg elundril


Boldar - Mi 20.01.10 22:17

Übrigens, wenn du eine aktuelle Delphi-Version hast (Weiss leider nicht, ab welcher das geht), kannst du auch folgendes schreiben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var c: char;
...


for c in satz do
begin
  if word <> ' ' then
  wort := wort + c
  else
  break;
end;


jaenicke - Mi 20.01.10 22:21

Was spricht eigentlich dagegen einfach Pos zu benutzen um die Position des Leerzeichens herauszufinden? Dann kannst du dir die ganze Spielerei mit Schleifen sparen...

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  SpacePos: Integer;
begin
  SpacePos := Pos(' ', frage);
  if SpacePos > 0 then
    wort := Copy(frage, 1, Pred(SpacePos))
  else
    WriteLn('Kein Leerzeichen gefunden');
end;


user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
Übrigens, wenn du eine aktuelle Delphi-Version hast (Weiss leider nicht, ab welcher das geht)
Diese und andere Spracherweiterungen kamen mit Delphi 2006 dazu.


Mister Riös - Mi 20.01.10 22:24

@elundril: Danke, ich glaube so in der Art werde ich das mal versuchen.

@Boldar: Ich hab Delphi 7, also klappt das wahrscheinlich nicht (Es ist auch zu spät um es auszuprobieren);-)

@jeanicke: Keine Ahnung ob das klappen würde, aber mit den Schleifen geht's auch^^


R4Y - So 24.01.10 22:24

ich würde ja auch pos nehmen ^^


Delphi-Quelltext
1:
 wort:=leftstr(frage,pos(frage,' '));                    


hierbei ist zu beachten, dass man "strutils" in die uses-klausel aufnehmen muss!