2015-07-12 4 views
0

Я пишу этот код, repeatc для повторения char для массива char. Это работает.Genie howto повторяет строку N раз как строковый массив

повторяет для повторяется строка N раз в массив строк. , но повторите строку, чтобы ядро ​​массива сбрасывалось.

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

Почему? мой код:

// --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 

Почему этот код ядро ​​сбрасывали? и как это исправить?

ответ

2

Есть несколько вещей, которые не соответствуют этому коду.

[indent=4] 

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

Фактически, он печатает «A, A, A» (обратите внимание на конечную запятую и пробел). Есть много способов исправить это, самым простым было бы сделать что-то вроде 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)) 

Используя Memory.copy (а.к.а. тетсру в C), чтобы скопировать один байт является больше, чем немного глупо. Нет абсолютно никакой причины не просто делать здесь a[0] = e. Это проще и будет работать лучше.

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

Это очень неправильно. Вы сообщаете ему скопировать sizeof (char) * (n - 1) байт из местоположения a в 1 байт после a. Это очень отличается от того, что вы намерены намереваться, чтобы заполнить остальную часть a значением первого байта в массиве. В действительности вы не должны использовать Memory.copy, вы должны использовать Memory.set: Memory.set (a, e, n) может заменить оба эти Memory.copy строк.

Это, скорее всего, то, что вы действительно хотите, это строка, а не массив символов. Если это так, вы можете заменить эту целую функцию и просто позвонить 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? 

Вам по-прежнему нужен цикл. После того, как вы начнете пытаться использовать функции Memory.*, вы работаете с указателями, поэтому вам нужно понять, как выкладывается память. Строки - это действительно массивы символов, а массивы - только указатели на первый элемент массива. Когда вы создаете массив строк, то, что у вас есть, является указателем на указатель (в C, gchar**), а не на указатель на большой смежный блок, в который вы можете начать копировать свои данные символов.

Я думаю, вы пытаетесь использовать Memory.copy вместо цикла и простого назначения для повышения производительности; единственное, что действительно плохо для производительности здесь, состоит в том, что простое назначение вызовет g_strdup, которое вызовет strlen, так что вы закончите сканирование своей строки ввода N раз, чтобы вычислить длину вместо одного раза. Лучшее, что вы собираетесь получить, вероятно, что-то вроде:

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

Если вы действительно заботитесь о производительности, что вы хотели бы сделать, это возвращает массив строк, не имеющих владельца указывают на то же место в памяти.Или, если вас интересует действительно объединенная строка, а не массив, просто сделайте что-нибудь вроде

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; 
+0

Привет, меня очень интересует ваш код. прочитайте их и принесите мне больше вопросов. 1: вы можете показать код: ** вернуть массив неизмененных строк, которые все указывают на одно и то же местоположение ** 2: почему вы добавляете ** (принадлежит) ** в конце ** repeatwithsep * * функция? ** var a ** - локальная переменная, когда она оставлена ​​этой функцией, она будет уничтожена? –

+0

Это действительно должно быть совершенно новые вопросы, каждый вопрос о стековом потоке должен быть как можно более атомарным, чтобы сделать его многоразовым для будущих ссылок. –

+0

yor являются правильными. Я отправляю 2 новых вопроса –

 Смежные вопросы

  • Нет связанных вопросов^_^