2015-07-12 75 views
0

我寫這個代碼, repeatc重複字符到char數組。它的工作原理是 。精靈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又名的memcpy)來複制一個字節是不是有點傻更。絕對沒有理由不在這裏做a[0] = e。這是更容易,並會表現更好。

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

這是非常錯誤的。您要求它將sizeof (char) * (n - 1)字節從a的位置複製到a之後的1個字節。這與你想要的非常不同,它是用數組中第一個字節的值填充其餘部分。在現實中你不應該使用Memory.copy,你應該使用Memory.setMemory.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

這真的應該是一個全新的問題,每一個stackoverflow問題都應該儘可能原子化,以便將來可以重用。 –

+0

你是對的。我發佈2個新問題 –