2009-04-07 10 views

risposta

2

Scrivere un parser personalizzato o utilizzare una delle funzioni di sostituzione stringa per sostituire il separatore ':' e quindi utilizzare sscanf().

+15

Ci sono molte trappole da guardare, quindi un parser personalizzato mi sembra una cattiva idea. – bortzmeyer

+0

@bortzmeye: ciò non rende il suggerimento non valido. È un vago ragionamento. Inoltre, un parser personalizzato è il più potente/efficiente/gratuito. Sscanf è più facile da sbagliare. – dirkgently

+4

come è "scrivere un codice che fa ciò di cui hai bisogno" una risposta accettata? – Spike0xff

9

Con un regular expression se si desidera il modo semplice. Altrimenti utilizzare FLEX/BISON.

Si potrebbe anche usare un URI parsing library

+1

In effetti, l'uso di una libreria sembra l'unica cosa ragionevole, dal momento che ci sono molte trappole (http vs https, porta esplicita, codifica nel percorso, ecc.). – bortzmeyer

+0

Ciao, ho scritto un BNF per url, come questo. URL = "http: //" {IP} {PORT}? {PAGINA}? Un flex ha generato un file che ha analizzato l'url. Ma come recuperare le singole parti come IP, PORT e PAGE. dall'URL –

9

Ho writed un semplice utilizzo di codice sscanf. Voglio avere un modo base per analizzarlo.

cat urlparse.c 
#include <stdio.h> 

int main(void) 
{ 
    const char text[] = "http://192.168.0.2:8888/servlet/rece"; 
    char ip[100]; 
    int port = 80; 
    char page[100]; 
    sscanf(text, "http://%99[^:]:%99d/%99[^\n]", ip, &port, page); 
    printf("ip = \"%s\"\n", ip); 
    printf("port = \"%d\"\n", port); 
    printf("page = \"%s\"\n", page); 
    return 0; 
} 

./urlparse 
ip = "192.168.0.2" 
port = "8888" 
page = "servlet/rece" 
+0

Quale piattaforma è attiva?Non sapevo che potessi inserire espressioni regolari come [^:] in un formato sscanf. –

+0

La mia piattaforma è: uname -a Ubuntu Linux 2.6.24-21-generiC# 1 SMP mar 21 ott 23:43:45 UTC 2008 i686 GNU/Linux –

+4

[^:] non è un'espressione regolare in questo contesto, è semplicemente un identificatore di formato speciale per sscanf(). È standard Vedi ad esempio questa pagina di manuale: . – unwind

22

Personalmente, mi rubano il modulo HTParse.cfrom the W3C (è usato nel browser lynx Web, per esempio). Quindi, è possibile fare cose come:

strncpy(hostname, HTParse(url, "", PARSE_HOST), size) 

La cosa importante su come utilizzare una biblioteca ben consolidata e il debug è che tu non cadere nella tipica trappole di analisi degli URL (molte espressioni regolari falliscono quando l'host è un Indirizzo IP, ad esempio, specialmente uno IPv6).

+1

In particolare, tenere presente che con IPv6 esistono casi ambigui se si tenta di utilizzare il separatore dei due punti. per esempio. 3ffe: 0501 :: 1: 2, è una porta di 2 o un indirizzo completo con la porta predefinita. Le specifiche dell'URL si sono occupate di questo, così come le librerie pre-scritte. – bitmusher

+3

Nota non c'è vera ambiguità. Lo standard URI, RFC 3986, è chiaro e il tuo esempio è illegale (hai bisogno di parentesi quadre). – bortzmeyer

+2

Grazie, questo è confortante. Avevo l'impressione sbagliata che il codice di fronte utente, come le barre degli indirizzi del browser, accettasse gli indirizzi senza parentesi quadre. Un rapido tour di alcuni browser popolari rivela che questo non è il caso. – bitmusher

2

Questo ha dimensioni ridotte e ha funzionato perfettamente per me http://draft.scyphus.co.jp/lang/c/url_parser.html. Solo due file (* .c, * .h).
Ho dovuto adattare il codice [1].

[1] modificare tutte le chiamate di funzione da http_parsed_url_free (rovescio) per parsed_url_free (rovescio)

//Rename the function called 
    //http_parsed_url_free(purl); 
    parsed_url_free(purl); 
+2

@ tremendows: collegamento eccellente. Esso funziona magicamente. –

+3

Purtroppo quel codice eccellente è protetto da copyright "tutti i diritti riservati", quindi non dovrebbe essere usato in un progetto personale. –

+1

Link eccellente. Funziona come un fascino –

0

Ciò C sostanza potrebbe essere utile. Implementa una soluzione C pura con sscanf.

https://github.com/luismartingil/per.scripts/tree/master/c_parse_http_url

Esso utilizza

// Parsing the tmp_source char* 
if (sscanf(tmp_source, "http://%99[^:]:%i/%199[^\n]", ip, &port, page) == 3) { succ_parsing = 1;} 
else if (sscanf(tmp_source, "http://%99[^/]/%199[^\n]", ip, page) == 2) { succ_parsing = 1;} 
else if (sscanf(tmp_source, "http://%99[^:]:%i[^\n]", ip, &port) == 2) { succ_parsing = 1;} 
else if (sscanf(tmp_source, "http://%99[^\n]", ip) == 1) { succ_parsing = 1;} 
(...) 
+0

terzo se la dichiarazione non verrà mai verificata, perché la seconda ha lo stesso significato, quindi questo potrebbe causare un problema con la porta/pagina – Risinek

9

Può essere in ritardo, ... quello che ho usato, è - la funzione http_parser_parse_url() e le macro necessarie separati dalla Joyent/HTTP parser lib - che ha funzionato bene, ~600 LOC.

+0

Sì. La pars HTTPj di node.js HTTP è ottima e molto ben collaudata per tutto ciò che ha a che fare con le richieste/risposte HTTP. –

Problemi correlati