"Rozsekání" URL do struktury – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

"Rozsekání" URL do struktury – C / C++ – Fórum – Programujte.com"Rozsekání" URL do struktury – C / C++ – Fórum – Programujte.com

 

HonzaC
~ Anonymní uživatel
6 příspěvků
14. 2. 2013   #1
-
0
-

Ahoj, 

chtěl bych se zeptat jak nejelegantněji rozsekat url do struktury na potřebné části. 

Chtěl bych to udělat nějak elegantně v c++, jsem schopen to udělat "škaredě" = spousta ifů, vybírání podřetězců atd ... 

chtěl jsem to udělat nějak elegantně, pomocí regulárních výrazů. Nevím jesli je to c++ mozne, predstavoval bych si to tak, ze na retezec aplikuju nejaky regularni vyraz a volana funkce mi vrati polozky treba v poli, kde budou jednotlive casti regularniho vyrazu. 

treba http://www.example.com/path/soubor.txt

bych potreboval rozsekat na 

protokol=http 
domena =www.example.com
port=80
cesta=path/soubor.txt
nazevSouboru=soubor.txt

Nevite o nejakem elegantnim reseni, by mi treba v poli na zaklade regularniho vyrazu vratilo tyto hodnoty, a fungovalo i kdyz tam nahodou treba ten protokol, nebo port neni. 


Dekuji za odpoved.
 

Nahlásit jako SPAM
IP: 90.177.17.–
vitamin+8
Grafoman
14. 2. 2013   #2
-
0
-
Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
HonzaC
~ Anonymní uživatel
6 příspěvků
14. 2. 2013   #3
-
0
-

Ano o to jsem se pokousel, ale psalo mi to neco o experimentali verzi, a ze se to musi prekladat s parametrem

-std=c++0x 

A ja nevim jesli po odevzdani ve skole nepouziji vlastni makefile. Coz by mi asi udelalo projekt nefunkcnim :]. 

Nicmene to zkusim zjistit. 

Nahlásit jako SPAM
IP: 90.177.17.–
KIIV
~ Moderátor
+43
God of flame
14. 2. 2013   #4
-
0
-

ten regex z g++ moc nedoporucuju.. sem to zkousel ani zdaleka neni funkcni... to same s boostem fungovalo uplne v pohode...

+ pokud by slo i o rychlost, tak na todle staci stavovy automat... regex je velice vyrazne pomalejsi

Nahlásit jako SPAM
IP: 94.112.35.–
Program vždy dělá to co naprogramujete, ne to co chcete...
HonzaC
~ Anonymní uživatel
6 příspěvků
14. 2. 2013   #5
-
0
-

Udelam to automatem. O rychlost ani nejde. Slo mi spis o to abych to mel co nejkratsi a samotnemu se mi to libilo. Nicmene objevovanim regexu jak v cpp tak v c jsem stravil asi den, a zase tolik casu na to nemam. 

Dekuji za rady. Pekny den.

Nahlásit jako SPAM
IP: 90.177.17.–
KIIV
~ Moderátor
+43
God of flame
14. 2. 2013   #6
-
0
-

#5 HonzaC
me u toho  <regex> trvalo hodinu nez sem konecne pochopil ze to maj proste rozbity...

Nahlásit jako SPAM
IP: 94.112.35.–
Program vždy dělá to co naprogramujete, ne to co chcete...
vitamin+8
Grafoman
14. 2. 2013   #7
-
0
-

#6 KIIV


Bohuzial to musim potvrdit, skusil som prelozit par prikladov cppreference.com a nic z toho nejde. Skoda :(

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
vitamin+8
Grafoman
14. 2. 2013   #8
-
0
-

#1 HonzaC


Tak som si to skusil naprogramovat a rozsekat to bez regexu je asi jednoduhsie ako sa babrat s roznymi kninicami :)

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
HonzaC
~ Anonymní uživatel
6 příspěvků
14. 2. 2013   #9
-
0
-

#8 vitamin
a vysledek? :] ja na tom take ted delam, nikdy jsem v c++ nedelal. Ale delam to s tim, pac se tam mnohem jednoduseji pracuje se stringem. Konstrukce kterymi se snazim zajistit to ze port a protokol jsou nepovinne casti v mem podani, se mi vubec nelibi. Ale ocekavam ze to bude fungovat. Nevim teda proc by nemelo :] 

Nahlásit jako SPAM
IP: 90.177.17.–
vitamin+8
Grafoman
14. 2. 2013   #10
-
0
-

#9 HonzaC

Daj sem tvoj kod, ak bude aspon z casti OK, tak ti sem hodim riesenie (ale je v c++11).

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
HonzaC
~ Anonymní uživatel
6 příspěvků
14. 2. 2013   #11
-
0
-

#10 vitamin
timto resim vytazeni protokolu z url. S tim ze pocitam s tim ze je nepovinny

parametrem funkce mi prijde ukazatel na strukturu s tim co chci vracet "source" a string "url"

    int urlBegin = 0;
    string tempUrl = url; 

 
    //hledam to co byva za protokolem ://
   
    int pointer = tempUrl.find("://");
    if (pointer != string::npos) {
        source->scheme = tempUrl.substr(urlBegin, pointer);
        tempUrl = tempUrl.erase(urlBegin, pointer + strlen("://"));

        cout << "\nscheme: " << source->scheme;
        cout << "\ntail: " << tempUrl;
   
    }else{
        source->scheme = "http";
       
        cout << "\nscheme: " << source->scheme;
        cout << "\ntail: " << tempUrl;
    }

.... jsou v tom pomocne vypisy ... za timto ifem se pracuje s tempUrl ... ze ktereho se snazim (jeste to nemam :]) dostat adresu, port, ktery je nepovinny, cestu k souboru a nazev souboru. 

Nahlásit jako SPAM
IP: 90.177.17.–
vitamin+8
Grafoman
14. 2. 2013   #12
-
0
-

#11 HonzaC
Mozes to riesit cez stavovy automat. Vstup budes prechadzat znak po znaku. V stavoch si budes uchovavat informaciu ktoru cast url-ky nacitavas a v pomocnom stringu budes mat nacitane znaky(pre danu cast url).

Nevyhoda tohto riesenia je ze tam bude dost stavov.

Ja som to spravyl tak ze om si vstup rozsekal na tokeny {key, value}, na to mi stacil stavovy automat s 2 stavmi. Key je enum{OPERATOR, WORD} a value je std::string. Takto spracovany vstup porovnavam sekvencne z lava do prava pomocou vzorov, ak sa pociatocne tokeny rovnaju vzoru, tak tokeny spracujem a zmazem, potom pokracujem na dalsi vzor. Tu je kod:

#include <regex>
#include <iterator>
#include <iostream>
#include <string>
#include <algorithm>
#include <cassert>
#include <map>
 
enum key_e{
	WORD,		//aj text aj cisla
	OPERATOR	//vsetko ostatne
};
struct Token{
	key_e key;
	std::string value;
	
	Token(key_e key):key(key){}
	Token(key_e key, std::string value):key(key), value(value){}
};

/*
 * Upravi vstupny stringu na vektor tokenov
 * (Mozno by bolo lepsie spravyt este 1 stav a umoznit spjit viacej operatorov do jedneho ak su vedla seba, zjednodusil by sa potom kod v maine)
*/
template <class Iterator>
std::vector<Token> lex(Iterator begin, Iterator end){
	std::vector<Token> tokens;
	
	enum state_e{
		Begin,
		Word
	};
	
	std::string value;
	state_e state = Begin;
	
	for(;begin != end; begin++){
		char c = *begin;
		if(std::isalpha(c) || std::isdigit(c)){
			switch(state){
				case Begin:
					value += c;
					state = Word;
					break;
				case Word:
					value += c;
					break;
			}
		}
		else if(std::isspace(c)){
			break;
		}
		else switch(state){
				case Begin:
					tokens.push_back({OPERATOR, {c}});
					break;
				case Word:
					tokens.push_back({WORD, value});
					tokens.push_back({OPERATOR, {c}});
					value.clear();
					state = Begin;
					break;
			}
	}
	switch(state){
		case Begin:
			break;
		case Word:
			tokens.push_back({WORD, value});
			break;
	}
		
	return std::move(tokens);
} 

/*
 * porovna N tokenov z &tokens s tokenmi s &pattern, kde N je pocet tokenov v &pattern 
 */
size_t parse(const std::vector<Token>& tokens, const std::vector<Token>& pattern){
	if(tokens.size() < pattern.size())return 0;
	
	if(std::equal(pattern.begin(), pattern.end(), tokens.begin(), [](const Token& p, const Token& t){
		return 
			(p.key == t.key) 	//kluce sa musia rovnat
			&& p.value.empty()?true:(p.value==t.value);	//hodnoty sa musia rovnak len ak je hodnota definovana v pattern.value
	}))return pattern.size();
	
	return 0;
}

int main()
{
	std::string str = "https://domena.sk:80/cesta/cesta/subor.hpp ";
	auto tokens = lex(str.begin(), str.end());
	
	std::map<std::string, std::string>   data;
	data["error"] = "false";
	
	// HTTP:
	if(size_t s = parse(tokens, {WORD, {OPERATOR, ":"}, {OPERATOR, "/"}, {OPERATOR, "/"}})){
		if(tokens[0].value == "http" || tokens[0].value == "https")data["http"] = tokens[0].value;
		tokens.erase(tokens.begin(), tokens.begin() + s);
	}
	else if(size_t s = parse(tokens, {{WORD, "www"}, {OPERATOR, "."}})){
		data["http"] = tokens[0].value;
		tokens.erase(tokens.begin(), tokens.begin() + s);
	}
	
	//DOMENA:
	while(size_t s = parse(tokens, {WORD, {OPERATOR, "."}})){
		data["domena"] += tokens[0].value;
		data["domena"] += tokens[1].value;
		tokens.erase(tokens.begin(), tokens.begin() + s);
	}
	
	if(size_t s = parse(tokens, {WORD})){
		if(data.find("domena") == data.end()){
			data["error"] = "true";
			data["domena"] = "<error>";
		}
		data["domena"] += tokens[0].value;
		tokens.erase(tokens.begin(), tokens.begin() + s);
	}
	else{
		data["error"] = "true";
		data["domena"] += "<error>";
	}
	
	//PORT:
	if(size_t s = parse(tokens, {{OPERATOR, ":"}, WORD})){
		data["port"] = tokens[1].value;
		tokens.erase(tokens.begin(), tokens.begin() + s);
	}
	
	//CESTA & SUBOR:
	while(size_t s = parse(tokens, {{OPERATOR, "/"}, WORD})){
		if(data["subor"].size())data["cesta"] += tokens[0].value;
		data["cesta"] += data["subor"];
		data["subor"] = tokens[1].value;
		tokens.erase(tokens.begin(), tokens.begin() + s);
	}
        //PRIPONA SUBORU:
	if(size_t s = parse(tokens, {{OPERATOR, "."}, WORD})){
		data["subor"] += tokens[0].value;
		data["subor"] += tokens[1].value;
		tokens.erase(tokens.begin(), tokens.begin() + s);
	}
	else{
		data["error"] = "true";
		data["subor"] += "<error>";
	}
	
	if(tokens.size())data["error"] = "true";
	
	//VYPIS:
	for(auto&d : data)std::cout << d.first << ": " << d.second << std::endl; 
}

edit: oprava chyby v lex pri teste isspace().

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
HonzaC
~ Anonymní uživatel
6 příspěvků
14. 2. 2013   #13
-
0
-

pekne funguje, a mozna si z nej casti vypujcim. Skoda jen ze je to tak dlouhe, snazim se to asi resit moc obecne a pozadavek je aby to melo par radku a kazdy pochopil co myslim. Nicmene pokud bych se s kazdym ukolem do skoly takhle sral, tak dopadnu spatne. Kor kdyz si to tam po me ani nikdo neprecte.\

Diky

Nahlásit jako SPAM
IP: 90.177.17.–
vitamin+8
Grafoman
14. 2. 2013   #14
-
0
-

#13 HonzaC
Co znamena ze je to moc dlhe? Ved 160 riadkov je na program malo, hlavne ked tam je plno switchov...

skratena verzia  http://pastebin.com/NhQtQz0R

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 127 hostů

Podobná vlákna

Rozsekání programu — založil ReVolt

čtení url/braní dat z url — založil tribalcz

Struktury — založil Samuel Lehotský

Struktury v C++ — založil pin2k

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý