0

我从他在网上找到的朋友那里得到了一个功能。问题是,我们都不明白它是如何工作的。它将网页的内容复制到字符串中。

我们使用 cURL 连接到一个 php 页面。有问题的功能是:

std::string contents;

size_t handle_data(void *ptr, size_t size, size_t nmemb, void *stream)
        {
                    int numbytes = size*nmemb;
                    char lastchar = *((char *) ptr + numbytes - 1);
                    *((char *) ptr + numbytes - 1) = '\0';
                    contents.append((char *)ptr);
                    contents.append(1,lastchar);
                    *((char *) ptr + numbytes - 1) = lastchar;  // Might not be necessary.
                    return size*nmemb;
        }

它在此函数中调用:

curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,handle_data);

任何关于它如何工作的解释都会很棒。干杯。

4

2 回答 2

2

我认为这是正确的:

std::string contents;

size_t handle_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
  // The number of bytes to transfer is simply the
  // number of elements (nmemb) times the size of
  // each element (size).
  int numbytes = size*nmemb;

  // Remember the last character of the data we'll
  // be appending to 'contents', because we're about
  // to overwrite it with a zero C-string nul terminator.
  char lastchar = *((char *) ptr + numbytes - 1);

  // Overwrite the last character of ptr's data block
  // with zero, which is a C-string's nul-terminator.
  *((char *) ptr + numbytes - 1) = '\0';

  // Append the C-string which begins at 'ptr' to
  // 'contents'.
  contents.append((char *)ptr);

  // Now tack on the last character that we remembered above.
  contents.append(1,lastchar);

  // Restore the original data buffer's last character
  // in case the caller expects it to still be the same.
  *((char *) ptr + numbytes - 1) = lastchar;  // Might not be necessary.

  // Return the number of bytes  that were appended
  // to 'contents'.
  return size*nmemb;
}

说了这么多,我不确定为什么 handle_data() 的全部内容不只是这样:

size_t handle_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
    contents.append((char*)ptr, size*nmemb);
    return size*nmemb;
}

...我认为这将完成完全相同的事情,只是更正确,因为如果“ptr”处的缓冲区包含嵌入的空字符,则发布的版本将提前停止。(当然,无论如何,这可能不是这个函数的用例。)

于 2012-05-05T00:38:12.233 回答
1

如果我必须描述它是如何工作的,我会说:“不是特别好”。

int numbytes = size*nmemb;

这将计算缓冲区的大小——项目数 * 每个项目的大小。

char lastchar = *((char *) ptr + numbytes - 1);

这将保存缓冲区中的最后一个字符以供以后使用。

*((char *) ptr + numbytes - 1) = '\0';

这会在缓冲区中添加一个 NUL 终止符,覆盖当前最后一个字符(这就是前面保存它的原因)。

contents.append((char *)ptr);

这会将(截断的)缓冲区附加到字符串。

contents.append(1,lastchar);

这会将保存的最后一个字符添加到字符串中。

*((char *) ptr + numbytes - 1) = lastchar;  // Might not be necessary.

这会将最后一个字符恢复到缓冲区中。

return size*nmemb;

这将返回缓冲区大小。

我想我应该解释为什么我说这不太好。并不是最终结果看起来是错误的,而是因为缓冲区中最后一个字符的所有旋转都是完全没有必要的。您可以指定附加到字符串的数量,而不是 NUL 终止缓冲区:

size_t numbytes = size * nmemb;
contents.append((char *)ptr, numbytes);
return numbytes;

...或者,如果您更喜欢类似迭代器的用法:

size_t numbytes = size * nmemb;
char *p = (char *)ptr;
contents.append(p, p+numbytes);
return numbytes;

我猜如果你找到了这样的一个,你就不必发布一个关于它是如何工作的问题。

于 2012-05-05T00:37:44.007 回答