0

私は彼がネットで見つけた友人から機能を得ました。問題は、私たちのどちらもそれがどのように機能するかを理解していないということです。Webページのコンテンツを文字列にコピーします。

phpページに接続するためにcURLを使用しています。問題の関数は次のとおりです。

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 に答える