01 Apr, 2009, Omega wrote in the 1st comment:
Votes: 0
This is part of my FileIO class in my new ruby mud.

I'm trying to figure out where I'm going wrong.

def read_word
temp = @file.getc
while temp =~ / / || temp =~ /\n/ do
temp = @file.getc
end
str = ""
@file.ungetc temp
while @file.eof? == false do
temp = @file.getc
break if temp =~ / /
break if temp =~ /\n/
str.concat(temp)
end

# return our string
return str
end


Goal, mimic fread_word if standard merc muds.

The problem: it doesn't stop at a space like it should, it reads the entire file onto the returned string.
I'm having a painstakingly hard time with this.

Breakdown of what it *SHOULD* do.
skip all spaces, and newlines, leading up to the first letter it finds, then it will read one letter at a time
until it hits a space or a newline, and return the string. Unfortunatly, its not working. So anyhelp would be greatly appreciated.

Note: I won't use YAML, so please don't even mention it.
01 Apr, 2009, Kayle wrote in the 2nd comment:
Votes: 0
Ruby, Lua, C++ How many muds are you building right now? lol
01 Apr, 2009, Omega wrote in the 3rd comment:
Votes: 0
C++ is my main mud, with a Lua mudprog system.

I'm writing a mud in Ruby now to help me learn ruby for work.

Anyways, all I need is alittle help with this, haven't been able to find the answer to my problem.

My google fu sucks!
01 Apr, 2009, Tyche wrote in the 4th comment:
Votes: 0
Like C, getc returns an integer in Ruby 1.8.x
01 Apr, 2009, Omega wrote in the 5th comment:
Votes: 0
Thats an interesting fact. Thanks Tyche!
01 Apr, 2009, Tyche wrote in the 6th comment:
Votes: 0
But I believe it returns a string in ruby 1.9.x.
I'm not altogether happy with that direction. :-(
01 Apr, 2009, Omega wrote in the 7th comment:
Votes: 0
I believe I'm using 1.9.1.

I just .chr'd the temp's and it fixed it. That tid-bit about it being a integer was a great help, and is mucho appreciated!
01 Apr, 2009, Tyche wrote in the 8th comment:
Votes: 0
There's a nice Ruby standard library class called StringScanner based on the C strscan utility. Both because of its features and performance.

In any case, I sub-classed it so I could parse TinyMud, TinyMush, MOO and Diku-derived databases.

Some of this might be useful to you…
class Scanner < StringScanner
attr_accessor :line
attr_accessor :fname

def filetostr(nm)
str = nil
File.open(nm) do |f|
str = f.read
# remove the stench of Windows, Mac, and wierd editors
str.gsub!(/\r\n|\n\r|\r/,"\n") # Windows
end
return str
end

def initialize(file, opts)
@line = 1
@file = File.expand_path(file)
@fname = File.basename(@file)
@opts = opts
super(filetostr(@file))
end

def eatnl
@line += 1 if scan_until(/\n/)
end

def getstr
t = scan_until(/~/).chop!
@line += t.count("\n") if t
eatws
t
end

def eatws
t = scan(/\s+/)
@line += t.count("\n") if t
t
end

def getword
t = scan(/'.*?'|[^~ \n\t\r\f]+/).to_s
eatws
t
end

def getnum
t = scan(/[-+]?\d+/).to_i
eatws
t
end

def getdec
t = scan(/[-+]?\d+\.\d+/).to_f
eatws
t
end

def getdice
d = Dice.new
if !scan(/(\d+)[d|D](\d+)([-+]\d+)/)
printf("Dice Error: file->%s line->%s\n",@fname,@line.to_s)
raise "Dice Error"
end
d.number = self[1].to_i
d.dietype = self[2].to_i
d.modifier = self[3].to_i
eatws
return d
end

def getflag
# check if number
wrd = scan(/[-+]?\d+/)
if wrd
flg = wrd.to_i
while scan(/\|/)
flg |= scan(/\d+/).to_i
end
eatws
return flg
end
# assume character
wrd = scan(/\w+/)
if wrd
if @opts.server == :rom #
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
else
alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
end
flg = 0
wrd.each_byte do |b|
flg |= 1 << alpha.index(b)
end
eatws
return flg
end
raise "Flag Error"
end

def getnumnl
num = gettonl
num.to_i
end

def gettonl
@line += 1
scan_until(/\n/).chop!
end

def gettopound
t = scan_until(/^\#/).chop!
@line += t.count("\n") if t
eatws
t
end
end
01 Apr, 2009, Omega wrote in the 9th comment:
Votes: 0
Nice!

I've been writing up all my own features, they are nowhere near as small as yours though.

Then again, I'm just discovering ruby now. I think I'm in love with it.

My module so-far is this….

#fileio!

# CRAZY LIKE PINEAPPLE!
class FileIo
# initialize our FileIO
def initialize(filename, mode)
@file = File.open(filename, mode)
end

def eof
return @file.eof
end

def read_letter
temp = @file.getc
while temp.chr == / / || temp.chr == /\n/ do
temp = @file.getc
end

# return our found character! YAY US!
return temp
end

# read a word from file!
def read_word
temp = @file.getc
while temp.chr =~ / / || temp =~ /\n/ do
temp = @file.getc
end
str = ""
@file.ungetc temp
while @file.eof? == false do
temp = @file.getc
break if temp.chr =~ / /
break if temp.chr =~ /\n/
str.concat(temp.chr)
end

# return our string
return str
end

#read a string!
def read_string
temp = @file.getc
str = ""
while temp.chr == / / || temp.chr == /\n/ do
temp = @file.getc
end

# go back one!
@file.ungetc temp
while @file.eof? == false
temp = @file.getc
# end of line!
if temp.chr =~ /¥/
return str
else
str.concat(temp.chr)
end
end
return str
end

# read numbers!
def read_number
number = 0
temp = @file.getc

# get rid of our spaces and newline crap!
while temp.chr == / / || temp.chr == /\n/ do
temp = @file.getc
end
str = ""

@file.ungetc temp
while @file.eof? == false
temp = @file.getc
break if temp.chr =~ / /
break if temp.chr =~ /\n/
str << temp.chr
end

return str.to_i
end

# write to the file
def write_string(*args)
@file.write sprintf(*args)
@file.write "¥\n"
end

def write(*args)
@file.write sprintf(*args)
end

#close the file!
def close
@file.close
end
end


As you can tell, I have a history of diku-derived string handling :P

All the features work now, although I need more testing with them to ensure that they aren't
going to explode on me. But so-far so good.

I'm going to start adding new debugging features. But those will happen in due-time.

sample-usage:
f = FileIo.new(whatever.txt, "w")
f.write_string("Blah %s", "some long string variable")
f.write("END\n")
f.close

f = FileIo.new(whatever.txt, "r")
while f.eof == false do
word = f.read_word
case word
when "Blah"
blah = f.read_string
when "END"
break
else
mud_log(LOG_BUG, "Unknown word: %s", word)
end
end
f.close


It works quite well, atleast as I said, so-far. I'm happy with it, though fine-tuning will come as I identify issue's with it.
0.0/9