2017-02-21 54 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

相关问题