Genie howto repeat a string N times as an string array

丶灬走出姿态 提交于 2019-12-11 20:35:41

问题


I write this code, repeatc for repeat char to char array. it works.

repeats for repeat string N times to an string array. but repeat string to string array core dumped.

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 this code core dumped? and How to fix it?


回答1:


There are several things wrong with 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 lots of ways to fix this, the easiest would just 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 (a.k.a. memcpy in C) to copy a single byte is a more than a little silly. There is absolutely no reason not to just do a[0] = e here. It is easier and will perform better.

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

This is very wrong. You're telling it to copy sizeof (char) * (n - 1) bytes from the location a to 1 byte after a. This is very different than what you seem to intend, which is to fill the rest of a with the value of the first byte in the array. In reality you shouldn't be using Memory.copy, you should be using Memory.set: Memory.set (a, e, n) can replace both those Memory.copy lines.

That said, it's likely that what you really want is a string not an array of chars. If that's the 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. Once you start trying to use the Memory.* functions you're working with pointers, so you need to understand how the memory is laid out. Strings are really just arrays of characters, and arrays are just pointers to the first element in 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 into.

I guess you're trying to use Memory.copy instead of a loop and simple assignment to improve performance; the only thing really bad thing for performance here is that a simple assignment will call g_strdup which will call strlen, so you end up scanning your input string N times to calculate the length instead of once. The best you're going to get is probably 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 you would want to do is return an array of unowned strings that all point to the same location in memory. Or, if what you're interested in is really the joined string and not the 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;


来源:https://stackoverflow.com/questions/31370915/genie-howto-repeat-a-string-n-times-as-an-string-array

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!