Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1

    [C++] std::string split di una linea in tre parti

    Salve,

    volevo sapere come potevo fare per dividere una stringa in tre parti, inpraticafacendo uno split(" ", line, 3)

    codice:
    #include <string>
    #include <iostream>
    
    struct reqline
    {
    	const char *method;
    	const char *uri;
    	const char *vprot;
    	reqline() : method(""), uri(""), vprot("") {}
    };
    
    bool splitReqLine(std::string const & line, reqline &rl);
    
    int main()
    {
    	std::string line = "GET /index.html HTTP/1.1";
    	reqline rl;
    
    	if( splitReqLine(line, rl) )
    	{
    		std::cout << "method: " << rq.method << std::endl;
    		std::cout << "uri: " << rq.uri << std::endl;
    		std::cout << "vport: " << rq.vprot << std::endl;
    	}
    	return 0;
    }
    
    bool splitReqLine(std::string const & line, reqline &rl)
    {
    
    	// ...code here...
    
    	return true;
    }
    la linea sarà sempre composta da: "caratteri/spazio/caratteri/spazio/caratteri"...

    come si fa lo split con std::string??

    grazie
    Alla batteria dai retta ballA

  2. #2
    Utente di HTML.it L'avatar di Stoicenko
    Registrato dal
    Feb 2004
    Messaggi
    2,254
    si usa la strtok

  3. #3
    Se vuoi usare i metodi della classe string, devi lavorare con i metodi find per trovare i delimitatori e con la substr per estrarre i token.
    Altrimenti puoi usare la strkot, come ti è stato suggerito, in una maniera simile:

    Codice PHP:
    std::vector<std::stringsplit(const std::stringstr, const chardelim){
        
    std::vector<std::stringvs;    
        
    chartoken;
        
    token strtok((char*)str.c_str(), delim);
        while (
    token != NULL){
            
    vs.push_back(std::string(token));        
            
    token strtok(NULLdelim);
        }
        
        return 
    vs;


  4. #4
    ti ringrazio! ora però vorrei fare una cosa più complessa...vorrei evitare di chiamare il metodo che poi riempe la struttura, ma bensi un costruttore che faccia tutto da solo, ovvero:

    codice:
    	struct reqline
    	{
    		const std::string method;
    		const std::string uri;
    		const std::string vprot;
    		reqline(std::string const & line); // costruttore
    	};
    così che possa fare:

    std::string line = "GET /index.html HTTP/1.1";
    reqline rl(line);

    // rl.method -> GET
    // rl.uri -> /index.html
    // vprot -> HTTP/1.1
    purtroppo però non riesco a fare una cosa del genere definendo questo costruttore:

    codice:
    	reqline::reqline(const std::string &line)
    	{
    		std::vector<std::string> vs;
    		char* token;
    		const char* delim = " ";
    		token=strtok((char*)line.c_str(), delim);
    
    		while (token != NULL)
    		{
    			vs.push_back(std::string(token));
    			token = strtok(NULL, delim);
    		}
    
    		method = vs[0];
    		uri = vs[1];
    		vprot = vs[2];
    
    	}
    in pratica non mi va l'assegnazione, però credevo che a run time si potesse assegnare un valore ad una costante in un costruttore :-(
    Alla batteria dai retta ballA

  5. #5
    da notare che tutto questo ambaradam è all'interno di un namespace

    mylib.h
    codice:
    #define _CRT_SECURE_NO_WARNINGS
    #include <string>
    #include <vector>
    
    namespace mylib
    {
    	struct reqline
    	{
    		const std::string method;
    		const std::string uri;
    		const std::string vprot;
    		reqline();
    		reqline(std::string const & line);
    	};
    
    }
    mylib.cpp
    codice:
    #include "mylib.h"
    
    namespace mylib
    {
    	// reqline
    	reqline::reqline() : method(""), uri(""), vprot("") {}
    	reqline::reqline(const std::string & line)
    	{
    		std::vector<std::string> vs;
    		char* token;
    		const char* delim = " ";
    		token=strtok((char*)line.c_str(), delim);
    
    		while (token != NULL)
    		{
    			vs.push_back(std::string(token));
    			token = strtok(NULL, delim);
    		}
    
    		method = vs[0];
    		uri    = vs[1];
    		vprot  = vs[2];
    
    	}
    }
    ma non credo che la cosa influenzi affatto il comportamento anomalo...

    da main() mi piacerebbe richiamarlo così:

    codice:
    #include <string>
    #include "mylib.h"
    using namespace mylib;
    
    int main()
    {
    	std::string line = "GET /index.html HTTP/1.1";
    	reqline rl(line);
    	(...)
    	return 0;
    }
    Per me è importante che i campi di quella struttura siano readonly...

    grazie
    Alla batteria dai retta ballA

  6. #6
    Utente di HTML.it L'avatar di Stoicenko
    Registrato dal
    Feb 2004
    Messaggi
    2,254
    ti conviene fare i campi struttura privati e non costanti..

    per accederci in lettura fai dei metodi che ritornano il valore

    oppure, non so se funziona, usi un cast per togliere il const nel momento di essegnare..
    ma credo che sia una scelta sbagliata

  7. #7
    seli faccio privati poi mi tocca fare un mini metodo pubblico per tornarli...
    Alla batteria dai retta ballA

  8. #8
    Utente di HTML.it L'avatar di Stoicenko
    Registrato dal
    Feb 2004
    Messaggi
    2,254
    non credo tu abbia tante soluzioni per tenerli readonly

  9. #9
    ho cambiato un pò il codice:

    // mylib.h
    codice:
    	struct reqline
    	{
    	public:
    		const std::string method;
    		const std::string uri;
    		const std::string vprot;
    		reqline();
    		reqline(std::string const & line);
    	private:
    		std::string getMethodFrom(const std::string & line) const;
    		std::string getUriFrom(const std::string & line) const;
    		std::string getVprotFrom(const std::string & line) const;
    	};
    // mylib.cpp
    codice:
    	reqline::reqline() : method(""), uri(""), vprot("") {}
    
    	reqline::reqline(const std::string & line) : 
    		method(getMethodFrom(line)),uri(getUriFrom(line)),vprot(getVprotFrom(line)) {}
    
    	std::string reqline::getMethodFrom(const std::string & line) const
    	{
    		const std::string delim(" ");
    		std::string::size_type first = 0;
    		std::string::size_type last = line.find_first_of(delim, first);
    		return line.substr(first, last);
    	}
    
    	std::string reqline::getUriFrom(const std::string & line) const
    	{
    		const std::string delim(" ");
    		std::string::size_type first = 0;
    		std::string::size_type last = line.find_first_of(delim, first);
    		first = last + 1;
    		last = line.find_first_of(delim, first);
    		return line.substr(first, last);
    	}
    
    	std::string reqline::getVprotFrom(const std::string & line) const
    	{
    		const std::string delim(" ");
    		std::string::size_type first = 0;
    		std::string::size_type last = line.find_first_of(delim, first);
    		first = last + 2;
    		last = line.find_first_of(delim, first);
    		return line.substr(first, last);
    	}
    nel main faccio:

    codice:
    //using namespace std;
    
    line = "GET /wiki/Pagina_principale HTTP/1.1";
    mylib::reqline rq(line);
    
    cout << endl << endl;
    cout << "method: " << rq.method << endl;
    cout << "uri: " << rq.uri << endl;
    cout << "vport: " << rq.vprot << endl;
    soltanto che method viene splittao bene: GET
    ma uri e vport ritornano la stessa riga // wiki/Pagina_principale HTT

    lo split avviene quà:

    codice:
    		const std::string delim(" ");
    		std::string::size_type first = 0;
    		std::string::size_type last = line.find_first_of(delim, first);
    		first = last + 1;
    		last = line.find_first_of(delim, first);
    		return line.substr(first, last);
    Alla batteria dai retta ballA

  10. #10
    Fondamentalmente ci sono due errori. Il metodo substr è questo

    Codice PHP:
    string substr size_t pos 0size_t n npos ) const; 
    Quindi se hai "ciao" e vuoi estrarre la 'a', devi scrivere:

    Codice PHP:
    a.substr(2,1); 
    cioè parti dal carattere due e prelevi 1 carattere. Tu invece passi come secondo argomento il termine della stringa, da quanto ho capito.

    Poi c'è un problema quando prelevi la versione del protocollo. Non capisco bene perchè scrivi first = last +2. Comunque il corpo delle get può essere questo:

    Codice PHP:
    std::string reqline::getMethodFrom(const std::string line) const
    {
        const 
    std::string delim(" ");
        
    std::string::size_type first 0;
        
    std::string::size_type last line.find_first_of(delimfirst);
        return 
    line.substr(firstlast-first); // nota last-first
    }

    std::string reqline::getUriFrom(const std::string line) const
    {
        const 
    std::string delim(" ");
        
    std::string::size_type first 0;
        
    std::string::size_type last line.find_first_of(delimfirst);    
        
    first last 1;    
        
    last line.find_first_of(delimfirst);    
        return 
    line.substr(firstlast-first); // nota last-first
    }

    std::string reqline::getVprotFrom(const std::string line) const
    {
        const 
    std::string delim(" ");
        
    std::string::size_type first 0;
        
    std::string::size_type last line.find_first_of(delimfirst);
        
    first last 1;
        
    last line.find_first_of(delimfirst);
        
    first last 1;
        return 
    line.substr(firstlast-first); // nota last-first

    Il secondo argomento della substr è last-first per indicare quanti caratteri prendere. L'ho fatto anche per getMethodFrom. In realtà first è 0 quindi last-first = last come avevi scritto, ma migliora la leggibilità.
    Quando prelevi il protocollo salti al terzo campo, quindi applichi la logica della terza e quarta riga di getUriFrom due volte in sostanza.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.