Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Here's another....file I/O difficulties.
#21
Quote:Sometimes you have really long functions (even longer if you do profusely comment!), and you can't split them. Take for example a fast syntactic analyzer. The fastest way to create it is with a SELECT CASE structure and a different entry for each keyword.
Yes, design should adapt the needs at hand, obviously. I'm not suggesting a blanket coding style, however in my experience, the companies I've worked for have required similar styles - in C++, variable initialization is a given. Granted, you have some leeway with function length since the IDE you're using can help you out (outlining/folding, function selection, statement completion, declaration/definition locating, etc.) FreeBASIC does not currently have such an exclusive IDE, but I'm of the mind that an IDE shouldn't be the main factor in how you implement code, either.

Quote:Note that I am an optimization and speed freak. Sometimes the "best looking algorithm" and the "best split function" are also way slower than uglier counterparts. When I coded my last finished QB game (i.e. Jill) the movement subroutine took up to 400 lines or so. I could've split it in subroutines, but the amount of data needed to be passed back and forth would have turned the process into a snail walking over sand :lol: That's why my code style is not always very ... rational.
Again, it depends on who's reading your code. For hobby work, either individually or with a small team, then feel free to code however it takes to be better productive, of course. For employers, software teams mandate a certain style, regardless of your personal preference. I realize that FreeBASIC, C, C++, Java, etc. are different languages. However, I strongly feel that beginning programmers should learn habits similar to that of those languages, since 1) it will only help them in transitioning over, and 2) languages like FreeBASIC are designed to give you the freedom to be able to do that (make the transition from FB to, for example C++, very easy by following similar programming paradigms).

Quote:Besides, I'm working now doing lots of web-coding mostly in Java, JSP and PHP, and I can assure you that you will find 1,000 lines functions quite easily :lol: specially when you have html rendering plus database handling plus open directory reading plus connection to a mail server plus call to a PDF generating library all in place (I mean, just the calls to all those subsystems take lots of lines - I just wrote a SQL query that took 15 lines five minutes ago Big Grin).
I'm not very familiar with web-programming, but no Java function I've ever been assigned to has been 1000 lines long ... I'd probably shoot myself.

Quote:I think I'm missing something. What I claim is for declaration on top of your function/sub or main section. I am not encouraging module globals.
I know you're not. We're on the same page.

Quote:In C++ or Java ... code snipped ... But in BASIC this is not possible (again, AFAIK Wink). Until it is, I'll keep declaring my stuff on top of each SUB/FUNCTION.
Wink prepare to change, my friend:
Code:
'' note: op_new_???(...) and op_delete(...) are functions from my MACRO library ...

if not( iConnectorStream = null ) then
scope
    dim as StatementGenerator ptr myGenerator = op_new_StatementGenerator( blah, 1 )
    ...
    '' Here you can use myGenerator
    ...
    op_delete( myGenerator )
end scope
end if

'' Here myGenerator is not declared

http://www.freebasic.net/wiki/wikka.php?...KeyPgScope
stylin:
Reply
#22
Nice to know new stuff :lol:

In that scenario, I concur and agree with you.

Anyway, for every variable which won't be used within a scope, I'd declare it on top rather than doing it just before it's used. Call it "cosmetic". I just find it more handy, and useful. 'Cause there's an advantage on declaring stuff when it's used if you are inside a delimited chunk of code (that scope thing), but there isn't if you are not.

Btw, when giving hints to code in BASIC, I always encourage coding in the right way, and the right way (for me) is the "pseudo OO" way, I mean, trying to use (or at least emulating) encapsulation as much as possible.

And, trust me, I'm usually working adapting already coded software to fit our needs at work. That means that I've played around with the guts of postnuke, squirrelmail, docmanager and other systems. And I can assure you that 1,000 lines functions are quite common :lol: (and a nightmare). And in Java it's even worse. Sometimes splitting your methods so much is a bad move, mainly 'cause of massive exception handling. Of course you have to break your code in as many functional parts as possible, that's the key to structured programming, but I just want to tell you that "Good functions are no more than 15-25 lines" is not always appliable.
SCUMM (the band) on Myspace!
ComputerEmuzone Games Studio
underBASIC, homegrown musicians
[img]http://www.ojodepez-fanzine.net/almacen/yoghourtslover.png[/i
Reply
#23
Back on the subject of Ethan Winer's clever little encryption there...
Well here it is in my expanded form. Shown is code for both ciphering and deciphering. It's a few lines longer, but a heckuva lot clearer.
Code:
OPTION EXPLICIT
CONST Text="Move 32nd platoon SSW 10 miles"
CONST Password="armypassword"

DIM AS STRING DecipheredText,CipheredText
DIM TempChar AS BYTE,PswdPos AS INTEGER,I AS INTEGER

PswdPos=1
FOR I=1 TO LEN(Text)
    IF PswdPos > LEN(Password) THEN PswdPos=1
    TempChar=ASC(MID$(Text,I,1)) XOR ASC(MID$(Password,PswdPos,1))
    CipheredText=CipheredText + CHR$(TempChar)
    PswdPos=PswdPos + 1
NEXT

PRINT "Text: ";Text
PRINT "Password: ";Password
PRINT "Ciphered text: ";CipheredText

PswdPos=1
FOR I=1 TO LEN(CipheredText)
    IF PswdPos > LEN(Password) THEN PswdPos=1
    TempChar=ASC(MID$(CipheredText,I,1)) XOR ASC(MID$(Password,PswdPos,1))
    DecipheredText=DecipheredText + CHR$(TempChar)
    PswdPos=PswdPos + 1
NEXT

PRINT "Deciphered text: ";DecipheredText
SLEEP
PswdPos indicates which character in the password string is to be used for each iteration. It's incremented each time, and reset once it exceeds the length of the password.
f only life let you press CTRL-Z.
--------------------------------------
Freebasic is like QB, except it doesn't suck.
Reply
#24
Nice work! That looks alot better. While we're on the subject of functions, though, this may be a good time to show their usefulness. Additionally, you can use the string-indexing operator ( [] ) to crisp up that code even more:
Code:
option explicit
option byval

function CipherText( text as string, key as string ) as string
    dim as integer textIndex = 0, keyIndex = 0
    dim as string result = string( len( text ), 0 )

    while( textIndex < len(text) )
        if( keyIndex > len(key) ) then keyIndex = 0
        result[textIndex] = text[textIndex] xor key[keyIndex]
        textIndex += 1 : keyIndex += 1
    wend
    return result
end function

const originalText as string = "Move 32nd platoon SSW 10 miles"
const password as string = "armypassword"

dim as string cipheredText : cipheredText = CipherText( originalText,password )
print "  original Text: " ; originalText
print "       Password: " ; Password
print "  Ciphered text: " ; cipheredText

dim as string decipheredText : decipheredText = CipherText( cipheredText,password )
print "Deciphered text: " ; decipheredText

sleep : end 0
Here, we solely work with the byte values of the strings, which is what operator[] gives us. As you may be able to guess, this is much more efficient than converting back and forth from strings to integers again and again.
stylin:
Reply
#25
I didn't know about that! Kinda renders MID$ less useful than it was in QB.
Now I'm working on another encryption method. I may post it, but I might offer it up to be cracked first as a challenge.
f only life let you press CTRL-Z.
--------------------------------------
Freebasic is like QB, except it doesn't suck.
Reply
#26
Quote:I didn't know about [the string indexing operator]! Kinda renders MID$ less useful than it was in QB.
Just a little. It would still be very inefficient to try and return large substrings using [] alone.

Quote:Now I'm working on another encryption method. I may post it, but I might offer it up to be cracked first as a challenge.
You're just an encrypting fool, aren't ya? Wink
stylin:
Reply
#27
Zack and Stylin,

The new encryption logic that you guys derived from Winer's algorithm is "crisper" and prettier, but, it doesn't work the same. I ran your new code against Winer's code in the same program. For the same original text and password, the ciphered text is the same for the first 11 characters, and then is different.

If the new version does not yield the same results, then it cannot qualify as being the same algorithm.

Run a test yourselves.
*****
Reply
#28
The problem was due to string copying; the string was getting truncated at the null character when it was being passed in. The original code you posted earlier used the same string. Passing by reference and explicitly copying solves the problem. Here is the updated code:
Code:
option explicit
option byval

function ZackText( byref text as string, key as string ) as string
    dim as string result => text
    dim as integer textIndex = 0, keyIndex = 0

    while( textIndex < len(text) )
        if( keyIndex = len(key) ) then keyIndex = 0
        result[textIndex] xor= key[keyIndex]
        textIndex += 1 : keyIndex += 1
    wend
    return result
end function

function WinerText( byref text as string, key as string ) as string
    dim as string result => text
    dim as integer L = len(key)
    dim as integer i, Pass

    for i = 1 to len(text)
         Pass = asc(mid$(key, (i mod L) - L  * ((i mod L) = 0), 1))
         mid$(result,i,1) = chr$(asc(mid$(text,i,1)) xor Pass)
    next
    return result
end function

const originalText as string = "Move 32nd platoon SSW 10 miles"
const key as string = "armypassword"

dim as string zackedText : zackedText = ZackText( originalText, key )
dim as string wineredText : wineredText = WinerText( originalText, key )
dim as string deZackedText : deZackedText = ZackText( zackedText, key )
dim as string deWineredText : deWineredText = WinerText( wineredText, key )

print "  original Text: " ; originalText
print "       Password: " ; key
print
print "    Zacked text: " ; zackedText
print "   Winered text: " ; wineredText
print
print "  DeZacked text: " ; deZackedText
print " DeWinered text: " ; deWineredText

sleep : end 0
stylin:
Reply
#29
Well I haven't learned references, pointers, etc. yet. I'll examine that code and see what it means.
Thanks for pointing that out, Moneo - usually when I test encryption stuff I test to see if it deciphers correctly - and not to see whether it comes out the same as another method of ciphering.
f only life let you press CTRL-Z.
--------------------------------------
Freebasic is like QB, except it doesn't suck.
Reply
#30
Quote:Well I haven't learned references, pointers, etc. yet. I'll examine that code and see what it means.
Passing a variable by value to a function means that a copy of the variable is made, and that copy is what the function refers to.

Passing a variable by reference means that the object a function recieves is a reference to the original variable. Many compilers implement references as pointers internally, but that should not be relied upon. A reference should be considered as the original variable. Any changes made to a reference affect the original variable. Passing by reference is the default behavior in both QB and FB.

Now, since many compilers implement references as pointers, passing a variable by reference often leads to faster code when passing UDTs and strings because - on my system - a pointer is 4 bytes. UDTs and strings can be potentially quite large and expensive objects to copy. Passing them by reference ensures that these copies are not made, and only a 4-byte pointer is passed instead. You need to be careful when passing by reference - especially since FB doesn't have true constant variables - because again, any changes you make to the reference are made to original variable as well. So, when passing variables that you don't want to be changed (accidentally or otherwise) pass by value, unless the object is a large UDT or string.

In the above code, "option byval" sets the default passing convention to by value. In both functions, "key" is being passed by value, since I don't want to accidentally change it. "text" is being passed by reference because for some reason FB truncates a string being passed to a function if it contains a null (chr$(0)) character but, curiously, this truncation does not happen if the string is copied in code. So, "text" is passed by reference to in order to avoid it being copied internally.
stylin:
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)