2017-02-21 91 views
-2

假設我們已經定義了一個char *如下:如何將一個char *追加到void *的末尾?

char *x; 

而且我們有喜歡它的功能:

void append(void *y, char *z); 

該函數將它的第二個參數(在指針ž所指向)到指針指向它開始的字符串的末尾。 ,我限制爲具有第一個參數的原因是無效*是,我需要重寫一個libcurl功能:

size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata); 

任何時候header_callback函數被調用,我需要追加緩衝區結束用戶數據。 userdata指針指向一個字符串的開頭。

+0

'void * y'指向'std :: string'嗎?或者一個'char'緩衝區? – Galik

+1

只具有裸指針和追加到它是非常不安全的,除非你能確保你不會出界。 –

+1

將'void'指針重新轉換爲您首先提供的任何類型,執行您所需的任何操作,即可繼續。確保你提供'size * nitems',因爲你不能指望通常的字符串複製技巧來處理'buffer'。 – user4581301

回答

-1

你的問題看起來更多的是指C(而不是C++)的方法。然後,你需要以下條件:

  1. 知道在y
  2. 的realloc的Y中的大小+ 1
  3. 的memcpy /的memmove y以新的地方
  4. 設置的最後一個字節的大小新的緩衝區到
  5. 返回給用戶指針和新緩衝區的大小
  6. 釋放舊的緩衝區y(取決於需要)。

在C++ hovewer中,你需要使用一些像std :: vector這樣的容器,它可以讓你追加一個字節。

+1

不好回答。太多未知數。例如,可能不需要調整緩衝區的大小。 – user4581301

+0

然後挫敗問題,而不是答案。 – dmi

+0

正是我所做的。也投票結束。 – user4581301

0

這是不可能實現的

void append(void *y, char *z); 

以這樣一種方式,它可以附加一個非空終止字符序列。

給予回調的char *buffer非空終止。

另外,在調用append之前,您可以將void指針轉換爲回調中正確類型的緩衝區。這必須最終完成,因爲你不能追加任何東西來無效。

你幾乎不需要外部函數,因爲追加很簡單。假設你void*指向一個std::string

auto bytes = size * nitems; 
auto str = (std::string*)userdata; 
str->append(buffer, bytes); 
+0

問題在於append()不能「增長」目標緩衝區。特別是如果那是來自std :: string的。我們應該預先分配適當的緩衝區並確保append不會在其外運行 – Swift

+0

@Swift爲什麼無法追加增長目標緩衝區?特別是如果它是'std :: string',它具有內置的增長功能。除非您在發送請求之前知道響應的長度,否則無法準確預分配。當你處理通信協議時,你通常不會這樣做。 – user2079303

+0

我們不知道,我們知道緩衝區,也就是說,如果我們可以改變它的存儲......如果我們知道提供的字符串的長度,我們可能知道答案的長度。所提供的代碼會創建一個新的緩衝區,並通過std :: string類從源代碼中整理數據......但即使嘗試返回它也可能是非法的。呈現的原型看起來不像是允許返回緩衝區地址。 – Swift

0

要追加的數據到緩衝器的那些東西應該被定義:

    在目標緩衝區中緩衝區本數據的 目標緩衝區的
  • 允許大小
  • 要複製到目標緩衝區的數據量

在C realloc()中可以用來創建一個新的緩衝區,其中的內容可能會或可能不會改變緩衝區的位置。在C++中,有一種允許類似操作的新操作符。

如果我們假設存儲的數據是嚴格null結尾的字符串(但即使未指定!),那麼第二個和第三個被稱爲 - 緩衝區的大小是未知的追加()是緩衝區的大小。因此,函數

void append(void *y, char *z); 

查找任務或者不適宜或非常不安全和可能的不明確的,除非空隙ý實際上是一些結構或類(但順便指出爲void ???)

您沒有提供實現或它的描述。看起來應該是比較有限的一個。我們應該預先分配一個合適大小的緩衝區,並確保append()不會超出邊界。它不能重新分配目標緩衝區,所以它是由已經分配的內存限制。要真正重新分配目標緩衝區追加會有void **yvoid &* y作爲形式參數(realloc()的可能變化指針和確實複製數據從舊的緩衝區,新緩衝區)

這提出了一個架構問題 - 緩衝的所有權。如果我們傳遞了我們控制的緩衝區,我們可以正確地分配緩衝區並將其傳遞給append()或將所有權傳遞給append(),以便重新分配它。如果我們不這樣做,我們必須創建一個時間緩衝區......但是我們可以使用那個時間緩衝區嗎?

的一點是沒有實際意義,除非你正在使用自定義標題寫功能。用戶數據指針CURLOPT_HEADERDATA,要麼是指向有效的文件,你應該_fwrite()數據吧...或者,如果要實現CURLOPT_WRITEFUNCTION和CURLOPT_READFUNCTION回調,該指針可以在回調的設計師的謹慎使用,作爲指向一些有用的數據容器的指針(libcurl使用fwrite作爲默認回調)。

1

根據您鏈接的文檔, userdata是先前提供給 CURLOPT_HEADERDATA的指針。像這樣的東西可能適合你。

size_t header_callback(char *buffer, size_t size, size_t nitems, vector<string> *userdata) 
{ 
    userdata->push_back(string(buffer, size*nitems)); 
    return size*nitems; 
} 

//... 
vector<string> headers; 
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &headers); 
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback); 
//... 
+0

應該爲自定義HEADERDATA定義新的回調,默認情況下它必須是FILE * – Swift

+0

@Swift'CURLOPT_HEADERFUNCTION'是新的回調函數,所以'CURLOPT_HEADERDATA'的默認值不適用。 @Bediver,回調的最後一個參數必須是'void *'以匹配所需的原型。 – user2079303

+0

@ user2079303只有在兩個函數都重新定義的情況下,OP_had_用CURLOPT_WRITEDATA選項設置一個新值。再次,太多未知數。在他寫的所有內容中,我有一個印象,它被設置爲char *,這就是append()使用的原因 – Swift