# First ruby code, need hint on iterator

**URL:** <https://www.ruby-forum.com/t/first-ruby-code-need-hint-on-iterator/98684>\
**Category:** Ruby\
**Created:** [July 17, 2006, 2:46pm UTC](https://www.ruby-forum.com/t/first-ruby-code-need-hint-on-iterator/98684 "2006-07-17T14:46:39Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gerr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/9de053/32.png) [@Gerr](https://www.ruby-forum.com/u/Gerr)\
**Post date:** [July 17, 2006, 2:46pm UTC](https://www.ruby-forum.com/t/first-ruby-code-need-hint-on-iterator/98684/1 "2006-07-17T14:46:39Z")

</div>

Hello,

Consider the following code which generates a hexdump of a string:

* * *

#!/usr/bin/ruby

module Dump

```
    def hexdump

            x = 0
            offset = 0
            hex = ""
            str = ""
            out = ""

            each_byte { |c|

                    x = x + 1

                    hex << sprintf("%02x ", c)
                    hex << "- " if(x == 8)
                    str << ((c >= 32 && c<=127) ? c.to_i.chr : ".")

                    if(x == 16)
                            out << sprintf("%08x: %-50s %s\n", 

```

offset, hex, str)  
x = 0  
hex = “”  
str = “”  
offset = offset + 16  
end  
}

```
            out << "\n"

            return out
    end

```

end

l = $stdin.read(10000)  
l.extend Dump  
print l.hexdump

* * *

This program has a serious flaw: only if 16 bytes are collected from the  
input,  
a new line with hex codes is printed. If the input string has a length  
that is  
not a multiple of 16, the remaining bytes will not be handled.

A solution would be to duplicate the line

```
out << sprintf("%08x: %-50s %s\n", offset, hex, str)

```

somewhere at the end of the loop, so that any remaining buffers are  
printed.  
This forces me to duplicate code, though, which is not what I want.

The obvious solution for me would be to change the line

```
if(x == 16)

```

to something like

```
if((x == 16) || (c.is_the_last_element_from_the_set))

```

The problem is in the fictional thingy ‘is\_the\_last\_element\_from\_the  
set’,  
which I believe is not available.

What would be the idiomatic solution for this in Ruby ? Any other  
comments on  
the code are welcome as well, ofcourse

Thank you

---

<div class="post-metadata">

**Author:** ![Gerr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/9de053/32.png) [@Gerr](https://www.ruby-forum.com/u/Gerr)\
**Post date:** [July 17, 2006, 4:56pm UTC](https://www.ruby-forum.com/t/first-ruby-code-need-hint-on-iterator/98684/2 "2006-07-17T16:56:28Z")

</div>

> This program has a serious flaw: only if 16 bytes are collected from the input,  
> a new line with hex codes is printed. If the input string has a length that is  
> not a multiple of 16, the remaining bytes will not be handled.
> 
> A solution would be to duplicate the line
> 
> ```
> out << sprintf("%08x: %-50s %s\n", offset, hex, str)
> 
> ```

I think it’s ok to duplicate a single line. If you are worried about  
the two lines  
getting out of sync, put the line in a function:

def printHex(out, offset, hex, str)  
out \<\< sprintf("%08x: %-50s %s\n", offset, hex, str)  
end

---

<div class="post-metadata">

**Author:** ![Gerr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/9de053/32.png) [@Gerr](https://www.ruby-forum.com/u/Gerr)\
**Post date:** [July 17, 2006, 5:03pm UTC](https://www.ruby-forum.com/t/first-ruby-code-need-hint-on-iterator/98684/3 "2006-07-17T17:03:08Z")

</div>

Keep a count of total characters processed, and output if that is the  
same as the length of your string: (see my embedded changes)

Gerr wrote:

> ```
> def hexdump
> 
> x = 0
> 
> ```

```
               num_chars = 0

```

> ```
> offset = 0
> hex = ""
> str = ""
> out = ""
> 
> each_byte { |c|
> 
> x = x + 1
> 
> ```

```
                       num_chars += 1

```

> ```
> hex << sprintf("%02x ", c)
> hex << "- " if(x == 8)
> str << ((c >= 32 && c<=127) ? c.to_i.chr : ".")
> 
> ```

```
                     if(x == 16) || num_chars >= length
```

---

<div class="post-metadata">

**Author:** ![Gerr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/9de053/32.png) [@Gerr](https://www.ruby-forum.com/u/Gerr)\
**Post date:** [July 17, 2006, 8:04pm UTC](https://www.ruby-forum.com/t/first-ruby-code-need-hint-on-iterator/98684/4 "2006-07-17T20:04:57Z")

</div>

On 7/17/06, Gerr [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hello,
> 
> Consider the following code which generates a hexdump of a string:  
> …  
> What would be the idiomatic solution for this in Ruby ? Any other comments on  
> the code are welcome as well, ofcourse

If you want to do things with 16 bytes at a time, you might as well  
process them in groups of 16:

require ‘enumerator’  
module Dump  
def hexdump  
offset = 0  
out = ‘’  
split(‘’).each\_slice(16) {|chars|  
hc = chars.map{|c| “%02x " % c[0] }  
hex = hc[0…7] \<\< '- ’ \<\< hc[8…15]  
str = chars.map{|c| (c[0] \>= 32 && c[0] \<= 127) ? c : “.” }  
out \<\< sprintf(”%08x: %-50s %s\n", offset, hex, str)  
offset += 16  
}  
return out;  
end  
end

or even:

module Dump  
def hexdump  
offset = -16  
split(‘’).enum\_slice(16).map {|chars|  
hc = chars.map{|c| “%02x " % c[0] }  
hex = hc[0…7] \<\< '- ’ \<\< hc[8…15]  
str = chars.map{|c| (c[0] \>= 32 && c[0] \<= 127) ? c : “.” }  
sprintf(”%08x: %-50s %s\n", offset += 16, hex, str)  
}.join  
end  
end

---

<div class="post-metadata">

**Author:** ![Gerr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/9de053/32.png) [@Gerr](https://www.ruby-forum.com/u/Gerr)\
**Post date:** [July 17, 2006, 9:52pm UTC](https://www.ruby-forum.com/t/first-ruby-code-need-hint-on-iterator/98684/5 "2006-07-17T21:52:50Z")

</div>

Sander L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> offset += 16
> }
> return out;
> 
> ```
> 
> end  
> end

Delightful ! It’s hard to think outside the box if you mainly have been  
programming C for 20 years…

Thank you very much, I will learn a _lot_ from this newsgroup, I’m sure  
🙂
