Dev (Back & Front)ARTIGO

Trabalhando com expressões regulares em C++11 – Parte 02

O código para este artigo está no GitHub: https://github.com/sol-prog/regex_tutorial.

Na primeira parte deste artigo, nós usamos regex_match para verificar a entrada do usuário. O algoritmo  regex_match no C++11 voltará verdadeiro somente se a string alvo corresponder exatamente à expressão regular, por exemplo [[:digit:]]+ irá corresponder exatamente a “123”, “456” e não a “123e-05” ou “456.22”.

Se você precisar de um correspondente parcial de uma determinada string, você poderia usar regex_search, que irá retornar verdadeiro se encontrar uma correspondência parcial na string alvo (uma correspondência em uma substring da string original). Você também pode recuperar o resultado de regex_search em um objeto smatch.

Uma aplicação prática do regex_search poderia estar em remover os primeiros espaços vazios de todas as linhas de um arquivo de entrada. Suponha que você tenha um arquivo de texto mal formatado que tenha vários espaços vazios em cada linha:

The solution was obviously to compile the last versions of llvm, 

clang and libc++ from sources. Because I use my computer to hack

some Objective-C code I didn’t want to mess my system installing

new versions of llvm and clang so I’ve tried to install these on
a test Linux box. After a few hours of struggle I was able to

compile C++11 code that uses regular expressions and raw strings
literals on Linux! This was interesting enough to deserve a

separate post on my blog and hopefully will help others to get
started with clang++ and libc++ on their Linux boxes.

Poderíamos usar o poder das expressões regulares para limpar essa bagunça de todos os espaços iniciais e linhas vazias. Suponha que o texto acima tenha sido colocado em um arquivo chamado “spaces.txt”. Poderíamos implementar um pequeno código que irá limpar este arquivo:

#include <iostream>
#include <string>
#include <fstream>
#include <regex>

using namespace std;

int main()
{
ifstream inp;
ofstream out;
regex leading_spaces("[[:space:]]*(.+)");
string line;
inp.open("spaces.txt");
out.open("clear_spaces.txt");
if(inp.is_open())
{
while(inp.good())
{
getline(inp,line);
smatch result;
regex_search(line,result,leading_spaces); //search for leading spaces
if(result[1].str().length()>0) //ignore empty lines
{
out<<result[1].str()<<endl; //write on disk the cleaned line
}
}
}
inp.close();
out.close();
return(0);
}

O código acima pode ser melhorado se retirarmos os nomes de arquivo codificados e usando argc, argv para recuperar os nomes de arquivos da linha de comando. Além disso, você deveria incluir algum código de verificação de erro, o que irá acontecer por exemplo se o arquivo do input não estiver presente? O que proponho aqui é exemplificar em um simples exemplo o uso do f regex_search. Sinta-se à vontade para melhorar o código no github.

Você poderia compilar o código acima com: 

clang++ -std=c++0x -stdlib=libc++ regex_04.cpp -o regex_04.out

regex_04.cpp também pode ser compilado com Visual Studio 2010. Infelizmente, no momento da escrita deste artigo foi escrito, o gcc-4.6.1 não possui a implementação completa da funcionalidade regex.

Se você rodar regex_04, o resultado será um arquivo sem nenhum espaço por linha e sem linhas vazias.

The solution was obviously to compile the last versions of llvm,
clang and libc++ from sources. Because I use my computer to hack
some Objective-C code I didn’t want to mess my system installing
new versions of llvm and clang so I’ve tried to install these on
a test Linux box. After a few hours of struggle I was able to
compile C++11 code that uses regular expressions and raw strings
literals on Linux! This was interesting enough to deserve a
separate post on my blog and hopefully will help others to get
started with clang++ and libc++ on their Linux boxes.

Outro algoritmo útil do C++11 regex é o regex_replace, ele pode ser utilizado para substituir todas as ocorrências de um determinado padrão com uma string de formatação.

Suponha que tenhamos uma linha de texto composta de palavras e números sem uma ordem específica. Poderíamos usar o  regex_replace para extrair os números ou palavras desta linha:

#include <iostream>
#include <string>
#include <regex>

using namespace std;

int main()
{
//This should match any real number
regex number("((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?((e|E)((\\+|-)?)[[:digit:]]+)?");
//This should match any word
regex word("[[:alpha:]]+");
string input,clean_words,clean_numbers;
//Replace with an empty string
const string format="";
getline(cin,input);
//Split the input string in numbers and words
clean_numbers=regex_replace(input,number,format,regex_constants::format_default);
clean_words=regex_replace(input,word,format,regex_constants::format_default);
//Print the results
cout<<clean_words<<endl;
cout<<clean_numbers<<endl;
return(0);
}

Vamos ver o código acima em ação:

Expressões parecidas podem ser construídas para testar qualquer tipo de entrada do usuário. Se você quiser aprender mais sobre expressões regulares, a melhor fonte no campo é o livro Mastering Regular Expressions, de Jeffrey E.F. Friedl:

Para aqueles interessados em aprender a sintaxe do novo C++11, eu recomendo a leitura do Professional C++, de M. Gregoire, N. A. Solter e S. J. Kleper: 

?

Texto original disponível em http://solarianprogrammer.com/2011/10/20/cpp-11-regex-tutorial-part-2/

Matérias especiais e reportagens conduzidas internamente pela Redação iMasters. Acompanhe no Twitter @imasters e no Instagram/Threads @portalimasters

Ver perfil