[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Logical Operations on Strings

Michael W. Ryder

1/28/2008 8:16:00 AM

Is there a bitwise and for strings that I am missing? I tried the
documentation and Google with no luck. I coded a simple method to
handle this, it obviously needs more error checking, but don't want to
reinvent the wheel if not necessary.

def AND(s, m)
t = s.dup
for i in 0...(s.size <= m.size ? s.size : m.size)
t[i] = (s[i] & m[i]).chr
end
return t
end

On a related note, is there any way to create a string from a hex number
other than separating each two digits and using .chr to convert them to
a number and adding them to the string? If I have a string such as
0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by
5 str1 << 0xFF.chr which seems to be unnecessarily clumsy.
5 Answers

Robert Klemme

1/28/2008 10:09:00 AM

0

2008/1/28, Michael W. Ryder <_mwryder@worldnet.att.net>:
> Is there a bitwise and for strings that I am missing? I tried the
> documentation and Google with no luck. I coded a simple method to
> handle this, it obviously needs more error checking, but don't want to
> reinvent the wheel if not necessary.
>
> def AND(s, m)
> t = s.dup
> for i in 0...(s.size <= m.size ? s.size : m.size)
> t[i] = (s[i] & m[i]).chr
> end
> return t
> end

I believe this implementation is flawed because it returns a string
that is too long if self.size > m.size.

This is what I'd probably do

class String
def &(s)
t = ""
[size, s.size].min.times do |i|
t << (self[i] & s[i])
end
t
end

def |(s)
t = ""
[size, s.size].max.times do |i|
t << ((self[i] || 0) | (s[i] || 0))
end
t
end
end

Now you can do

irb(main):020:0> 0.chr | "a"
=> "a"
irb(main):021:0> 0.chr | "abc"
=> "abc"
irb(main):022:0> 0.chr & "abc"
=> "\000"
irb(main):023:0> a="s"
=> "s"
irb(main):024:0> a|="123"
=> "s23"
irb(main):025:0> a&="\012"
=> "\002"

> On a related note, is there any way to create a string from a hex number
> other than separating each two digits and using .chr to convert them to
> a number and adding them to the string? If I have a string such as
> 0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by
> 5 str1 << 0xFF.chr which seems to be unnecessarily clumsy.

I am not sure which direction you mean (there is no such thing as a
"hex number" in Ruby, a number is a number, hex is just one
representation - internally they are most likely stored binary). Does
this help?

irb(main):001:0> 123.to_s 16
=> "7b"
irb(main):002:0> "%04x" % 123
=> "007b"
irb(main):003:0> "7b".to_i 16
=> 123

Kind regards

robert

--
use.inject do |as, often| as.you_can - without end

Michael W. Ryder

1/28/2008 8:05:00 PM

0

Robert Klemme wrote:
> 2008/1/28, Michael W. Ryder <_mwryder@worldnet.att.net>:
>> Is there a bitwise and for strings that I am missing? I tried the
>> documentation and Google with no luck. I coded a simple method to
>> handle this, it obviously needs more error checking, but don't want to
>> reinvent the wheel if not necessary.
>>
>> def AND(s, m)
>> t = s.dup
>> for i in 0...(s.size <= m.size ? s.size : m.size)
>> t[i] = (s[i] & m[i]).chr
>> end
>> return t
>> end
>
> I believe this implementation is flawed because it returns a string
> that is too long if self.size > m.size.
>

Actually I designed it that way so that I could change only part of the
original string without having to create a mask of 0xFF for the
remaining characters. Your implementations look a little cleaner than
my first try and I will probably use them in the finished version. I
still wonder why these weren't implemented in Ruby as I have been using
them for over 25 years in other languages.


> This is what I'd probably do
>
> class String
> def &(s)
> t = ""
> [size, s.size].min.times do |i|
> t << (self[i] & s[i])
> end
> t
> end
>
> def |(s)
> t = ""
> [size, s.size].max.times do |i|
> t << ((self[i] || 0) | (s[i] || 0))
> end
> t
> end
> end
>
> Now you can do
>
> irb(main):020:0> 0.chr | "a"
> => "a"
> irb(main):021:0> 0.chr | "abc"
> => "abc"
> irb(main):022:0> 0.chr & "abc"
> => "\000"
> irb(main):023:0> a="s"
> => "s"
> irb(main):024:0> a|="123"
> => "s23"
> irb(main):025:0> a&="\012"
> => "\002"
>
>> On a related note, is there any way to create a string from a hex number
>> other than separating each two digits and using .chr to convert them to
>> a number and adding them to the string? If I have a string such as
>> 0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by
>> 5 str1 << 0xFF.chr which seems to be unnecessarily clumsy.
>
> I am not sure which direction you mean (there is no such thing as a
> "hex number" in Ruby, a number is a number, hex is just one
> representation - internally they are most likely stored binary). Does
> this help?
>

The reason I asked is that sometimes it is easier for me to think in hex
when creating masks for logical operations. Plus, I learned the PCL
codes for printing using hex and it is easier for me to use them that
way. In Business Basic to enter a group of hex characters into a string
I just use A$=$1B2C062C$ to create a 4 character string. No need to
enter each character individually.


> irb(main):001:0> 123.to_s 16
> => "7b"
> irb(main):002:0> "%04x" % 123
> => "007b"
> irb(main):003:0> "7b".to_i 16
> => 123
>
> Kind regards
>
> robert
>

Adam Shelly

1/28/2008 8:38:00 PM

0

On 1/28/08, Michael W. Ryder <_mwryder@worldnet.att.net> wrote:
> Robert Klemme wrote:
> > 2008/1/28, Michael W. Ryder <_mwryder@worldnet.att.net>:
> >> On a related note, is there any way to create a string from a hex number
> >> other than separating each two digits and using .chr to convert them to
> >> a number and adding them to the string? If I have a string such as
> >> 0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by
> >> 5 str1 << 0xFF.chr which seems to be unnecessarily clumsy.
> >
> The reason I asked is that sometimes it is easier for me to think in hex
> when creating masks for logical operations. Plus, I learned the PCL
> codes for printing using hex and it is easier for me to use them that
> way. In Business Basic to enter a group of hex characters into a string
> I just use A$=$1B2C062C$ to create a 4 character string. No need to
> enter each character individually.

Are you looking for something like this?

irb(main):010:0> ["414243"].pack('H*')
=> "ABC"
irb(main):011:0> ["7FFFFFFFFFFF"].pack('H*')
=> "\177\377\377\377\377\377"
irb(main):012:0> A=['1B2C062C'].pack('H*')
=> "\e,\006,"

-Adam

Michael W. Ryder

1/28/2008 11:01:00 PM

0

Adam Shelly wrote:
> On 1/28/08, Michael W. Ryder <_mwryder@worldnet.att.net> wrote:
>> Robert Klemme wrote:
>>> 2008/1/28, Michael W. Ryder <_mwryder@worldnet.att.net>:
>>>> On a related note, is there any way to create a string from a hex number
>>>> other than separating each two digits and using .chr to convert them to
>>>> a number and adding them to the string? If I have a string such as
>>>> 0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by
>>>> 5 str1 << 0xFF.chr which seems to be unnecessarily clumsy.
>> The reason I asked is that sometimes it is easier for me to think in hex
>> when creating masks for logical operations. Plus, I learned the PCL
>> codes for printing using hex and it is easier for me to use them that
>> way. In Business Basic to enter a group of hex characters into a string
>> I just use A$=$1B2C062C$ to create a 4 character string. No need to
>> enter each character individually.
>
> Are you looking for something like this?
>
> irb(main):010:0> ["414243"].pack('H*')
> => "ABC"
> irb(main):011:0> ["7FFFFFFFFFFF"].pack('H*')
> => "\177\377\377\377\377\377"
> irb(main):012:0> A=['1B2C062C'].pack('H*')
> => "\e,\006,"
>
> -Adam
>

That is much better, I will have to read up on pack and template strings
now but at least I have a starting point. It's not as concise as what I
am used to but it is usable. Thank you for pointing this out.

Robert Klemme

1/29/2008 8:37:00 AM

0

2008/1/28, Michael W. Ryder <_mwryder@worldnet.att.net>:
> Robert Klemme wrote:
> > I believe this implementation is flawed because it returns a string
> > that is too long if self.size > m.size.
>
> Actually I designed it that way so that I could change only part of the
> original string without having to create a mask of 0xFF for the
> remaining characters.

Ah, ok, then this was on purpose. Personally I'd consider an element
that is not there as 0x00 for OR and AND - that's why I did it this
way.

> Your implementations look a little cleaner than
> my first try and I will probably use them in the finished version. I
> still wonder why these weren't implemented in Ruby as I have been using
> them for over 25 years in other languages.

Since Ruby is so flexible chances are that you will find an equally
easy (or easier) way. :-)

> The reason I asked is that sometimes it is easier for me to think in hex
> when creating masks for logical operations. Plus, I learned the PCL
> codes for printing using hex and it is easier for me to use them that
> way. In Business Basic to enter a group of hex characters into a string
> I just use A$=$1B2C062C$ to create a 4 character string. No need to
> enter each character individually.

Then #pack and #unpack are your friends (see Adam's reply). You could
easily put that in a method if you want a more concise representation,
e.g.

def h(s)
[s.to_str].pack 'H*'
end

irb(main):005:0> h '212223'
=> "!\"#"
irb(main):006:0> h '414243'
=> "ABC"
irb(main):010:0> h %Q{414243}
=> "ABC"
irb(main):011:0> h %q{414243}
=> "ABC"

Note also, that you can use hex constants in Ruby:

irb(main):001:0> 0x7b
=> 123

but it seems you are more after construction of strings.

Kind regards

robert


--
use.inject do |as, often| as.you_can - without end