Topo

Mostrar mensagens com a etiqueta C. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta C. Mostrar todas as mensagens

domingo, 16 de junho de 2013

Linguagem C: comentários e identação

Um tópico muito importante em C (e em qualquer linguagem de programação) são os comentários. Quando os programas começam a ficar muito grandes, torna-se difícil seguir o raciocínio que o programador utilizou (mesmo que esse programador tenhas sido tu!). Os comentários são blocos de texto normal que inserimos entre as instruções do nosso programa para nos ajudar a seguir a lógica do mesmo. Substitui o código do nosso programa pelo seguinte:
 
/* Em baixo temos uma diretiva de pré-processador */
#include <stdio.h>

/* Vamos começar o nosso programa. */
int main() {
    /* Escrever no ecrã uma frase */
    printf("O meu primeiro programa em C!\n"); /* O \n indica uma nova linha*/
    /* Vamos retornar zero, indicando que correu tudo bem. */
    return 0;
}

Como podes constatar, os comentários em C são colocados dentro de blocos que começam com /* e terminam com */, como por exemplo /* isto é um comentário */. Se compilares e executares o programa vais verificar que os comentários são totalmente ignorados. É uma excelente prática comentar os nossos programas, e algo que aconselho fazerem sempre, seja em projetos para a universidade ou a nível profissional.

Outra boa prática é a chamada identation (não existe uma palavra exata em Português, mas para facilitar vamos chamar-lhe identação). A identação não é mais do que chegar à frente os conteúdos de um bloco. Por exemplo, tudo o que está dentro do bloco da função main está identado com quatro espaços. Desta forma o programa torna-se mais claro e mais fácil de entender. A identação é essencial para que um programa seja minimamente legível. Aqui vamos usar identação de 4 espaços (o chamado estilo Kernighan & Ritchie), no entanto cada pessoa tem a sua preferência, alguns usam 2 espaços, outros usam um tab, e por ai fora. O que interessa é que o nosso programa seja consistente e mantenha a mesma identação do princípio ao fim. Se por acaso tiverem longas partes do vosso código que não estejam identadas, estejam mal identadas ou estejam identadas de forma inconsistente, existem várias formas automáticas de resolver o problema. Deixo duas soluções, uma usando a interface gráfica, outra usando a linha de comandos:
  1. A maioria dos IDEs (ver aqui o que é um IDE) suporta esta operação. Por exemplo, no Code::Blocks, basta ires ao menu "Plugins => Source Code Formatter (AStyle)", e o teu código fica automaticamente identado. Para alterares o estilo de identação efetuada através deste processo, edita as preferências do plugin em "Setting => Editor", e selecionares em baixo "Source Formatter". Como podes verificar, existem vários estilos de identação, e podes inclusive criar um personalizado.
  2. Usando o comando indent. Este comando também suporta uma série de estilos diferentes, bem como personalizações específicas de cada estilo. Após instalares o indent (ver parágrafo seguinte), podes fazer identação automática do nosso primeiro programa usando o seguinte comando:

    $ indent -kr -nut primeiroprog.c

    As opções -kr e -nut indicam que queres usar o estilo Kernighan & Ritchie e que não queres usar tabs, respetivamente. Para veres todas as opções deste comando basta fazeres:

    $ man indent
Nem o Code::Blocks nem o comando indent estão instalados por defeito na maioria das distribuições Linux. Em distribuições baseadas em Debian (Ubuntu, Mint, WattOS, Bodhi, etc.), um simples comando serve para instalar os dois programas de uma só vez:

$ sudo apt-get install codeblocks indent

Seja qual for o estilo que usares, convém seres consistente e usares esse estilo em todo o teu programa. Em situações em que várias pessoas estão a trabalhar no mesmo código, convém definir à partida o estilo usado, de forma a que o resultado final tenha um aspeto coerente.

segunda-feira, 10 de junho de 2013

Linguagem C: o nosso primeiro programa


Neste post vamos voltar a falar do nosso primeiro programa em C, e vamos assumir que o leitor já tem um sistema preparado para compilar e executar programas em C (ver posts anteriores).

Vamos criar uma pasta para colocarmos o nosso código, e vamos abrir o gedit para editar o nosso programa. Para isso abre um terminal, e insere os seguintes comandos (explicações detalhadas de todos estes comandos estão disponíveis nos posts anteriores):

$ mkdir aprender_c
$ cd aprender_c
$ gedit primeiroprog.c &

Agora, faz copy-paste do código em baixo para dentro do gedit, e guarda o ficheiro.
 
#include <stdio.h>

int main() {
    printf("O meu primeiro programa em C!\n");
    return 0;
}

Vamos então por partes. A linha 1 do código contém o seguinte texto:
 
#include <stdio.h>

Este texto não corresponde a código C, mas sim a uma directiva de pré-processador. Não te assustes com o nome. Esta directiva de pré-processador serve apenas para indicar ao compilador que pretendemos usar funções (ou comandos) que estão na biblioteca de funções stdio.h (Standard Input/Output). Esta biblioteca contém funções de entrada/saída de dados, tais como o printf (usado na linha 4, do qual falaremos adiante). Se quisermos usar outros tipos de funções, tais como funções matemáticas ou funções para tratamentos de sequências de caracteres (strings), vamos ter de incluir (#include) mais bibliotecas (math.h no caso das funções matemáticas, e string.h no caso das funções para tratamento de sequências de caracteres). As directivas de pré-processador começam sempre com um cardinal (#), e, ao contrário de todas as expressões e chamadas de função em C, não devem terminar com um ponto e vírgula (;), como acontece nas linhas 4 e 5.

Nas linhas 3 e 6 temos o início e o fim da função principal, main, que é chamada em primeiro lugar assim que o nosso programa é executado.
 
int main() {
}

A palavra-chave int antes do nome da função (neste caso main), indica o tipo de dados que a função vai devolver a quem a chamou. Por definição, a função main devolve sempre um número inteiro. Adiante falaremos melhor sobre os diferentes tipos de dados existentes em C. Tudo o que está entre as chavetas {...} é o nosso programa propriamente dito, que é composto por instruções. As instruções em C devem ser sempre terminadas por ponto e vírgula.

Na linha 4 temos a função printf.
 
printf("O meu primeiro programa em C!\n");

Esta função, na sua forma mais simples, aceita uma sequência de caracteres, e escreve/imprime essa sequência no ecrã. Em C, as sequências de caracteres são definidas entre aspas (ex. "sou uma sequencia de carateres"). Repara nos dois últimos caracteres da sequência que estão dentro do printf. Temos uma barra "\" seguida de um "n". Esta sequência, "\n", indica uma nova linha (new line), e serve para indicar o fim da linha atual e o início de uma nova linha. Vamos ver um exemplo do seu efeito mais à frente. Por último, na linha 5 temos a seguinte instrução:
 
return 0;

Esta instrução indica o fim da função main, e por consequência o fim do nosso programa, devolvendo o valor zero (que é um número inteiro). Neste caso o valor é devolvido ao sistema operativo, e é comum este valor indicar que o programa terminou sem erros.

Agora que temos um entendimento mais completo sobre o nosso programa, vamos compila-lo e executa-lo. Salva o documento no gedit, e na linha de comandos escreve o seguinte:

$ gcc primeiroprog.c -ansi -pedantic -Wall -g -o primeiroprog

Se tudo correr bem, o programa vai compilar sem erros. Antes de executarmos o nosso programa, uma pequena explicação sobre as opções que usámos para o compilador gcc:
  • gcc : Nome do comando de compilação
  • primeiroprog.c : Nome do ficheiro a compilar
  • -ansi e -pedantic : Indicam que o  nosso ficheiro contém código C o mais standard possível, sem extensões mais recentes.
  • -Wall : Pede ao compilador para nos avisar (Warning) de todos (all) os pequenos problemas que possam existir no programa, mesmo que esses problemas não impeçam a compilação.
  • -g : Pede ao compilador para incluir informação de depuração (debug), que nos pode ajudar a resolver problemas usando um depurador (debugger) tal como o gdb, o qual vamos usar mais à frente.
  • -o primeiroprog : Indica ao compilador que o ficheiro executável resultante (output) da compilação deve-se chamar primeiroprog.
Vamos executar o programa da seguinte forma:

$ ./primeiroprog

O resultado será:

O meu primeiro programa em C!

Se removermos o "\n" da cadeia de caracteres dentro do printf e voltarmos a compilar, vamos verificar que no fim da execução do programa o cursor fica situado logo à frente da frase e não por baixo da mesma. Existem outros caracteres especiais em C, como podes ver aqui. Experimenta inserir alguns destes caracteres especiais na cadeira de caracteres, volta a compilar e executar o programa e observa o resultado!

No final do nosso programa retornamos o valor zero, que indica que o programa terminou sem problemas. Após a execução de qualquer comando em Linux podes verificar o resultado retornado usando outro comando:

$ echo $?

Ao executares este comando após teres executado o nosso primeiro programa, vais ver o resultado retornado: zero. Na linha 5 do nosso programa, substitui o 0 por outro valor inteiro, volta a compilar e executar, e logo de seguida corre o comando anterior e verifica o resultado obtido.

Por último o programador deve ter em atenção que o C é case-sensitive, ou por outras palavras, é sensível às maiúsculas e minúsculas. Se por exemplo em vez de escrevermos main, printf ou return, escrevermos Main, PRINTF ou ReTuRn, o programa não vai sequer compilar.

sábado, 6 de outubro de 2012

Preparar o PC para aprender C: parte II

Vamos então finalizar a configuração do sistema Linux para que possamos escrever o primeiro programa em C. Vou assumir que o leitor deu uma olhada no post anterior e está a usar uma versão do Linux baseada em Debian, como por exemplo o Ubuntu, Mint, Bodhi ou Pear1.

Antes de começarmos a programar, temos de verificar se o software necessário para esse efeito está instalado, e isso leva-nos temporariamente a outro tópico: a gestão e instalação de programas em Linux. A boa notícia é que, regra geral, é muito mais fácil instalar e desinstalar aplicações em Linux do que, por exemplo, em Windows. Por outro lado, a enorme quantidade de maneiras de realizar essa tarefa pode confundir o utilizador inexperiente. Vamos então tentar simplificar: cada distribuição de Linux tem o seu gestor gráfico de aplicações e pacotes (o seu "AppCenter" em linguagem corrente), cujo objetivo é apresentar, instalar e remover o software disponível (99% do qual gratuito e aberto) de forma apelativa; por exemplo, o Ubuntu tem o Ubuntu Software Center, enquanto o Mint tem o Mint Software Center. Existe no entanto um programa comum a todas as distribuições, embora menos "bonito", e que faz a mesma coisa: chama-se Synaptic Package Manager e vem instalado de raiz em algumas distribuições (e caso não venha, é fácil instalar). Todos estes diferentes "AppCenters" não são mais do que interfaces gráficas para o sistema base de gestão de aplicações e pacotes, chamado Apt. O Apt faz parte do núcleo duro do Debian e seus derivados, e vem sempre instalado de raiz. Ao contrário dos restantes "AppCenters", o Apt é usado através da temível linha de comando. Vou usar o Apt na demonstração da instalação de quaisquer aplicações (que neste post são as aplicações necessárias para programarmos em C). No entanto é bom ter a noção de que instalar ou remover um programa usando o Apt tem exatamente o mesmo efeito que fazê-lo com o Ubuntu Software Center, Synaptic, etc. (por exemplo, se instalarmos um programa com o Apt, esse mesmo programa vai aparecer como "Instalado" no Ubuntu Software Center).

A primeira coisa que temos de verificar é se o sistema básico de desenvolvimento de programas está instalado. Algumas distribuições trazem este sistema instalado de raiz, mas outras mais minimalistas (como o Bodhi) nem por isso. Vamos então usar o Apt para instalar (ou confirmar se está instalado) o sistema de desenvolvimento de programas. Para tal, basta abrir a linha de comandos2, e escrever (não meter o $!):

$ sudo apt-get install build-essential

Este comando pode ser críptico para quem não está habituado ao Apt, mas é na realidade bastante simples: estamos a pedir ao Apt para instalar o build-essential, que é o nome do pacote que contém o sistema básico de desenvolvimento de programas. O comando sudo indica que o Apt deve ser executado em modo super-utilizador/administrador, o que normalmente implica a solicitação da palavra-passe ao utilizador. No próximo post vou falar sobre sobre a linha de comandos (incluindo o Apt), pois trata-se de um tópico muito importante para quem deseja perceber como um computador funciona na realidade. Caso o build-essential já esteja instalado, o Apt vai indicar uma mensagem do género:

build-essential is already the newest version.

Caso contrário, o Apt vai pedir confirmação para instalar o pacote e as respectivas dependências3. Estamos prontos para escrever o nosso primeiro programa em C. Para criar o programa é necessário um editor de texto, de preferência com realce de sintaxe, para facilitar a escrita desse mesmo programa. Todas as distribuições de Linux costumam trazer três editores de texto, dois baseados na linha de comando (nano e vi4) e um com interface gráfica. O Ubuntu e o Mint trazem o gedit por defeito, embora distribuições mais leves normalmente optem pelo LeafPad ou MousePad, que são bastante limitados. Caso não encontrem o gedit nos menus da vossa distribuição Linux, é fácil instalar usando o Apt no terminal (ou a tua "AppCenter" preferida):

$ sudo apt-get install gedit

Neste blog vou usar o gedit a maior parte das vezes, pois é rápido, simples e realça a sintaxe de todas as linguagens de programação que vão ser discutidas neste blog. Além disso, o gedit não esconde os detalhes do desenvolvimento do software, e permite ao programador iniciante entender completamente o que se está a passar, ao contrário de alguns IDEs5. As distribuições baseadas no ambiente gráfico KDE6 (tais como o Kubuntu) normalmente trazem o editor Kate, que é do mesmo nível de qualidade do gedit, ou até superior;  caso optem por usar o ambiente KDE, podem perfeitamente usar o Kate em vez do gedit.

Vamos então escrever o nosso primeiro programa em C. Abre um terminal e cria uma pasta onde vamos colocar o nosso primeiro código C:

$ mkdir aprender_c

O comando anterior significa "make directory", ou seja, cria uma pasta ou diretoria. Em seguida vamos para "dentro" dessa diretoria:

$ cd aprender_c

O comando anterior significa "change directory" e vai-nos colocar "dentro" da pasta que acabamos de criar. Em seguida vamos criar o nosso programa em C usando o gedit (ou o teu editor preferido):

$ gedit primeiroprog.c &

O comando anterior invoca o editor gedit, que vai assumir um novo ficheiro chamado primeiroprog.c, localizado na pasta que acabamos de criar. O caractere & no final do comando indica que queremos voltar a ter o controlo do terminal após invocar o gedit (se experimentares o mesmo comando sem o & no fim, vais verificar que o terminal fica bloqueado até fechares o gedit). Obviamente, também é possível invocar o gedit diretamente através do menu, e guardar posteriormente o novo ficheiro na pasta criada. Agora, faz copy-paste do código em baixo para dentro do gedit, e guarda o ficheiro.
 
#include <stdio.h>

int main() {
    printf("O meu primeiro programa em C!\n");
    return 0;
}

Agora vamos compilar o programa, ou por outras palavras, vamos transformar o nosso código C num ficheiro executável. Para tal, executa o seguinte comando no terminal:

$ gcc primeiroprog.c -ansi -Wall -pedantic -g -o primeiroprog

Em princípio não deverás ter erros neste processo. Vamos então executar o nosso programa:

$ ./primeiroprog

O resultado deverá ser:

O meu primeiro programa em C!

Sucesso! Não te preocupes se não percebeste estes últimos passos do processo. Estamos apenas a verificar se o nosso sistema Linux está de facto preparado para desenvolvermos programas em C. Vamos voltar a este primeiro programa mais tarde e dissecar ponto por ponto o que cada um dos passos indicados significa.

Até breve!

1 Não referi estas duas últimas distribuições no meu último post, mas resumindo muito rapidamente, o Bodhi Linux é super-leve e minimalista (usa uma interface gráfica chamada Enlightenment), sendo necessário instalar praticamente tudo o que o utilizador quer usar. Por usa vez, o Pear Linux é basicamente o Ubuntu com uma interface Gnome-shell personalizada para se parecer com a interface do MacOS X.

2 A aplicação Terminal dá-nos acesso à linha de comandos. No Ubuntu ou no Mint basta carregar na tecla "Start" (com o logotipo do Windows, entre o Ctrl e o Alt, do lado esquerdo), começar a escrever "Term...", e a aplicação Terminal aparece logo. Noutras distribuições, o terminal pode ser acedido através do menu "Acessórios => Terminal". Por vezes as distribuições trazem diferentes tipos de aplicações Terminal, que podem ter nomes como LXTerm, Terminology, Konsole, ROXTerm, Sakura,  XTerm, etc. Normalmente é possível invocar a aplicação Terminal em qualquer distribuição pressionando as teclas Ctrl+Alt+T.

3 Muitos programas dependem bibliotecas ou aplicações de terceiros para funcionar, evitando assim "reinventar a roda" para realizar algumas das suas funcionalidades (o mesmo acontece no Windows através dos ficheiros .dll, que por vezes dão problemas e conflitos). Nos sistemas modernos de Linux todas as dependências das aplicações disponíveis nos repositórios são geridas automaticamente pelo Apt (ou pelo "AppCenter" que estivermos a usar), poupando muitas preocupações ao utilizador.

4 O vi, bem como a sua versão melhorada, vim, são editores de texto do mais diferente e estranho que se possa imaginar. Inicialmente são totalmente contra-intuitivos, porém, os fiéis juram a pés juntos que após dominar um ou outro, a produtividade na programação mais que duplica. Não sei se isto é verdade, pois eu não uso nem um nem outro, mas fica a dica.

5 IDEs - Ambientes de desenvolvimento integrado tais como o Eclipse, NetBeans, Code::Blocks ou Kdevelop (ou o Visual Studio no Windows), podem facilitar e acelerar imenso o desenvolvimento de software; porém, para o programador iniciante, os IDEs podem complicar mais do que simplificar, pois ofuscam detalhes importantes do que está na realidade a acontecer, tornando difícil a resolução de certos problemas. Na minha opinião, o programador só deverá começar a usar um IDE quando dominar minimamente a linguagem de programação em questão (especialmente C); até lá, a melhor opção é usar um editor simples tipo gedit para editar o código juntamente com a linha de comando para compilar e executar os programas desenvolvidos. Existe um programa chamado Geany, que oferece algumas facilidades de um IDE sem esconder a complexidade do desenvolvimento de programas (tem inclusive uma linha de comando incorporada...). Todos estes IDEs podem ser instalados na tua distribuição de Linux através da tua "AppCenter" preferida (Apt, Synaptic, etc...).

6 O KDE consiste num ambiente gráfico, bibliotecas gráficas e conjunto de aplicações para Linux. A sua interface é das mais avançadas hoje em dia, embora nem toda a gente o aprecie. Os seu principal concorrente é o Gnome 3 (bibliotecas gráficas + conjunto de aplicações), embora este esteja fragmentado em vários ambientes gráficos tais como o Gnome-shell (ambiente gráfico por defeito no Gnome 3), Unity (ambiente gráfico do Ubuntu) e Cinnamon (ambiente gráfico do Mint).

sexta-feira, 5 de outubro de 2012

Preparar o PC para aprender C: parte I

A melhor forma de aprender e desenvolver programas na linguagem de programação C é através de um sistema operativo (OS) baseado em Unix, como por exemplo Linux ou MacOS X (sim, o MacOS X é baseado em Unix...). Porquê? Bem, porque basicamente o Unix e o C foram desenvolvidos mais ou menos em simultâneo por dois génios da computação (Ken Thompson e Dennis Ritchie1), e têm uma relação tão próxima que por vezes se confundem. Deixo aqui um excelente artigo sobre a história do Unix, a meu ver indispensável para qualquer aluno de Engenharia Informática ou Electrotécnica. Neste blog vou focar-me sempre no Linux, pois além de ser gratuito e aberto e de correr em qualquer PC (ou Mac!), por muito antigo que seja, não tenho (nem quero ter) acesso ao MacOS X. Aliás, por uns meros 25€ podemos comprar um pequeno computador que corre linux...

Dito isto, é possível - embora não aconselhável - aprender2 C em Windows. As (muitas e boas) razões para tal não ser aconselhável deixo para mais tarde. No entanto para os mais teimosos existem duas possibilidades: MinGW e Cygwin.

Não é necessário largar o Windows para aprender C num ambiente 100% Linux. Para tal basta fazer download de um gestor de máquinas virtuais (sugiro o VirtualBox) e instalar uma distribuição de Linux dentro do Windows (ou do MacOS X). Neste caso, podem inicializar e desligar o Linux apenas quando quiserem programar, podendo usar o Windows (ou o MacOS X) normalmente. O Linux vai "pensar" que está a correr num hardware físico, quando na realidade está a correr num ambiente virtual. Em todo o caso, se tiverem coragem, sugiro que deitem fora o Windows e comecem a usar Linux: muito mais seguro, muito mais rápido, mais aplicações e mais fáceis de instalar... mas isto é apenas a minha opinião e já estou a fugir do assunto em questão: aprender C.

Se começarem a procurar por uma distribuição Linux para instalar, vão verificar que existem muitas, e com tanta escolha pode tornar-se difícil escolher qual usar. Deixo aqui uma curta lista de distribuições, com indicação das principais vantagens e desvantagens de cada uma:

  • Ubuntu - Excelente distribuição, qualidade em toda a linha. No entanto tem uma interface muito moderna (chamada Unity) que requer um PC relativamente recente (não mais antigo que 2007) e que pode ser estranha ao princípio, embora após uma ou duas horas de habituação seja talvez a interface gráfica mais avançada e produtiva nos dias que correm.
  • Lubuntu ou Xubuntu - São versões do Ubuntu com interface gráficas mais tradicionais e muito mais leves em termos de requisitos. Basicamente têm todo o poder e qualidade do Ubuntu, mas correm com grande desempenho até em PCs do século passado. São boas opções para instalar dentro do VirtualBox, pois puxam muito pouco pelo sistema.
  • Mint (versão Cinnamon) - É uma distribuição baseada em Ubuntu mas com uma interface mais tradicional (chamada Cinnamon), embora inovadora e moderna. Talvez seja a interface mais familiar para quem vem do Windows 7 ou Vista. Tal como o Ubuntu, requer um PC relativamente moderno, com aceleração 3D. Existem outras versões do Mint, mais leves, como por exemplo o Mint Xfce, que usa a mesma interface que o Xubuntu. A única desvantagem do Mint em relação ao Ubuntu, é que parece um bocadinho menos profissional e estável no uso diário; mas não é por isso que não deixa de ser um OS excelente.
Talvez mais tarde publique qualquer coisa sobre a história das distribuições. Para já refiro apenas que todas as distribuições que mencionei derivam do Debian, uma das primeiras distribuições de Linux, muito estável e segura, mas com desenvolvimento um bocado lento e com repositórios de aplicações um pouco desactualizados. Uma lista completa (?) das distribuições existentes está disponível aqui (ver coluna do lado direito, um pouco mais em baixo).

Comecei este post por referir que um OS baseado em Unix (como o Linux) é a melhor forma para aprender a programar em C. Podem tirar as duas últimas palavras da frase anterior. Um OS baseado em Unix (e.g. Linux) é a melhor forma de aprender a programar, ponto. No caso do Linux, as ferramentas para programar em 99% das linguagens de programação existentes já estão instaladas de raiz ou podem ser instaladas com poucos clicks. Em posts futuros darei exemplos em Python, Java, PHP e Matlab (sem usar o Matlab!).

No próximo post vou escrever sobre o software que se pode usar em Linux para desenvolver programas em C, bem como sobre a linha de comando e o porquê de ser importante dominar esta ferramenta que tanto medo mete a tanta gente.

Até breve!


1 Dennis Ritchie faleceu recentemente, sem que isso tenha sido referido na imprensa, ao contrário do que aconteceu, por exemplo, com Steve Jobs. Acerca disto li um comentário muito interessante que dizia o seguinte: "If the ghosts of Jobs and Ritchie were to find themselves marooned on a desert island, it might be Jobs who managed to light the fire, but it would be Ritchie who showed up with the wood". Façam a vossa interpretação.

2 Refiro-me apenas a aprender C e não a desenvolver software em C para Windows, pois nesse caso o melhor é usar uma ferramenta integrada como o Visual Studio. No entanto, para aprendizagem de C considero que este género de abordagem é péssima, mas sobre isso falarei depois...