2012-12-16 8 views
10

Ich habe Hausaufgaben, wo ich irgendwie zwei HTTP-Antworten vergleichen muss. Ich schreibe es auf C und benutze libcurl, um die Dinge einfacher zu machen. Ich rufe die Funktion auf, die libcurl verwendet, um eine HTTP-Anfrage und eine Antwort von einer anderen Funktion auszuführen, und ich möchte die HTTP-Antwort als char * zurückgeben. Hier ist mein Code so weit (es stürzt ab):In C, wie benutzt man libcurl, um eine HTTP-Antwort in eine Zeichenkette zu lesen?

#include <stdio.h> 
#include <curl/curl.h> 
#include <string.h> 

size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) { 
    size_t written; 
    written = fwrite(ptr, size, nmemb, stream); 
    return written; 
} 

char *handle_url(void) { 
    CURL *curl; 
    char *fp; 
    CURLcode res; 
    char *url = "http://www.yahoo.com"; 
    curl = curl_easy_init(); 
    if (curl) { 
     curl_easy_setopt(curl, CURLOPT_URL, url); 
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 
     res = curl_easy_perform(curl); 
     if(res != CURLE_OK) 
       fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 

     curl_easy_cleanup(curl); 

     //printf("\n%s", fp); 
    } 
    return fp; 
} 

Diese Lösung C libcurl get output into a string funktioniert, aber nicht in meinem Fall, weil ich nur die Zeichenfolge an die aufrufende Funktion zurückkehren wollen.

Irgendwelche Ideen?

+0

Was ist 'char * fp;'? Warum gibst du es zurück? Wie/wo ordnen Sie Speicher zu? Wo ist meine Brille? –

+0

lol. Ich hatte Jahre, um C zu schreiben, also bin ich wieder auf Null. Die Sache ist, dass es im Beispiel "C libcurl get output in eine Zeichenfolge" funktioniert, ich verweise oben. Ich kenne die genaue Dateneingabe nicht, daher bin ich mir nicht sicher, ob die Zuweisung von Speicher für char * fp funktioniert. –

+0

Ihre 'write_data' sollte als Parameter' char * fp' übergeben werden, aber Sie haben definiert, dass sie eine 'FILE' braucht. Außerdem müssen Sie wahrscheinlich den Fall behandeln, in dem Ihr 'write_func' mehr als einmal aufgerufen wird. Wenn Sie möchten, dass dies wie erwartet funktioniert, muss 'char * fp' in' write_func() 'als Zeiger auf einen Zeiger übergeben werden, damit Sie es richtig zuordnen können. Mit anderen Worten, Ihr 'write_func()' sollte ein 'char **', nicht ein 'FILE *' nehmen. – mpontillo

Antwort

18

Es wurde für Sie behoben. Sie müssen den Fall behandeln, in dem die write_data()-Funktion mehrmals aufgerufen wird, und übergeben Sie die richtige Art von Parameter. Sie müssen auch verfolgen, wie groß eine Struktur ist, die Sie haben, damit Sie genügend Speicher reservieren können.

Ich links in einem Debug printf in der write_data Funktion, damit Sie verstehen, wie es funktioniert.

#include <stdio.h> 
#include <curl/curl.h> 
#include <string.h> 
#include <stdlib.h> 

struct url_data { 
    size_t size; 
    char* data; 
}; 

size_t write_data(void *ptr, size_t size, size_t nmemb, struct url_data *data) { 
    size_t index = data->size; 
    size_t n = (size * nmemb); 
    char* tmp; 

    data->size += (size * nmemb); 

#ifdef DEBUG 
    fprintf(stderr, "data at %p size=%ld nmemb=%ld\n", ptr, size, nmemb); 
#endif 
    tmp = realloc(data->data, data->size + 1); /* +1 for '\0' */ 

    if(tmp) { 
     data->data = tmp; 
    } else { 
     if(data->data) { 
      free(data->data); 
     } 
     fprintf(stderr, "Failed to allocate memory.\n"); 
     return 0; 
    } 

    memcpy((data->data + index), ptr, n); 
    data->data[data->size] = '\0'; 

    return size * nmemb; 
} 

char *handle_url(char* url) { 
    CURL *curl; 

    struct url_data data; 
    data.size = 0; 
    data.data = malloc(4096); /* reasonable size initial buffer */ 
    if(NULL == data.data) { 
     fprintf(stderr, "Failed to allocate memory.\n"); 
     return NULL; 
    } 

    data.data[0] = '\0'; 

    CURLcode res; 

    curl = curl_easy_init(); 
    if (curl) { 
     curl_easy_setopt(curl, CURLOPT_URL, url); 
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); 
     res = curl_easy_perform(curl); 
     if(res != CURLE_OK) { 
       fprintf(stderr, "curl_easy_perform() failed: %s\n", 
         curl_easy_strerror(res)); 
     } 

     curl_easy_cleanup(curl); 

    } 
    return data.data; 
} 

int main(int argc, char* argv[]) { 
    char* data; 

    if(argc < 2) { 
     fprintf(stderr, "Must provide URL to fetch.\n"); 
     return 1; 
    } 
    data = handle_url(argv[1]); 

    if(data) { 
     printf("%s\n", data); 
     free(data); 
    } 

    return 0; 
} 

Hinweis: kompilieren mit gcc -o test test.c -lcurl (vorausgesetzt, Sie in test.c eingefügt). Verwenden Sie gcc -o test test.c -lcurl -DDEBUG, um den Test printf() Anrufe zu sehen.

Haftungsausschluss: Dies ist hässlich, schnell und schmutzig Code. Es könnte Fehler geben. Bitte beachten Sie die more robust, better commented example here.

+0

danke @Mike, es funktioniert !!! jetzt muss ich nur noch daran denken (lesen) wie alloc und malloc funktioniert. –

+1

Herzlichen Glückwunsch, Sie haben das Beispiel gettinmemory.c libcurl erneut implementiert: http://curl.haxx.se/libcurl/c/getinmemory.html :-) –

+1

@Daniel, hah, danke für den Link. Es war eine lustige Übung, um es herauszufinden. =) – mpontillo

Verwandte Themen