Atualmente, estou usando o seguinte código para aparar à direita todos os std::strings
meus programas:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
Funciona bem, mas gostaria de saber se há alguns casos finais em que pode falhar.
Obviamente, respostas com alternativas elegantes e também solução à esquerda são bem-vindas.
std::string
classe, quando são funções como essas que tornam outras linguagens tão agradáveis de usar (Python, por exemplo).Respostas:
EDIT Desde c ++ 17, algumas partes da biblioteca padrão foram removidas. Felizmente, começando com o c ++ 11, temos lambdas que são uma solução superior.
Agradecemos a https://stackoverflow.com/a/44973498/524503 por apresentar a solução moderna.
Resposta original:
Costumo usar um destes três para minhas necessidades de corte:
Eles são bastante auto-explicativos e funcionam muito bem.
EDIT : BTW, eu tenho
std::ptr_fun
lá para ajudar a desambiguar,std::isspace
porque na verdade existe uma segunda definição que suporta localidades. Este poderia ter sido um elenco da mesma forma, mas eu costumo gostar mais disso.EDIT : Para endereçar alguns comentários sobre aceitar um parâmetro por referência, modificá-lo e retorná-lo. Concordo. Uma implementação que eu provavelmente preferiria seria dois conjuntos de funções, um para o local e outro que faz uma cópia. Um melhor conjunto de exemplos seria:
Mantenho a resposta original acima, porém, por contexto e no interesse de manter a resposta mais votada ainda disponível.
fonte
boost::trim
para resolver o problema.Usar os algoritmos de string do Boost seria mais fácil:
str
é agora"hello world!"
. Há tambémtrim_left
etrim
, que apara ambos os lados.Se você adicionar
_copy
sufixo a qualquer um dos nomes de funções acimatrim_copy
, por exemplo , a função retornará uma cópia cortada da string em vez de modificá-la através de uma referência.Se você adicionar
_if
sufixo a qualquer um dos nomes de funções acimatrim_copy_if
, por exemplo , poderá cortar todos os caracteres que satisfazem seu predicado personalizado, em vez de apenas espaços em branco.fonte
Use o código a seguir para aparar à direita (à direita) espaços e caracteres de tabulação de
std::strings
( ideone ):E só para equilibrar as coisas, também incluirei o código de compensação esquerdo ( ideona ):
fonte
str.substr(...).swap(str)
é melhor. Salve uma atribuição.basic_string& operator= (basic_string&& str) noexcept;
?O que você está fazendo é bom e robusto. Eu uso o mesmo método há muito tempo e ainda não encontrei um método mais rápido:
Ao fornecer os caracteres a serem aparados, você tem a flexibilidade de aparar caracteres que não sejam espaços em branco e a eficiência de aparar apenas os caracteres que deseja aparar.
fonte
trim
, ou seja, torná-lortrim(ltrim(s, t), t)
ele vai ser um pouco mais eficienteUm pouco tarde para a festa, mas não importa. Agora que o C ++ 11 está aqui, temos variáveis lambdas e auto. Portanto, minha versão, que também lida com espaços em branco e strings vazios, é:
Poderíamos criar um iterador reverso
wsfront
e usá-lo como condição de finalização no segundo,find_if_not
mas isso só é útil no caso de uma cadeia de espaços em branco, e o gcc 4.8 pelo menos não é inteligente o suficiente para inferir o tipo do iterador reverso (std::string::const_reverse_iterator
) comauto
. Eu não sei o quão caro é a construção de um iterador reverso, então YMMV aqui. Com essa alteração, o código fica assim:fonte
std::isspace
:auto wsfront=std::find_if_not(s.begin(),s.end(),std::isspace);
candidate template ignored: couldn't infer template argument '_Predicate' find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred)
Tente isso, funciona para mim.
fonte
str.find_last_not_of(x)
retorna a posição do primeiro caractere diferente de x. Ele retorna npos apenas se nenhum caractere não corresponder a x. No exemplo, se não houver espaços com sufixo, ele retornará o equivalente astr.length() - 1
, produzindo essencialmentestr.erase((str.length() - 1) + 1).
Isto é, a menos que eu esteja terrivelmente enganado.std::string&
.Eu gosto da solução do tzaman, o único problema é que ele não apara uma string contendo apenas espaços.
Para corrigir essa falha, adicione str.clear () entre as duas linhas do aparador
fonte
ltrim
ourtrim
assim.std::stringstream
.http://ideone.com/nFVtEo
fonte
it
) e reverse: posição do caractere após o qual existem apenas espaços (rit
) - depois disso, ele retorna uma string recém-criada == uma cópia da parte da string original - uma parte com base nessas iterators ...No caso de uma cadeia vazia, seu código pressupõe que adicionar 1 a
string::npos
0.string::npos
for do tipostring::size_type
não assinado. Assim, você está confiando no comportamento de adição de transbordamento.fonte
1
astd::string::npos
deve dar de0
acordo com oC++ Standard
. Portanto, é uma boa suposição que pode ser absolutamente invocada.Hackeado do Cplusplus.com
Isso funciona também para o caso nulo. :-)
fonte
rtrim
, não #ltrim
Com o C ++ 17, você pode usar basic_string_view :: remove_prefix e basic_string_view :: remove_suffix :
Uma boa alternativa:
fonte
Minha solução com base na resposta de @Bill the Lizard .
Observe que essas funções retornarão a sequência vazia se a sequência de entrada contiver nada além de espaço em branco.
fonte
Minha resposta é uma melhoria na resposta superior desta publicação que apara caracteres de controle e espaços (0-32 e 127 na tabela ASCII ).
std::isgraph
determina se um caractere tem uma representação gráfica; portanto, você pode usá-lo para alterar a resposta de Evan para remover qualquer caractere que não tenha uma representação gráfica de ambos os lados de uma sequência. O resultado é uma solução muito mais elegante:Nota: Como alternativa, você poderá usá-
std::iswgraph
lo se precisar de suporte para caracteres largos, mas também precisará editar esse código para ativar astd::wstring
manipulação, algo que não testei (consulte a página de referência parastd::basic_string
explorar esta opção) .fonte
Com o C ++ 11, também veio um módulo de expressão regular , que obviamente pode ser usado para aparar espaços à esquerda ou à direita.
Talvez algo parecido com isto:
fonte
É isso que eu uso. Continue removendo o espaço da frente e, se sobrar alguma coisa, faça o mesmo por trás.
fonte
fonte
Para o que vale a pena, aqui está uma implementação elegante com um olho no desempenho. É muito mais rápido do que muitas outras rotinas de corte que eu já vi por aí. Em vez de usar iteradores e std :: found, ele usa strings e índices c brutos. Otimiza os seguintes casos especiais: tamanho 0 string (não faça nada), string sem espaço em branco para aparar (não faça nada), string com apenas espaço em branco à esquerda para aparar (apenas redimensione a string), string que seja totalmente em branco (limpe a string) . E, finalmente, na pior das hipóteses (string com espaço em branco à esquerda), ele faz o possível para executar uma construção de cópia eficiente, executando apenas 1 cópia e movendo essa cópia no lugar da string original.
fonte
Uma maneira elegante de fazer isso pode ser como
E as funções de suporte são implementadas como:
E uma vez que você tenha todas essas opções, você também pode escrever:
fonte
Apare a implementação do C ++ 11:
fonte
Eu acho que se você começar a pedir a "melhor maneira" de cortar uma string, eu diria que uma boa implementação seria aquela que:
Obviamente, existem muitas maneiras diferentes de abordar isso e isso definitivamente depende do que você realmente precisa. No entanto, a biblioteca padrão C ainda possui algumas funções muito úteis em <string.h>, como o memchr. Há uma razão pela qual C ainda é considerado o melhor idioma para IO - seu stdlib é pura eficiência.
fonte
Não tenho certeza se o seu ambiente é o mesmo, mas no meu, o caso de cadeia vazia fará com que o programa seja interrompido. Gostaria de quebrar essa chamada de apagar com um if (! S.empty ()) ou usar o Boost, como já mencionado.
fonte
Aqui está o que eu vim com:
A extração de fluxo elimina os espaços em branco automaticamente, portanto, isso funciona como um encanto.
Muito limpo e elegante também, se é que digo. ;)
fonte
Contribuindo com minha solução para o barulho.
trim
O padrão é criar uma nova string e retornar a modificada enquantotrim_in_place
modifica a string passada para ela. Atrim
função suporta semântica de movimento c ++ 11.fonte
Isso pode ser feito de maneira mais simples no C ++ 11 devido à adição de
back()
epop_back()
.fonte
Aqui está a minha versão:
fonte
Os métodos acima são ótimos, mas às vezes você deseja usar uma combinação de funções para o que sua rotina considera como espaço em branco. Nesse caso, o uso de functores para combinar operações pode ficar confuso, por isso prefiro um loop simples que posso modificar para o ajuste. Aqui está uma função de recorte ligeiramente modificada, copiada da versão C aqui no SO. Neste exemplo, estou aparando caracteres não alfanuméricos.
fonte
Aqui está uma implementação direta. Para uma operação tão simples, você provavelmente não deve usar nenhuma construção especial. A função isspace () incorporada cuida de várias formas de caracteres em branco, portanto devemos tirar proveito dela. Você também deve considerar casos especiais em que a string está vazia ou simplesmente vários espaços. O corte à esquerda ou à direita pode ser derivado do código a seguir.
fonte
Aqui está uma solução fácil de entender para iniciantes que não costumam escrever em
std::
todos os lugares e ainda não estão familiarizados comconst
-correctness,iterator
s, STLalgorithm
s, etc ...Espero que ajude...
fonte
Esta versão apara espaços em branco internos e não alfanuméricos:
fonte
Ainda outra opção - remove um ou mais caracteres de ambas as extremidades.
fonte