Este semana rolou um email bem legal na lista de emails cppbrasil, o email continha o link para um mapa do C++ no estilo usado em mapas antigos:

O post original do mapa pode ser encontrado clicando-se aqui, inclusive contem opções de tamanho.
Este semana rolou um email bem legal na lista de emails cppbrasil, o email continha o link para um mapa do C++ no estilo usado em mapas antigos:

O post original do mapa pode ser encontrado clicando-se aqui, inclusive contem opções de tamanho.
O primeiro post do blog foi exatamente este, e não querendo já parecer sessão da tarde e começar a repetir tudo de novo estou re-fazendo o post.
O post original é bem incompleto em vários aspectos, e ao invés de atualizar ele decidi fazer um completamente novo aproveitando que estou configurando uma maquina de build.
Outra vantagem deste artigo é que indo direto a seção “Configurando o Visual”, as informações ali contidas servem para a maioria das bibliotecas de C/C++.
Esta é a etapa mais simples de todas, basta acessar o site oficial, e clicar no link “Download” do lado direito da tela. A versão 1.39.0 (a ultima lançada até o dia que esse artigo foi publicado) pode ser baixada clicando aqui.
No meu caso utilizo a versão zip do pacote, mas todos os outros pacotes acredito que possuam o mesmo conteúdo.
Após o download extraia o conteúdo dos arquivos para o diretório de bibliotecas que você costuma utilizar, no meu caso c:\develop\libs.
Depois de extrair os arquivos é necessário baixar o bjam, que é a ferramenta de compilação da Boost, a ultima versão pode ser encontrada clicando aqui.
Após concluído o download do bjam extraia o arquivo exe para o mesmo diretório em que a Boost foi colocada (no meu caso C:\develop\libs\boost_1_39_0).
Agora com as ferramentas prontas é necessário rodar o bjam, para tal acesse o console do Visual Studio (não o console padrão do Windows) clicando em “Iniciar” –> Todos os programas –> Microsoft Visual Studio –> Visual Studio Tools –> Visual Studio 2008 Command Prompt.
Com o console aberto abra o diretório da Boost (no meu caso digito: cd \develop\libs\boost_1_39_0). Dentro do diretório da boost digite “bjam” e ENTER.
Agora como já diz o programa, paciência…
Se tudo correu bem, muitos minutos depois a compilação deve estar completa, as vezes aparecem alguns warnings, que eu simplesmente ignoro.
O jeito mais pratico de configurar o visual na minha opinião é criando uma variável de ambiente que contenha o diretório da Boost, fica mais pratico na hora de atualizar as versões (se não quiser criar a variável, basta ir para o próximo paragrafo), então primeiramente clique em “Iniciar” –> Botão direito em “Meu Computador” –> Propriedades. Na janela que se abrir, clique em “Avançado”, depois no botão “Variáveis de Ambiente”. Na caixa “Variáveis do Sistema”, clique em “Novo”. Agora entre com o nome (ex: BOOST_HOME), e o valor, que é o diretório onde a boost foi instalada (c:\develop\libs\boost_1_39_0 no meu caso), agora é ir clicando em Ok até fechar tudo.
O próximo passo é abrir o visual (se o seu visual já estava aberto e você criou a variável, feche ele e abra novamente). Dentro do visual acesse “Tools” –> “Options”, expanda a linha “Projects and Solutions” –> “VC++ Directories”.
Com a janela de configuração de diretórios podemos configurar os diretórios utilizados pelo visual durante builds, o primeiro a ser configurado é o de include (a ordem não importa aqui), então do lado direito, na caixa de seleção “Show directories for”, selecione “Include Files”. Basta clicar na primeira linha vazia após o ultimo item e entrar com o diretório, que no meu caso foi: $(BOOST_HOME). Caso eu não tivesse criado a variável, o valor teria sido: c:\develop\libs\boost_1_39_0.
Por fim é necessário configurar o diretório de bibliotecas selecionando “Libraries Files” na caixa “Show Directories for” e entrando com o diretório das libs, que no meu caso foi: $(BOOST_HOME)\stage\lib, se não estiver usando a variável, basta então: c:\develop\libs\boost_1_39_0\stage\lib, note que o diretório varia de acordo com o diretório que foi usado na instalação, mas o principal é o sub-diretório “stage\lib”.
Tendo inserido os diretórios, clique em Ok para salvar.
Para testar a instalação crie um novo projeto no Visual (se não sabe como fazer, clique aqui) e use um código exemplo da Boost, eu utilizei o código abaixo:
#include<boost/filesystem/operations.hpp>
#include<iostream>
namespace bf = boost::filesystem;
int main(int, char **)
{
bf::path p("first.cpp");
if(bf::exists(p))
std::cout<<p.leaf()<<"exists.\n";
else
std::cout<<p.leaf()<< "does not exist.\n";
return 0;
}
O código compilou sem problemas aqui e executou perfeitamente, sendo assim, instalação concluída.
Note que a Boost automaticamente já linka o código com as bibliotecas necessárias, com algumas bibliotecas é necessário configurar o arquivo lib a ser usado, mas isso fica para outro post.
Foi lançada a mais nova versão da Boost, desta vez inclui apenas uma lib nova, a Signals2, que é uma implementação de um sistema de sinais e slot, na verdade essa lib é uma implementação thread safe da Signals já existente. Além desta lib nova foram feitas diversas correções e melhoramentos nas libs existentes, maiores detalhes no release notes.
No artigo anterior vimos de maneira mais detalhada como realizar um build no Visual e diversas configurações, agora vamos expandir um pouco mais nosso ambiente instalando a Windows SDK, que consiste num kit de desenvolvimento para aplicações Windows.
Pode ser que seu projeto não precise utilizar a API do Windows diretamente, mas outras libs podem precisar (Boost por exemplo).
Para baixar a SDK basta acessar o link de download: Windows SDK for Windows Server 2008 and .NET Framework 3.5, para baixar uma imagem de DVD ISO com toda a SDK, use esse link.
No meu caso optei por instalar a versão web, pois como não utilizo todos os componentes não preciso fazer todo o download.
Após o donwload do programa setup, basta rodar ele. Surge então a primeira tela do setup, clicando em next ele pergunta sobre os diretórios de destino (no meu caso, uso o valor padrão).
Em seguida o instalador pergunta sobre os componentes a instalar, no meu caso dispenso qualquer coisa relacionada a desenvolvimento 64 bits (minhas maquinas são todas 32 bits), dispenso também os samples (exemplos) e documentação (que pode ser vista online), minha configuração ficou:
As seleções aqui são um tanto pessoais e dependem do que você pretende fazer, mas o principal a instalar são os componentes do Windows Headers and Libraries, incluindo no minimo os “Header Files” e alguma das “Libraries”. Lembre-se que se for incluído apenas as bibliotecas para CPU 64 bits, será possível apenas compilar código para essa arquitetura.
Clicando em “next”, o instalador vai iniciar o download e a instalação logo após a conclusão deste.
A instalação é bem básica, e apos a conclusão basta clicar em “Finish”.
Se tudo correu bem, agora basta pegar o programa “Hello World” do primeiro artigo da série e modifica-lo:
#include <windows.h>
int main(int argc, char **argv)
{
MessageBox(NULL, L"Ola Windows!", L"Teste", MB_OK);
return 0;
}
Agora é compilar e executar o programa, durante a execução deve ser surgir uma dialogo com a mensagem definida acima.
No próximo post vou aproveitar e atualizar o artigo de compilação da Boost, que esta incompleto e desatualizado.
No artigo anterior vimos como instalar e como criar um programa de teste no visual, agora vamos nos aprofundar um pouco mais no sistema de build do visual.
O visual por padrão possui duas configurações de build, a debug e a release. Cada versão permite que o usuário configure o compilador de maneiras totalmente diferentes, além de ser possível criar quantas configurações forem necessárias.
Estas configurações são uteis para permitir, por exemplo, desabilitar qualquer otimização do compilador e facilitar a depuração de código (fato que já ocorre na configuração Debug gerada quando um projeto é criado), sendo assim, a versão debug é geralmente usada apenas pelos desenvolvedores.
Já a versão release liga as otimizações do compilador e (geralmente) desliga a geração de informações de debug, sendo esta usada para se realizar um build quando queremos enviar o software ao usuário final.
A configuração atual pode ser visualizada no topo da janela do visual, próximo as opções de menu:
Na figura acima vemos que a configuração ativa é a Debug, clicando na caixa de seleção é possível alterar a configuração a ser usada no próximo build.
Além das configurações de build, é possível especificar uma plataforma para cada configuração, como por exemplo Win32 e Win64, como nunca trabalhei com desenvolvimento multi-plataforma no visual (nos projetos multi-plataforma que trabalhei usávamos uma IDE para cada ambiente) não vou me aprofundar nesse item.
Na figura abaixo podemos ver as opções do menu build do visual, que são descritas a seguir:
Vemos que o menu de build é divido em quatro seções, sendo estas:
Note que os comandos de compilação são basicamente:
Detalhe que os comandos relacionados ao projeto não afetam unicamente o projeto sendo editado, podem afetar as suas dependências, se existirem múltiplos projetos dentro de uma solução, os comandos da seção projeto vão afetar as dependências também, para aplicar o comando apenas ao projeto selecionado, escolha as opções do item “Project Only”. Veremos o uso de dependências em mais detalhes no próximo post.
O runtime (no caso do visual) é a forma como seu projeto é associado a biblioteca padrão do C ou C++ (a libc), que no caso do visual pode ser uma dll, as famosas MSVC???.lib, onde ??? varia de acordo com a versão e tipo de build, ou então, uma lib que é linkada diretamente com seu projeto.
Mas para que especificar uma biblioteca C/C++, não deveriam ser iguais? Sim, deveriam, mas a Microsoft disponibiliza dois tipos básicos, uma versão debug e outra versão release.
A versão debug da libc gera informações extras de depuração que veremos em detalhes no post sobre como usar o depurador do visual, já a versão release não possui essas informações e é construída com todas as otimizações possíveis.
Além da versão debug e release, existem para cada uma delas a versão DLL e não DLL. A diferença entre elas é que na versão DLL, seu código é linkado com a MSVC???.dll, na versão não dll (estática), o seu código é linkado diretamente com o arquivo lib não precisando da dll para ser executado.
Para configurar o runtime sendo usado basta clicar com o botão direito do mouse sobre um projeto, e escolher “Properties”:
Na janela que abrir, basta expandir a “Configuration Properties”, depois o item “C/C++”, e clicar em “Code Generation”, do lado deve surgir então o item “Runtime Library”, como na figura abaixo:
As opções são:
Detalhe que todas as libs são especificadas como multi-threaded, isso indica que elas podem ser usadas com código multi-thread (antigamente existia também a opção single thread).
Um detalhe que pode passar despercebido sobre a janela de propriedades é que existe uma versão para cada configuração, a configuração sendo utilizada fica no canto superior esquerdo da janela de configurações.
A escolha do runtime depende muito do tipo de projeto, e a decisão se baseia entre versão DLL ou não DLL, sendo debug e release escolhidos de acordo com o tipo de build.
A versão DLL é recomendada se seu projeto utiliza dlls, isso é necessário porque se o seu projeto usar a versão não dll da libc, cada dll e o exe do seu programa vão ter sua própria heap. Como cada módulo possui sua própria heap, a memória alocada em um módulo (dll ou exe), utilizando new ou malloc, tem quer ser liberada apenas no mesmo módulo, a estrutura do programa fica como no exemplo abaixo:
Já o mesmo programa utilizando a versão da libc para dlls, fica com a estrutura como na figura abaixo:
Sendo assim, se seu projeto utiliza dlls, é recomendável linkar ele apenas com a versão dll da libc.
Na configuração padrão de projetos do visual, ele cria duas sub-pastas uma para os builds de debug, e outra para release:
Nestas duas pastas são colocados os arquivos gerados durante o build, no caso do build de release do meu programa de testes:
Exceto por hello.exe, todos os outros arquivos são utilizados apenas pelo visual durante um build. Isso significa que para enviar esse programa para alguem basta enviar o arquivo exe gerado, que é suficiente para este programa funcionar.
Outro detalhe que como o conteúdo destas pastas é todo gerado pelo visual, removendo qualquer um ou todos os arquivos não causa problema algum, basta executar o build que o visual os gera novamente.
O visual permite modificar a pasta usada para armazenar os arquivos gerados e a maneira mais simples consiste em acessar as propriedades do projeto (clicando com o botão direito sobre o projeto no Solution Explorer, e clicando em “Properties”), na janela que abrir, selecione a opção General, que fica dentro de “Configuration Properties”, deve surgir então a opção “Output Directory”, que indica o diretório usado:
O caminho padrão é um pouco estranho, pois consiste de: $(SolutionDir)$(ConfigurationName). Isso na verdade são duas variáveis de ambiente criadas pelo visual, sendo que $(SolutionDir) e $(ConfigurationName) contém respectivamente o diretório da solução e o diretório da configuração sendo usada. Pode-se por exemplo modificar para: $(SolutionDir)\bin, com esta alteração o arquivo exe vai ser ser gerados no diretório bin.
Alterando o valor da opção “Intermediate Directory” modifica o diretório de destino dos arquivos temporários (como arquivos obj).
No próximo post, vamos ver como instalar a Windows SDK no visual.
O Visual Studio é um pacote de programas da Microsoft para desenvolvimento de software, suportando diversas linguagens como C#, C++, C, Java, Visual Basic, etc. Nesta série de artigos vou focar apenas no Visual C++ Express 2008, mas a maioria da dicas / comandos devem funcionar em outras versões do Visual C++.
As versões express do Visual Studio são versões grátis que a microsoft disponibiliza e obviamente elas não possuem todas as funcionalidades das versões pagas, mas na minha opinião o Visual C++ Express é a melhor ferramenta “grátis” para se trabalhar com C++ no Windows.
O primeiro passo é instalar a ferramenta, e o jeito mais simples é indo ao site oficial: Visual C++ Express. Logo ali no lado direito tem um botão “Download Now”, escolha a linguagem (Inglês no meu caso) e clique em Download.
Após concluído o download, execute o programa para inicializar a instalação que a principio é como qualquer outro programa, aceitar licença, instalar algum atalho extra, etc.
A versão atual do instalador pergunta se você quer instalar o Microsoft Silverlight Runtime e o Microsoft SQL Server, nenhum dos dois é necessário, a menos que você queira usar o SQL Server como banco de dados para suas aplicações ou utilizar o Silverlight
Após escolher os adicionais, vem a escolha do diretório de instalação, de novo, é a gosto do fregues. Clicando em “Next” é iniciado o download. Existe no site da Microsoft imagens de CD para quem quiser instalar em um computador que não tenha acesso a rede.
Após concluída a instalação, o instalador cria um atalho no menu iniciar, basta então acessar ele e clicar no “Microsoft Visual C++ Express Edition 2008″. O Visual vai carregar e você deve ver uma tela parecida com a abaixo:
A versão express costuma solicitar registro, basta seguir o link do dialogo que surgir, entrar com os dados e depois inserir a chave de registro no visual.
O Visual Studio gerencia o software criado através de soluções, cada solução possui um ou mais projetos, que formam o software ou o conjunto de software sendo criado.
Para criarmos nosso “Hello Visual”, clique em “File” -> “New” -> “Project”. Surge então um dialogo parecido com o abaixo:
Clique em Win32, depois selecione “Win32 Console Application”. Entre com o nome do projeto, diretório onde ele vai ser criado, e nome da solução (que é opcional), em seguida clique em “Ok”.
Surge então a primeira tela do Application Wizard, clique em “Next”, na segunda tela selecione “Console Application” e marque a caixa “Empty Project “. Dessa forma é criada uma aplicação vazia, e sem o código de “Hello World” do visual. Depois de criado, o projeto pode ser modificado para aplicação com janela, dll ou biblioteca.
Agora clique em “Finish” e o projeto vai ser criado.
Após criada a aplicação, deve surgir então o “Solution Explorer”, que é uma janela (que costuma ficar do lado esquerdo da tela) com a visão de todos os projetos e arquivos da sua solução.
No nosso caso ela vai estar vazia, agora criaremos o primeiro arquivo de código: clique com o botão direito do mouse no nome do projeto (meuPrimeiroProjeto, no exemplo), selecione “Add” -> “New Item”. Na janela que aparecer, selecione “C++ File (.cpp)”, entre com o nome do arquivo e clique em “Add”.
Vai surgir então um lindo arquivo em branco, repare no “Solution Explorer” que o arquivo foi adicionado ao seu projeto, agora basta entrar com o código do “Hello World”:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("Hello Visual");
return 0;
}
Após entrar com o código, clique na opção “Build” (menu principal) e selecione “Build”, ou então pressione F7. Na parte de baixo da tela vai surgir a tela de output, que mostra o que o compilador esta fazendo, e no final do processo ela indica se houve algum erro ou não. Se aconteceu algum erro, dando um clique duplo sobre a mensagem de erro foca o mesmo na tela.
Agora que o projeto já foi compilado, basta executar ele. No menu principal, selecione “Debug” -> “Start Without Debugging”, ou pressione “CTRL + F5″. Pronto, vai surgir uma janela de console com a saída do seu programa.
No proximo post, vamos aprender um pouco mais sobre o build do visual.
Foi lançado no ultimo dia 8 a versão 1.38.0 da Boost, que além de inúmeras correções de bugs inclui três novas bibliotecas:
Caso tenha dificuldades em compilar esta novar versão, experimente ler o artigo: Compilando a Boost.
No ultimo post mostrei as operações básicas com strings como contar caracteres e comparações, agora vamos nos aprofundar um pouco mais.
Primeiramente, como funciona um char? O char em C é um int pequeno (geralmente 8 bits) sinalizado (o char pode ser sinalizado ou não, dependendo da plataforma), a questão é que o char armazena números, e os números representam caracteres. Mas qual número é qual? O Visual (e acho que quase todos compiladores) usam como base a tabela ASCII que define o valor numérico de cada caracter.
Com base nisso, podemos então escrever:
#include <stdio.h>
int main(int, char **)
{
char ola[4];
ola[0] = 111;
ola[1] = 108;
ola[2] = 97;
ola[3] = 0;
printf(ola);
return 0;
}
No código acima inicializamos a string “ola” usando os valores numéricos dela, mas qual a vantagem disso? Nenhuma, na verdade apenas facilitamos a vida do compilador, mas o que pode ser feito de útil com esse conhecimento?
A primeira coisa que pode ser feita é traduzir o outdoor da EA:

Agora vamos supor que seja necessário criar um programa para verificar se uma string possui apenas caracteres de A a Z (caixa alta):
#include <iostream>
bool ehAZ(const char *str)
{
for(int i = 0;str[i]; ++i)
{
if((str[i] < 'A') || (str[i] > 'Z'))
return false;
}
return true;
}
int main(int argc, char **argv)
{
using namespace std;
cout << ehAZ("ABC") << endl;
cout << ehAZ("ABaC") << endl;
cout << ehAZ("!@#$%") << endl;
return 0;
}
Note que na tabela ASCII letras e números estão em sequência, por isso não precisamos nos preocupar em testar todas as letras, podemos testar apenas sequências.
Agora vamos ver como fica uma rotina para mudar todas as letras de uma string para maiúsculas:
#include <iostream>
char *toUp(char *str)
{
for(int i = 0;str[i]; ++i)
{
if((str[i] >= 'a') && (str[i] <= 'z'))
str[i] = 'A' + (str[i] - 'a');
}
return str;
}
int main(int argc, char **argv)
{
char str[] = "abCd!@#$456z";
using namespace std;
cout << toUp(str) << endl;
return 0;
}
A função toUp é bem simples, ela percorre a string procurando caracteres que estejam no intervalo de ‘a’ a ‘z’, e quando encontra converte o caractere para sua versão maiúscula. A formula de conversão primeiramente calcula qual o índice da letra sendo convertida (que seria o número da letra no alfabeto, mas começando de zero) e depois soma esse índice ao índice inicial das letras maiúsculas.
Vamos pegar como exemplo a conversão da letra ‘c’, primeiramente é feito str[i] – ‘a’, o que resulta em ‘c’ – ‘a’, chegando em 99 – 97, resultando 2. Na sequência é feito ‘A’ + 2, que significa: 65 + 2 = 67. Consultando a tabela temos: 67 = C.
Apenas para lembrar, já existe uma função na biblioteca padrão para conversão de letras minusculas para maiúsculas chamada toupper, que é declarada em ctype.h. Neste header também existem outras funções do mesmo genero, como: tolower, islower, isupper, etc.
Por fim, vamos ver como converter uma string que contêm um número inteiro para uma variável to tipo int:
#include <iostream>
int myAtoi(const char *str)
{
int len = (int) (strlen(str)-1);
int num = 0;
int dec = 1;
for(;len >= 0; --len)
{
if(str[len] >= '0' && str[len] <= '9')
{
num += dec * (str[len] - '0');
dec *= 10;
}
else if((len == 0) && (str[len] == '-' || str[len] == '+'))
num = (str[0] == '-') ? -num : num;
else
{
//numero invalido, entao 0
return 0;
}
}
return num;
}
int main(int argc, char **argv)
{
using namespace std;
int num = myAtoi("23");
cout << num << endl;
cout << myAtoi("-10") + myAtoi("5") << endl;
return 0;
}
A função myAtoi processa a string e retorna o int que ela representa, note que a função processa a string do final para o começo para facilitar os cálculos. No loop principal primeiramente é verificado se o caracter atual é um número (ou seja, tem que estar entre ‘0′ e ‘9′). Se for um número, a variável num é atualizada com a formula: dec * (str[len] – ‘0′). O código str[len] – ‘0′ calcula qual o valor do número atual (da mesma forma que foi feita na conversão de letras para caixa alta). Achado o número, multiplicamos ele por dec, que armazena qual a casa decimal que ele se encontra (unidade, dezena, centena, etc), e por fim o valor é somado com o número atual. Depois disso a casa decimal é atualizada (em dec *= 10).
Caso o caracter não seja um número, é verificado se a string contêm o sinal + ou – na primeira posição, caso sim, o sinal do número é atualizado de maneira adequada. Caso o caractere em questão não seja número ou sinal, a função retorna 0. O correto seria retornar algum erro, mas para não complicar o exemplo ficamos com o zero.
Na biblioteca padrão existem as funções atoi e strtol que fazem conversões de strings para números.
A conversão de int para string fica como lição de casa, uma boa leitura para se aprender mais é o artigo sobre tipos básicos do Caloni: Básico do básico: tipos.
Bom já que o Vinícius convidou
, vamos la…
Vamos as regras:
Minhas coisas aleatórias são:
1. Sou também fanático por coca-cola, mas apenas a bebida!
2. Sou fanático tambem por trens, ferrovias e coisas relacionadas, sendo ferreomodelista e membro da ABPF
3. Não suporto calor e sinto falta do frio de Curitiba
4. Gostaria de morar em uma cidade montanhosa em uma casa com uma bela vista para as montanhas (e para alguma linha de trem).
5. Gostaria de aprender pilotar aviões, mas falta verba…
6. Odeio futebol
A minha lista de convidados é ridiculamente pequena, convido apenas o PV e o David Ferreira.
Um item que vejo muitos novatos na linguagem tendo dificuldades são as strings em C, por isso resolvi escrever alguns posts e tentar resolver muitas das duvidas que vejo por ai.
Para começo de conversa strings em C praticamente não existem, o compilador tem apenas uma vaga noção do que é uma string, pois elas são uma convenção onde um vetor de caracteres terminado com 0 (zero) representa uma string. Sendo assim, podemos criar uma string usando:
#include <stdio.h>
int main(int, char **)
{
char ola[4];
ola[0] = 'o';
ola[1] = 'l';
ola[2] = 'a';
ola[3] = 0;
printf(ola);
return 0;
}
Este código simplesmente imprime “ola” na tela, mas note que ao inicializar ola colocamos o caracter ‘\ 0′ (que nada mais é que o numero 0) no final do array, ele é necessário pois é a única forma do printf saber onde termina a string. Agora escrever esse código toda vez que precisarmos criar uma string é bem chato, por isso, uma das poucas coisas que o compilador C sabe sobre strings é:
#include <stdio.h>
int main(int, char **)
{
char ola[] = "ola";
printf(ola);
return 0;
}
Este código é idêntico ao anterior, mas escrito de uma maneira bem mais simples. Note que o compilador reconhece a string “ola” e declara um array de 4 chars e já inicializa ela com a string “ola” (incluindo o ). Também podemos escrever:
#include <stdio.h>
int main(int, char **)
{
const char *ola = "ola";
printf(ola);
return 0;
}
Este código já é um pouco diferente do anterior, aqui não criamos um vetor de caracteres, e sim um ponteiro para uma região de memória constante do tipo char, trocando por miúdos, criamos um ponteiro que aponta para string. Mas onde diabos foi parar a string? O compilador alocou um trecho de memória constante na seção de dados do código (uma variável global). Por isso usamos const, pois esta string não deve ser modificada pelo código.
Agora que já sabemos como uma string funciona em C, vamos fazer uma função para contar quantos caracteres uma string tem, assim podemos ver como o 0 no final dela é usado:
#include <stdio.h>
int contaChar(const char *str)
{
int i = 0;
for(;str[i] != 0; ++i);
return i;
}
int main(int, char **)
{
char ola[] = "ola";
printf("A string %s possui %d caracteres\n", ola, contaChar(ola));
return 0;
}
Note que sempre que precisamos saber quantos caracteres uma string possui, precisamos percorrer toda a string, isso pode trazer problemas de performance em algumas aplicações, e isto ocorre com quase todas as operações com string.
Outro detalhe, não é preciso criar a função contaChar, quando precisar saber o tamanho de uma string basta usar a strlen, que é declarada no string.h:
#include <stdio.h>
#include <string.h>
int main(int, char **)
{
char ola[] = "ola";
printf("A string %s possui %d caracteres\n", ola, strlen(ola));
return 0;
}
Neste mesmo arquivo existem varias outras funções para se trabalhar com strings, é recomendável dar uma olhada na documentação antes de escrever a sua própria função para verificar se ela já não existe (alias, isso é recomendável para qualquer coisa, não apenas strings).
Agora chegamos ao ponto onde a maioria tem dificuldades, como saber se uma string é igual a outra? A idéia inicial é escrever:
#include <stdio.h>
int main(int, char **)
{
char ola[] = "ola";
char ola2[] = "ola";
if(ola == ola2)
printf("Iguais");
else
printf("Nao sao iguais");
return 0;
}
Se você entendeu tudo até aqui já deve imaginar qual vai ser a saída do programa acima, se não, tente ler novamente e execute o programa. Muitos ficam surpresos ao ver o programa imprimir “Não são iguais”. Isto ocorre porque o if esta na verdade comparando dois ponteiros (lembre-se, arrays sem índice são ponteiros).
Então como fazer para saber se duas strings são iguais? É necessário comparar todos os caracteres das strings:
#include <stdio.h>
bool saoIguais(const char *s1, const char *s2)
{
for(int i = 0;s1[i] == s2[i]; ++i)
{
if(s1[i] == 0)
return true;
}
return false;
}
int main(int, char **)
{
char ola[] = "ola";
char ola2[] = "ola";
if(saoIguais(ola, ola2))
printf("Iguais");
else
printf("Nao sao iguais");
return 0;
}
Agora já sabemos como identificar se duas strings são iguais ou não, um pouco trabalhoso, mas é o único jeito. Para simplificar um pouco a vida, a biblioteca padrão já vem com uma função de comparação de strings chamada strcmp, que funciona de maneira similar a função saoIguais, a diferença é que essa função não verifica apenas se as duas strings são iguais, ela compara as duas, retornando 0 quando são iguais, -1 quando a primeira string vem antes da segunda, ou 1 caso contrário:
#include <stdio.h>
#include <string.h>
int main(int, char **)
{
char ola[] = "ola";
char ola2[] = "ola";
if(strcmp(ola, ola2) == 0)
printf("Iguais\n");
else if(strcmp(ola, ola2) != 0)
printf("Nao sao iguais");
return 0;
}
Pronto, agora já temos uma maneira simples de verificar se duas strings são iguais ou não.
No próximo post, vamos dar uma olhada em mais algumas operações com strings em C.