Genie howto repeats string N times as string array

I am writing this code, repeatc to iterate a char array to char. it works.

repeats to repeat string N times in an array of strings. but repeat the string in the core of the string array.

A, A, A, 
AB, AB, AB, 
*** Error in `./untitled': free(): invalid pointer: 0x0000000000400f3d ***
....
....
Aborted (core dumped)

      

why? my code:

// - cc = 'gcc'

[indent=4]

init
    var carray = repeatc ('A', 3)
    for i in carray do stdout.printf ("%c, ", i)
    // A, A, A

    stdout.putc ('\n')
    var sarray = repeats ("AB", 3)
    for i in sarray do stdout.printf ("%s, ", i)
    stdout.putc ('\n')



def repeatc (e: char, n: int): array of char
    var a = new array of char[n]
    Memory.copy (a, &e, sizeof (char))
    Memory.copy (&a[1], a, sizeof (char) * (n - 1)) // gcc
    return a

def repeats (e: string, n: int): array of string
    var a = new array of string[n]
    // WORKS: for var i = 0 to (n - 1) do a[i] = e
    // Memory.copy HOW TO?

    // (CORE DUMPED)
    Memory.copy (a, &e, sizeof (uint8*))
    Memory.copy (&a[1], a, sizeof (uint8*) * (n - 1))
    return a

      

Why is this code being flushed by the kernel ? and how to fix it?

0


source to share


1 answer


There are several things in this code.

[indent=4]

init
    var carray = repeatc ('A', 3)
    for i in carray do stdout.printf ("%c, ", i)
    // A, A, A

      

Actually, it prints "A, A, A" (note the trailing comma and space). There are many ways to fix this, the easiest would be to do something like stdout.puts (string.joinv (", ", sarray))

.

def repeatc (e: char, n: int): array of char
    var a = new array of char[n]
    Memory.copy (a, &e, sizeof (char))

      

Using Memory.copy (aka memcpy in C) to copy a single byte is more than silly. There is absolutely no reason not to just do it a[0] = e

here. It's easier and will work better.

    Memory.copy (&a[1], a, sizeof (char) * (n - 1)) // gcc

      

This is very wrong. You are telling it to copy the sizeof (char) * (n - 1)

bytes from the location a

1 byte after a

. This is very different from what you intend to intend to fill the rest of a with with the value of the first byte in the array. In fact, you shouldn't use Memory.copy

, you should use Memory.set

: Memory.set (a, e, n)

can replace both strings Memory.copy

.



That said, it's likely what you really want is a string, not an array of characters. In this case, you can replace that whole function and just call string.nfill (3, 'A')

.

def repeats (e: string, n: int): array of string
    var a = new array of string[n]
    // WORKS: for var i = 0 to (n - 1) do a[i] = e
    // Memory.copy HOW TO?

      

You still need a loop. When you start trying to use the functions Memory.*

that you work with pointers, you need to understand how memory is laid out. Strings are really arrays of characters, and arrays are just pointers to the first element of the array. When you create an array of strings, what you have is a pointer to a pointer (in C, gchar**

), not a pointer to a large contiguous block, you can start copying your character data.

I think you are trying to use Memory.copy

instead of for loop and simple assignment for better performance; the only thing really bad for performance here is that a simple assignment will call g_strdup

that will call strlen

, so you end up scanning your input string N times to compute the length, not once. The best you are going to get is perhaps something like:

var elen = e.length
for var i = 0 to (n - 1)
    a[i] = (string) Memory.dup (e, (uint) elen);

      

If you really care about performance, what would you like to do, return an array of immutable strings that all point to the same place in memory. Or, if you are interested in a truly concatenated string and not an array, just do something like

def repeatwithsep (e: string, n: int, separator: string): string
    var elen = e.length;
    var slen = separator.length;
    var a = new StringBuilder.sized ((elen * n) + (slen * (n - 1)) + 1);
    for var i = 0 to (n - 1)
        if i != 0
            a.append_len (separator, slen)
        a.append_len (e, elen)
    return (owned) a.str;

      

+2


source







All Articles