2013-12-19 136 views
4

我正在爲Ruby編寫一個C擴展,我需要接受一個字符串作爲參數,並迭代字符串中的字符。我的代碼在ASCII字符下工作正常,但它不處理多個字節字符,而是輸出「垃圾」。我找不到任何可以迭代unicode字符串的示例代碼。我會很感激任何指針。在C擴展中的unicode字符串

static VALUE test_method(VALUE self, VALUE text) 
{ 
    char *pch; 
    char *pch_end = RSTRING_END(text); 

    for (pch = RSTRING_PTR(text); pch < pch_end; pch++) 
    { 
     printf("%c\n", *pch); 
    } 
    ... 
} 

回答

3

這裏是你可以遍歷字符一種方式的示例:

static VALUE print_single_char(VALUE s) 
{ 
    char* pch; 
    pch = StringValueCStr(s); 

    // pch is now a pointer to a sequence of bytes representing the 
    // character in whatever its encoding was. printf will work if the 
    // console encoding is the same, otherwise you may get junk again. 
    printf("%s\n", pch); 

    return Qnil; 
} 

static VALUE test_method(VALUE self, VALUE text) 
{ 
    rb_block_call(text, rb_intern("each_char"), 0, NULL, print_single_char, Qnil); 

    return Qnil; 
} 

注意,一旦你轉換任何字符C字符串你失去任何相關的編碼信息。您可能想在做任何事情之前將任何輸入轉換爲已知編碼(例如UTF-8):

text = rb_funcall(text, rb_intern("encode"), 1, rb_str_new_cstr("utf-8")); 
1

char只有大小爲1,所以如果你處理多字節字符,你將不得不使用wchar_t代替並使用適當的寬版本,以及像wprintf

+0

如果我的字符串是UTF8,那麼我需要檢查每個字符的寬度。有沒有API? – akonsu

+0

所以你的意思是你得到一個指針,你事先不知道哪種字符串是? – Devolus

+0

'wchar_t'具有固定大小(32位?),但UTF8字符串可以具有不同長度的字符(從一個字節到我認爲五個字節)。 – akonsu