2011-11-11 35 views
36

C'è qualche modo in C++ per verificare se una stringa inizia con una certa stringa (più piccola dell'originale)? Proprio come possiamo fare in Javacome verificare l'inizio della stringa in C++

bigString.startswith(smallString); 
+0

stai parlando stringhe C o std: : String –

+0

sto parlando di C++ string.std :: string –

risposta

65
std::string s("Hello world"); 

if (s.find("Hello") == 0) 
{ 
    std::cout << "String starts with Hello\n"; 
} 
+0

@avakar Sono d'accordo. Non ho ancora provato le espressioni regolari di C++ 11, ma sarebbe anche una soluzione e, si spera, più efficiente? –

+3

Penso che regex sia una cattiva scelta per un controllo così semplice, vedere la mia risposta per quello che penso sia una soluzione efficiente per questo problema. O ancora meglio, Alan Stokes risponde con string :: compare(). – Kleist

+5

Una soluzione efficiente dovrebbe essere 'O (min (bigString.length(), smallString.length()))' –

25

Gli approcci utilizzando string::find() o string::substr() non sono ottimali perché sia ​​fare una copia della stringa, o la ricerca di più di partite all'inizio della stringa. Potrebbe non essere un problema nel tuo caso, ma se è possibile utilizzare l'algoritmo std::equal. Ricordati di controllare che il "pagliaio" sia lungo almeno quanto "l'ago".

#include <string>  

using namespace std; 

bool startsWith(const string& haystack, const string& needle) { 
    return needle.length() <= haystack.length() 
     && equal(needle.begin(), needle.end(), haystack.begin()); 
} 
-1

O creare una stringa che è la lunghezza della variabile smallString, e confrontare i due. Oppure effettuare una ricerca per la sottostringa smallString e vedere se restituisce l'indice 0

0

strstr() restituisce un puntatore alla prima occorrenza di una stringa all'interno di una stringa.

55

È possibile eseguire questa operazione con string::compare(), che offre varie opzioni per il confronto di tutte o parte di due stringhe. Questa versione confronta smallString con il prefisso dimensione appropriata di bigString (e funziona correttamente se bigString è più breve di smallString):

bigString.compare(0, smallString.length(), smallString) == 0 

tendo a avvolgere questo in una funzione gratuita chiamata startsWith(), poiché in caso contrario si può guardare un po ' misterioso.

UPDATE: C++20 is adding nuova starts_with e ends_with funzioni, in modo sarete finalmente in grado di scrivere solo bigString.starts_with(smallString).

14

La soluzione corretta, come sempre, proviene da Boost: boost::algorithm::starts_with.

+12

Awful da usare boost solo per fare questo semplice compito. – Borzh

+1

@Borzh, sicuramente stai già utilizzando Boost pesantemente nei tuoi progetti, perché no per questo? – avakar

+37

Non tutti usano boost. E per scaricarlo, metterlo nel repository solo per usare starts_with() è un po 'esagerato. Forse dovresti considerare di rimuovere "La soluzione corretta, come sempre ...". Non è né "corretto" né "sempre". – Borzh

1

L'approccio più semplice potrebbe essere:

if (smallString.size() <= bigString.size() 
    && std::equals(smallString.begin(), smallString.end(), bigString.end()) 

(Questo funziona anche se uno dei due, o entrambi, è un vettore O qualsiasi altro tipo container standard..)

+1

-1 1) Non riesco a trovare nessuno std :: equals. Intendevi: std :: uguale? 2) sei sicuro con bigString.end() - ci si aspetterebbe bigString.begin()? 3) risposta di Kleist postata prima sembra di avere tutto a posto – Suma

+0

Sì, ad entrambi. È 'std :: equal', e dovrebbe essere' bigString.end() '. –

5

Per ottimizzare un po ':

if (smallString.size() <= bigString.size() && 
    strncmp(smallString.c_str(), bigString.c_str(), smallString.length()) == 0) 

non dimenticare di #include <cstring> o #include <string.h>

0

Ho pensato che pubblicare una soluzione grezza che non utilizza alcuna funzione di libreria ...

// Checks whether `str' starts with `start' 
bool startsWith(const std::string& str, const std::string& start) { 
    if (&start == &str) return true; // str and start are the same string 
    if (start.length() > str.length()) return false; 
    for (size_t i = 0; i < start.length(); ++i) { 
     if (start[i] != str[i]) return false; 
    } 
    return true; 
} 

Aggiunta di un semplice std::tolower possiamo fare questo case insensitive

// Checks whether `str' starts with `start' ignoring case 
bool startsWithIgnoreCase(const std::string& str, const std::string& start) { 
    if (&start == &str) return true; // str and start are the same string 
    if (start.length() > str.length()) return false; 
    for (size_t i = 0; i < start.length(); ++i) { 
     if (std::tolower(start[i]) != std::tolower(str[i])) return false; 
    } 
    return true; 
} 
0

Mi sorprende che nessuno ha scritto ancora questo metodo:

#include <string>  
using namespace std; 

bool starts_with(const string& smaller_string, const string& bigger_string) 
{ 
    return (smaller_string == bigger_string.substr(0,smaller_string.length())); 
} 
Problemi correlati