2017-02-21 11 views
-2

は以下の通り*私たちは文字を定義したと想定しますvoid *の末尾にchar *を追加する方法は?

char *x; 

そして、我々はそれのような機能があります。

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

この関数は、それはだ追加ポインタZを指している2番目のパラメータ( )をポインタのyという文字列の最後に指しています。私は最初のパラメータを持つように制限されています理由は無効とする*は私がlibcurl関数をオーバーライドする必要があるということです。

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

header_callback機能は、私がの最後にバッファを追加する必要があると呼ばれている任意の時間ユーザーデータ。ユーザーデータポインタが文字列の先頭を指しています。

+0

'void * y'は' std :: string'を指していますか?または 'char'バッファ? – Galik

+1

裸のポインタを持ってそれに追加するのは、あなたが境界を越えていないことを確かめることができない限り、かなり安全ではありません。 –

+1

'void'ポインタを最初に指定したタイプにキャストし、必要な操作を実行してキャリーを実行します。 'buffer * 'を使うためのトリックをコピーする通常の文字列にはカウントできないので、' size * nitems'を指定してください。 – user4581301

答えて

-1

あなたの質問はC(C++ではない)アプローチを参照しています。そして、以下が必要です。

  1. 新しい場所にサイズ+ 1つの
  2. memcpyを/ MEMMOVE yのように、Yのrealloc Y
  3. の大きさを知っているの最後のバイトを設定します
  4. 新しいバッファのポインタとサイズ
  5. 古いバッファyを解放する(必要に応じて)。

C++のhovewerでは、std :: vectorのようないくつかのコンテナを使用する必要があります。これにより、1バイトを追加できます。

+1

答えが間違っています。あまりにも多くの未知数。たとえば、バッファのサイズを変更する必要はありません。 – user4581301

+0

その後、答えではなく、質問を下ろしてください。 – dmi

+0

正確に何をしたのですか?また、投票に投票しました。 – user4581301

0

非ヌル終端文字列を付加するような方法であなたの

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

を実装することは不可能です。

コールバックに指定されたchar *bufferは、nullで終端されません。

また、appendを呼び出す前に、voidポインターをコールバック内の正しいタイプのバッファーに変換することもできます。あなたは何も追加することができないので、それは最終的に行われなければなりません。

追加は非常に簡単なので外部機能はほとんど必要ありません。std::stringにごvoid*のポイントを仮定:

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

問題は、append()がターゲットバッファを「拡張」できないことです。特にそれがstd :: stringからのものだったならば。適切なバッファをあらかじめ割り当てておき、追加がその外部で実行されないようにする必要があります – Swift

+0

@Swiftなぜ追加することができなかったのですか?特に 'std :: string'ならば、それは成長のためのinbuilt機能を持っています。要求を送信する前に応答の長さがわからない場合は、事前に事前に割り当てることはできません。あなたは通信プロトコルを扱うときにしばしばそうしません。 – user2079303

+0

私たちは記憶装置を変更することができればバッファーを知っていることはわかりません...提供された文字列の長さを知っていれば答えの長さを知ることができます。提供されたコードは、std :: stringクラスによってソースから照合されたデータを持つ新しいバッファを作成しますが、それを返そうとしても違法かもしれません。提示されたプロトタイプは、バッファアドレスの返却が許可されていないように見えます。 – Swift

0

それらのものをバッファにデータを追加するために定義する必要があります。

宛先バッファのサイズ宛先バッファに存在するバッファ内のデータの
  • 量許さ
    • 宛先バッファにコピーされるデータの量

    C realloc()は、古いバッファの内容を持つ新しいバッファを作成するために使用することができます。これは、バッファの位置を変更する場合と変更しない場合があります。 C++には、同様のアクションを可能にする新しい演算子の風味があります。

    保存されたデータが完全にヌル終端の文字列であると仮定すると、指定されていない場合でも、2番目と3番目が分かります。バッファのサイズはappend()のバッファのサイズです。そのため、機能

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

    は、ボイドyは実際にいくつかの構造体またはクラスでない限り、をタスクに適さないか、非常に危険な、おそらく不明確のどちらかになります(それとして、ボイド ???渡し)を。

    あなたはその実装または説明を提供していません。外観では、どちらかといえば限定的なものでなければなりません。適切なサイズのバッファをあらかじめ割り当てておき、append()がその範囲外で実行されないようにする必要があります。ターゲットバッファを再割り当てできないため、ですでにのメモリが割り当てられています。実際に仮パラメータとしてvoid **yまたはvoid &* yを持つことになり、目標バッファアペンドを再割り当てするには(のrealloc()かもしれ変更ポインタとが新しいバッファに古いバッファからコピーデータを行います)

    これは、アーキテクチャの問題を提起 - バッファの所有権。私たちが制御するバッファを渡すなら、それを適切に割り当ててappend()に渡すか、または所有権をappend()に渡してそれを再割り当てすることができます。私たちがしなければ、一時的なバッファを作成しなければなりません...その後、その一時的なバッファを使用できますか?

    カスタムヘッダー書き込み機能を使用している場合を除き、ポイントは偽です。ユーザーデータポインタはCURLOPT_HEADERDATAです。これは有効なFILEへのポインタであり、そのデータを_fwrite()する必要があります... CURLOPT_WRITEFUNCTIONとCURLOPT_READFUNCTIONコールバックを実装する場合、そのポインタはコールバックのデザイナの裁量でいくつかの有用なデータコンテナへのポインタ(libcurlはデフォルトのコールバックとしてfwriteを使います)。

  • 1

    リンクされたドキュメントによると、ユーザデータは、以前 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

    関連する問題