 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
JPT
Anmeldungsdatum: 27.02.2006 Beiträge: 35
|
Verfasst am: 01.03.2006, 17:33 Titel: Ich bin eingerostet... - Sub nimmt Deklarierte Variable nich |
|
|
So, neuer Thread, selbes Problem, alte Lösung, aber es geht nicht:
Ich lese in einem Programm mit line input einen Text in die auch schon deklarierte Variable cline$ ein.
Das Problem: Ich kann mein Programm nicht starten, da in der Sub die deklarierte Variable nicht akzeptiert wird
Code: |
DECLARE SUB check (cline$)
DIM SHARED cline AS STRING
'das öffnen und so lasse ich mal weg
LINE INPUT #1, cline$
Call check(cline$)
-----------------------------------------------
Sub check (cline$)
cline$ = UCASE$(cline$)
RETURN
END SUB
|
Was mache ich falsch ?
Die Variable cline$ soll mit ihrem Inhalt in der Sub weitergenutzt werden. _________________ MfG JPT |
|
Nach oben |
|
 |
otti

Anmeldungsdatum: 28.02.2005 Beiträge: 112 Wohnort: Wildberg
|
Verfasst am: 01.03.2006, 17:53 Titel: |
|
|
Wie wärs damit:
Code: |
DECLARE SUB check (subvariable$)
DIM SHARED cline AS STRING
...
LINE INPUT #1,cline$
check(cline$)
----
SUB CHECK (subvariable$)
subvariable$=UCASE$(subvariable$)
RETURN
END SUB
|
Achja:du weist schon das du mit deinem prog nur eine Zeile aus der Datei einliest?
So gings auch:
Code: |
DIM SHARED zeile(100) AS STRING
DECLARE SUB check(nr%) AS STRING
...
WHILE NOT EOF(1)
i=i+1
LINE INPUT #1,zeile(i)
Check(i)
WEND
SUB check(nr%)
zeile(nr%)=UCASE$(zeile(i))
RETURN
END SUB
|
(Code nicht getestet!)
grüße otti _________________ Gute Musik
 |
|
Nach oben |
|
 |
Tomtitom

Anmeldungsdatum: 20.09.2004 Beiträge: 308
|
Verfasst am: 01.03.2006, 17:57 Titel: |
|
|
also entweder du schreibst
Code: | DIM SHARED cline AS STRING |
und dann überall cline (ohne $)
oder du schreibst
und überall cline$ (mit $)
achso, und dann bräuchtest du eigentlich auch gar keinen Parameter bei check. Da es aber mit Parametern besser ist, lass einfach Code: | DIM SHARED cline AS STRING | weg.
Und was soll das RETURN eigentlich? |
|
Nach oben |
|
 |
JPT
Anmeldungsdatum: 27.02.2006 Beiträge: 35
|
Verfasst am: 01.03.2006, 18:19 Titel: |
|
|
Nur so, ich habe natürlich eine Schleife drin, soll ja ein Converter werden.
Das Problem war nur, das die Sub ihren Dienst verweigert hat.
Das Return benötige ich, um, nachdem die sub check die Zeile von unnützen Zeichen bereinigt hat, weiter im Prog zu machen. _________________ MfG JPT |
|
Nach oben |
|
 |
JPT
Anmeldungsdatum: 27.02.2006 Beiträge: 35
|
Verfasst am: 01.03.2006, 18:24 Titel: |
|
|
sry für dp, aber:
Irgendwie funktioniert trotzdem nichts, da die Sub ein und dieselbe Variable bearbeiten soll.
Ich muss noch einmal klarstellen, wofür ich das benötige, und wie ich es mir vorstelle:
Im Hauptprogramm wird innerhalb einer Schleife eine Zeile eingelesen. In eine Variable cline$. Dann wird eine Sub aufgerufen, die die Variable cline$ bearbeiten soll, und zurückgeben soll.
Frage: Wie realisiere ich diesen Ablauf ? _________________ MfG JPT |
|
Nach oben |
|
 |
MisterD

Anmeldungsdatum: 10.09.2004 Beiträge: 3071 Wohnort: bei Darmstadt
|
Verfasst am: 01.03.2006, 21:04 Titel: |
|
|
a) sub hat keine rückgabe und b) return hat in subs und functions unter qb glaub ich noch nix verloren
=>
Code: | declare function bla(blubb as string) as string
print blubb("hallo")
function bla(blubb as string) as string
bla=UCASE$(blubb)
end function |
_________________ "It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
Edsger W. Dijkstra |
|
Nach oben |
|
 |
jb

Anmeldungsdatum: 14.01.2005 Beiträge: 2010
|
Verfasst am: 01.03.2006, 22:06 Titel: |
|
|
Zum Thema SUBs und FUNCTIONs: Ein Link zur MonsterFAQ
jb |
|
Nach oben |
|
 |
Tomtitom

Anmeldungsdatum: 20.09.2004 Beiträge: 308
|
Verfasst am: 01.03.2006, 22:17 Titel: |
|
|
@ JPT: Ok, hab dich erst falsch verstanden, du willst einen Call by reference
Dazu musst du entweder Code: | Call check((cline$)) | oder schreiben, das DIM SHARED ... kannst du weglassen. Und Das RETURN ist auch sinnlos.
Oder du machst es so wie MD, pass bloß auf, dass du nicht wie er die blas und blubbs vertauschst
edit: bin irgendiwe immer etwas langsam  |
|
Nach oben |
|
 |
pinkpanther

Anmeldungsdatum: 28.05.2005 Beiträge: 79 Wohnort: Wien
|
Verfasst am: 02.03.2006, 00:32 Titel: |
|
|
@MisterD
Damit die Verwirrung hier nicht überhand nimmt, mach ich mal deinen Code lauffähig. Abgesehen von der bereits erwähnten bla/blubb-Vertauschung ist es auch nicht möglich, den Funktionstyp als AS-Klausel zu formulieren.
Code: | DECLARE FUNCTION bla$ (blubb AS STRING)
PRINT bla$("hallo")
FUNCTION bla$ (blubb AS STRING)
bla = UCASE$(blubb)
END FUNCTION |
@Tomtitom
Zitat: | @ JPT: Ok, hab dich erst falsch verstanden, du willst einen Call by reference. Dazu musst du entweder
Call check((cline$))
oder
check(cline$)
schreiben... |
Code: | Call check((cline$)) |
Das ist kein "Call By Reference", sondern ein "Call By Copy", bei dem eine Kopie des Parameters an die Prozedur übergeben wird. Änderungen, die innerhalb der Prozedur an dieser Kopie vorgenommen werden, wirken sich - im Gegensatz zum "Call By Reference" - nicht auf den Originalwert aus.
Das hingegen ist ein "Call By Reference", bei dem die Adresse des Parameters an die Prozedur übergeben wird. In diesem Fall kann das Original des übergebenen Wertes von der Prozedur verändert werden.
@JPT
Bei deinem Code fällt mir zunächst auf, dass du eine SUB mit RETURN statt mit EXIT SUB/END SUB verlassen willst. RETURN ist nur nach einem mit GOSUB eingeleiteten Sprung zulässig. Ansonsten müsste cline$ innerhalb der SUB jedenfalls als Parameter (nicht als Variable!) "akzeptiert" werden (funktioniert bei mir einwandfrei).
Zur Unterscheidung:
Parameter und lokale dynamische Variable werden anders als statische Variable verspeichert und sind auch nur innerhalb der Prozedur zugänglich, in der sie vorkommen (QB erspart dir allerdings diese Unterscheidung, sodass du auf Parameter und lokale Variable innerhalb der jeweiligen Prozedur wie auf statische Variable zugreifen kannst).
Prozeduren sollten idealerweise kleine abgeschlossene Einheiten darstellen, die - abgesehen von der Parameterübergabe - keine Berührungspunkte mit den übrigen Prozeduren eines Programms haben. Auf globale Variable sollte - wo sinnvoll möglich - verzichtet werden, da sie, wahllos eingesetzt, ein Programm fehlerhaft und schwer verständlich machen können. Parameter und Variable sollten jedenfalls schon der Klarheit halber niemals den gleichen Namen teilen!
Parameter kannst du dir als "Durchreiche", also als Schnittstelle zwischen aufrufender und aufgerufener Prozedur vorstellen. Ein Prozeduraufruf wird intern in Adressen (Call By Reference) bzw. Werte (Call By Value bzw. By Copy) aufgelöst, und diese Werte werden der aufgerufenen Prozedur vorübergehend als Information zur Verfügung gestellt. Die aufgerufene Prozedur kann - technisch gesehen - diese Werte nicht verändern! Auch im Fall der Übergabe eines Parameters "By Reference" mit anschließender Änderung innerhalb der aufgerufenen Prozedur wird ja nicht die übergebene Adresse selbst verändert, sondern jener Wert, der an dieser Adresse verspeichert ist.
Jedenfalls ergibt sich aus dem "Durchreiche"-Prinzip der Vorteil, dass die aufrufende Prozedur nicht die Namensgebung der einzelnen Parameter der aufgerufenen Prozedur berücksichtigen muss, sondern nur Aufrufreihenfolge und Typ (Integer, String...). Andernfalls wären ja auch Programmbibliotheken (LIBs, QLBs) ohne Kenntnis des Quellcodes unbenutzbar. _________________ lG
pinkpanther  |
|
Nach oben |
|
 |
Tomtitom

Anmeldungsdatum: 20.09.2004 Beiträge: 308
|
Verfasst am: 02.03.2006, 10:59 Titel: |
|
|
verdammt du hast recht, ich habs mal wieder voll verpeilt, meine Beispiele waren Call by Value, habs also genau vertauscht. Wenn man bei beiden Beispielen eine Klammer (rechts und links) wegnimmt, dann ist es Call by Reference.
Ich hoffe mal JPT blickt bei den ganzen Fehlern noch durch.
Aber dann verstehe ich auch nicht recht, warum das Programm von dir nicht klappen sollte, abgesehen von dem RETURN (und vielleicht noch das DIM zuviel) dürfte doch alles richtig sein. Vielleicht wäre es doch besser, wenn man mal das ganze Prog sieht. |
|
Nach oben |
|
 |
JPT
Anmeldungsdatum: 27.02.2006 Beiträge: 35
|
Verfasst am: 02.03.2006, 20:52 Titel: |
|
|
Ihr wollt also den ganzen Code:
(Trotz der vielen Anmerkungen funktioniert es nicht *?*)
Code: |
DECLARE SUB check (cline$)
DIM SHARED cline$
PRINT "This is the BZFlag World converter 1.0 -> 2.0"
PRINT
PRINT "Where is your world file located?"
INPUT "Please enter the complete path of the original file:", path$
INPUT "Please enter the path for the converted file:", path2$
CLOSE
OPEN path$ FOR INPUT AS #1
OPEN path2$ FOR OUTPUT AS #2
PRINT #2, "# This world has been converted with JPTs 1.0 -> 2.0 World Converter"
PRINT #2, "# Thanks for using this tool ! ;) "
PRINT #2, ""
DO UNTIL EOF(1)
LINE INPUT #1, cline$
CALL check(cline$)
IF LEFT$(cline$, 1) = "#" THEN
PRINT #2, cline$
END IF
IF LEFT$(cline$, 7) = "OPTIONS" THEN
DO UNTIL cline$ = "END" OR EOF(1)
PRINT #2, cline$
LINE INPUT #1, cline$
CALL check(cline$)
LOOP
PRINT #2, cline$
END IF
IF cline$ = "BOX" THEN
LINE INPUT #1, cline$
IF LEFT$(cline$, 4) = "name" THEN
PRINT #2, "#" + cline$
ELSE
IF LEFT$(cline$, 3) = "pos" THEN
'An dieser Stelle sollen aus einer Zeile 3 durch Leerzeichen getrennte Zahlen isoliert werden. Das kommt später.
END IF
END IF
END IF
LOOP
CLOSE
SUB check (cline$)
cline$ = UCASE$(cline$)
DO
IF cline$(chr) = "4" OR cline$(chr) = "9" OR cline$(chr) = "32" THEN
cline$ = RIGHT$(cline$, 2)
ELSE
EXIT DO
END IF
LOOP
END SUB
|
Wie gesagt, es soll eine Worldfile von einem Spiel eben convertieren.
Aber im Moment ist das Grundgerüst nicht lauffähig
Innerhalb der Sub stoppt QB und sagt mir:
"Datenfeld nicht definiert" _________________ MfG JPT |
|
Nach oben |
|
 |
Michael Frey

Anmeldungsdatum: 18.12.2004 Beiträge: 2577 Wohnort: Schweiz
|
Verfasst am: 02.03.2006, 21:04 Titel: |
|
|
Hier ist der Fehler:
Code: | IF cline$(chr) = "4" OR cline$(chr) = "9" OR cline$(chr) = "32" THEN |
und so sollte es gehen:
Code: | IF ASC(cline$) = 4 OR ASC(cline$) = 9 OR ASC(cline$) = 32 THEN |
_________________ http://de.wikibooks.org/wiki/FreeBasic Jede Hilfe für dieses Buch ist Willkommen!
http://de.wikibooks.org/wiki/FreeBasic:_FAQ FAQ zu Freebasic (im Aufbau, hilfe Willkommen)
Neu mit Syntax Highlight |
|
Nach oben |
|
 |
JPT
Anmeldungsdatum: 27.02.2006 Beiträge: 35
|
Verfasst am: 02.03.2006, 21:35 Titel: |
|
|
sry Michael, aber deine Version berücksichtigt nicht, das ASC nur ein Zeichen verarbeitet/en (kann)
Aber meine Version geht auch nicht: "Unzulässiger Funktionsaufruf"
Code: |
If ASC(MID$(cline$, 1, 1)) = 4 OR ASC(MID$(cline$, 1, 1)) = 9 OR ASC(MID$(cline$, 1, 1)) = 32 THEN
|
_________________ MfG JPT |
|
Nach oben |
|
 |
pinkpanther

Anmeldungsdatum: 28.05.2005 Beiträge: 79 Wohnort: Wien
|
Verfasst am: 02.03.2006, 23:32 Titel: |
|
|
Beschreib uns doch bitte mal mit ein paar einfachen Worten, was genau die SUB check bewirken soll! Andernfalls können wir dir beim Suchen logischer Fehler nur schwer helfen.
Aufgrund deiner bisherigen Äußerungen rate ich mal munter drauflos, dass du dir die SUB check folgendermaßen vorgestellt haben könntest:
Code: | SUB check (cline$)
cline$ = UCASE$(cline$)
FOR i% = 1 TO LEN(cline$)
SELECT CASE ASC(MID$(cline$, i%))
CASE 4, 9, 32
cline$ = RIGHT$(cline$, 2)
CASE ELSE
EXIT FOR
END SELECT
NEXT
END SUB |
Stimmt's?
Der "unzulässige Funktionsaufruf" sollte damit Vergangenheit sein. Ob die Lösung deinen Programmzweck erfüllt, weiß ich aber nicht. Wenn du weitere Hilfe brauchst, mach bitte nähere Angaben zur Problemstellung. _________________ lG
pinkpanther  |
|
Nach oben |
|
 |
JPT
Anmeldungsdatum: 27.02.2006 Beiträge: 35
|
Verfasst am: 03.03.2006, 09:01 Titel: |
|
|
Ja, das stimmt.
Die Sub soll im Falle, das das erste Zeichen einen der drei Werte hat, das erste zeichen "rausnehmen" _________________ MfG JPT |
|
Nach oben |
|
 |
Tomtitom

Anmeldungsdatum: 20.09.2004 Beiträge: 308
|
Verfasst am: 03.03.2006, 15:48 Titel: |
|
|
hm, bist du sicher, dass die Version von Michael nicht funktioniert?
Denn ASC nimmt auch bei einen String immer das erste Zeichen, darum müsste das eigentlich klappen.
Und das Code: | cline$ = RIGHT$(cline$, 2) | klappt auch nur, wenn cline$ genau 3 Zeichen lang ist. Besser wäre Code: | cline$ = RIGHT$(cline$, LEN(cline$)-1) | (kann ja sein, dass du mal die Länge ändern willst)
Falls auch auch öfters z.B. CHR$(9) auftritt, dürfte auch der Code von Pink Panther nix bringen, da sich in der FOR-Schleife cline$ ändert und somit bei 2 hintereinanderfolgenden "Sonderzeichen" das 2. nicht erkennen würde. |
|
Nach oben |
|
 |
pinkpanther

Anmeldungsdatum: 28.05.2005 Beiträge: 79 Wohnort: Wien
|
Verfasst am: 03.03.2006, 20:10 Titel: |
|
|
Wenn ich den Zweck der Prozedur richtig verstanden habe (siehe einleitenden Kommentar am Prozeduranfang), müsste die Lösung folgendermaßen aussehen:
Code: | SUB check (cLine$)
'Zweck der Prozedur:
'- wandelt die in der uebergebenen Zeichenfolge
' cLine$ enthaltenen Buchstaben in Grossbuchstaben um
'- entfernt bestimmte Zeichencodes vom Beginn der
' uebergebenen Zeichenfolge cLine$, konkret die
' ASCII-Codes 4, 9 und 32.
cLine$ = UCASE$(cLine$)
DO WHILE LEN(cLine$)
SELECT CASE ASC(cLine$)
CASE 4, 9, 32
cLine$ = MID$(cLine$, 2)
CASE ELSE
EXIT DO
END SELECT
LOOP
END SUB |
Es werden hier nur die Codes 4, 9 und 32 entfernt, die am Anfang einer Zeichenfolge stehen. Wenn die Codes ein paar gültige Zeichen später abermals vorkommen, werden diese Zeichen dann nicht mehr entfernt. Will man auch das erreichen, muss man folgende, weniger effiziente Variante einsetzen:
Code: | SUB check (cLine$)
'Zweck der Prozedur:
'- wandelt die in der uebergebenen Zeichenfolge
' cLine$ enthaltenen Buchstaben in Grossbuchstaben um
'- entfernt bestimmte Zeichencodes (konkret die ASCII-Codes
' 4, 9 und 32), die an beliebiger Position der uebergebenen
' Zeichenfolge cLine$ vorkommen koennen.
cLine$ = UCASE$(cLine$)
tErgebnis$ = SPACE$(LEN(cLine$))
FOR i% = 1 TO LEN(cLine$)
tChar$ = MID$(cLine$, i%, 1)
SELECT CASE ASC(tChar$)
CASE 4, 9, 32
CASE ELSE
iAusgPos% = iAusgPos% + 1
MID$(tErgebnis$, iAusgPos%) = tChar$
END SELECT
NEXT
cLine$ = LEFT$(tErgebnis$, iAusgPos%)
END SUB |
Beachte weiters:
UCASE$() ignoriert deutsche Sonderzeichen - UCASE$("ä") ergibt unverändert "ä"! Wenn deine Datei keine deutschen Sonderzeichen enthalten kann, kann dir dieses Verhalten natürlich egal sein.
Ich hoffe, dass dir damit geholfen ist! _________________ lG
pinkpanther  |
|
Nach oben |
|
 |
JPT
Anmeldungsdatum: 27.02.2006 Beiträge: 35
|
Verfasst am: 03.03.2006, 23:13 Titel: |
|
|
Es geht mir darum, nur die anfänglichen Tabs/Leerzeichen zu entfernen, um den Inhalt der Zeile gezielt zu Interpretieren.
Und die Select Case Variante funktioniert gut. _________________ MfG JPT |
|
Nach oben |
|
 |
MisterD

Anmeldungsdatum: 10.09.2004 Beiträge: 3071 Wohnort: bei Darmstadt
|
Verfasst am: 04.03.2006, 01:16 Titel: |
|
|
print ltrim$(" hallo")
... _________________ "It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
Edsger W. Dijkstra |
|
Nach oben |
|
 |
pinkpanther

Anmeldungsdatum: 28.05.2005 Beiträge: 79 Wohnort: Wien
|
Verfasst am: 04.03.2006, 10:08 Titel: |
|
|
@MisterD
LTRIM$() entfernt nur Leerzeichen, aber keine Tabstopps... _________________ lG
pinkpanther  |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|