Voglio inserire 'n' spazi (o qualsiasi stringa) all'inizio di una stringa in C ++. C'è un modo diretto per farlo utilizzando std :: strings o char * strings?
Ad esempio, in Python potresti semplicemente farlo
>>> "." * 5 + "lolcat"
'.....lolcat'
Voglio inserire 'n' spazi (o qualsiasi stringa) all'inizio di una stringa in C ++. C'è un modo diretto per farlo utilizzando std :: strings o char * strings?
Ad esempio, in Python potresti semplicemente farlo
>>> "." * 5 + "lolcat"
'.....lolcat'
Risposte:
Nel caso particolare di ripetizione di un singolo carattere, puoi utilizzare std::string(size_type count, CharT ch):
std::string(5, '.') + "lolcat"
NB. Non può essere utilizzato per ripetere stringhe multi-carattere.
Non esiste un modo idiomatico diretto per ripetere stringhe in C ++ equivalenti all'operatore * in Python o all'operatore x in Perl. Se stai ripetendo un singolo carattere, il costruttore a due argomenti (come suggerito dalle risposte precedenti) funziona bene:
std::string(5, '.')
Questo è un esempio artificioso di come potresti usare un ostringstream per ripetere una stringa n volte:
#include <sstream>
std::string repeat(int n) {
std::ostringstream os;
for(int i = 0; i < n; i++)
os << "repeat";
return os.str();
}
A seconda dell'implementazione, questo potrebbe essere leggermente più efficiente della semplice concatenazione della stringa n volte.
Usa una delle forme di string :: insert:
std::string str("lolcat");
str.insert(0, 5, '.');
Questo inserirà "....." (cinque punti) all'inizio della stringa (posizione 0).
So che questa è una vecchia domanda, ma stavo cercando di fare la stessa cosa e ho trovato quella che penso sia una soluzione più semplice. Sembra che cout abbia questa funzione incorporata in cout.fill (), vedere il collegamento per una spiegazione "completa"
http://www.java-samples.com/showtutorial.php?tutorialid=458
cout.width(11);
cout.fill('.');
cout << "lolcat" << endl;
uscite
.....lolcat
cout << "" << endl;
Ai fini dell'esempio fornito dal PO std :: ctor della stringa è sufficiente: std::string(5, '.'). Tuttavia, se qualcuno sta cercando una funzione per ripetere std :: string più volte:
std::string repeat(const std::string& input, unsigned num)
{
std::string ret;
ret.reserve(input.size() * num);
while (num--)
ret += input;
return ret;
}
Come alludeva il Commodoro Jaeger, non credo che nessuna delle altre risposte risponda effettivamente a questa domanda; la domanda chiede come ripetere una stringa, non un carattere.
Sebbene la risposta data da Commodore sia corretta, è piuttosto inefficiente. Ecco un'implementazione più veloce, l'idea è di ridurre al minimo le operazioni di copia e le allocazioni di memoria aumentando prima in modo esponenziale la stringa:
#include <string>
#include <cstddef>
std::string repeat(std::string str, const std::size_t n)
{
if (n == 0) {
str.clear();
str.shrink_to_fit();
return str;
} else if (n == 1 || str.empty()) {
return str;
}
const auto period = str.size();
if (period == 1) {
str.append(n - 1, str.front());
return str;
}
str.reserve(period * n);
std::size_t m {2};
for (; m < n; m *= 2) str += str;
str.append(str.c_str(), (n - (m / 2)) * period);
return str;
}
Possiamo anche definire un operator*per ottenere qualcosa di più vicino alla versione Python:
#include <utility>
std::string operator*(std::string str, std::size_t n)
{
return repeat(std::move(str), n);
}
Sulla mia macchina questo è circa 10 volte più veloce dell'implementazione fornita da Commodore, e circa 2 volte più veloce di una soluzione ingenua "aggiungi n - 1 volte" .
+=all'interno del tuo ciclo for internamente ha anche un ciclo di qualche tipo che fa str.size()iterazioni. str.size()cresce in ogni iterazione del ciclo esterno, quindi dopo ogni iterazione esterna il ciclo interno deve eseguire più iterazioni. La tua implementazione e l'ingenua "copia n volte" in totale copiano entrambi i n * periodcaratteri. La tua implementazione esegue solo un'allocazione di memoria a causa dell'iniziale reserve. Immagino che tu abbia profilato la tua implementazione con un piccolo stre un grande n, ma non anche con un grande stre un piccolo n.
stre piccoli ntra i due approcci. Credo che questo abbia più a che fare con la pipeline complessiva che con la previsione dei rami di per sé, ci sono anche problemi di allineamento dei dati da considerare. Dovresti porre una nuova domanda per i dettagli del motivo per cui è più compatibile con il processore / la memoria, sono sicuro che guadagnerebbe molto interesse e riceverebbe una risposta migliore di quella che posso dare qui.
rep movsbè uno dei modi più efficienti per copiare, almeno per copie medio-grandi. La sua implementazione microcodificata ha un overhead di avvio quasi costante (sia su AMD che Intel), ad esempio su Sandybridge, da ~ 15 a 40 cicli, più 4 cicli per linea di cache da 64B (caso migliore) . Per le piccole copie, un ciclo SSE è il migliore perché non ha il sovraccarico di avvio. Ma poi è soggetto a errori di previsione del ramo.
ITNOA
Puoi usare la funzione C ++ per farlo.
std::string repeat(const std::string& input, size_t num)
{
std::ostringstream os;
std::fill_n(std::ostream_iterator<std::string>(os), num, input);
return os.str();
}