Джинн, как повторить строку N раз как строковый массив
Я пишу этот код, repeatc для повторения символов в массив символов. оно работает.
повторяется для повторения строки 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
Почему это ядро кода сброшено? и как это исправить?
1 ответ
Есть несколько вещей не так с этим кодом.
[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 (он же memcpy в 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;