使用cURL将数据从网页复制到cpp中的字符串

时间:2012-05-05 00:16:28

标签: php c++ curl webpage

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

我们正在使用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);

对其工作方式的任何解释都会很棒。 欢呼声。

2 个答案:

答案 0 :(得分: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'中的缓冲区包含嵌入的空字符,则发布的版本将提前停止。 (当然,这可能不是这个功能的用例。)

答案 1 :(得分: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;

我猜你如果找到这样的话,你就不必发表一个关于它如何运作的问题。