Arquivo de etiquetas: c

Desbravando o goto!

Introdução

O assunto dos gotos é um dos tópicos mais discutidos nos fóruns de programação. Várias críticas são reiteradas para a sua não utilização, mas será o goto assim tão maléfico? Não terá realmente a sua utilidade? Com este artigo espero convencê-lo que o goto, como uma ferramenta de programação que é, tem lugar na sua caixa de ferramentas.

Continuar a ler

Arduino: const vs #define

Longe vão os tempos em que os computadores possuíam quantidades irrisórias de memória RAM quando comparadas com os dias de hoje. Falo sim em quantidades na ordem dos kbytes de memória.

Actualmente os programadores descuram um pouco essa afinação e optimização na alocação de memória das suas aplicações, mas ainda existe um pequeno grupo onde ainda é necessário optimizar ao pormenor a alocação de memória, refiro-me então às áreas da robótica e electrónica, de um modo geral na utilização de micro-controladores.

Continuar a ler

A ferramenta gengetopt

Os parâmetros de linha de comando constituem um poderoso mecanismo de interação, especialmente nas aplicações de modo consola/terminal que funcionam em modo de texto. De facto, através dos parâmetros da linha de comando, torna-se possível especificar múltiplos comportamentos e funcionalidades para uma mesma aplicação de modo consola/terminal, estando cada comportamento associado a um dado conjunto de parâmetros passado pela linha de comando. Por exemplo, o bem conhecido comando ls, cuja função primária no UNIX é a listar nomes de ficheiros e diretórios, disponibiliza na versão GNU mais de 50 parâmetros da linha de comando, desde o -a (mostra todos os ficheiros) ao -x (mostra a listagem por linhas). Curiosamente, existe ainda a opção -X (maiúscula) que lista os ficheiros por ordem alfabética das respetivas extensões.

Este artigo mostra como se usa e quais as mais-valias da ferramenta gengetopt para o tratamento semi-automatizado das opções passadas pela linha de comando em programas escritos em linguagem C que se destinam a ambientes Linux.

Implementação de Árvores de Vantagem

Nesta edição, em que estamos em pleno Outono e muitas das nossas ruas se cobrem de mantos de folhas, propomos ao leitor uma vista mais reforçada às árvores… Mais concretamente pelas árvores binárias e pelas árvores de vantagem.

Os que me conhecem, sabem que esta foi uma temática que me deu algumas dores de cabeça, mas no fim de contas, este foi um assunto que confesso, ter valido a pena ter aprofundado.

Antes de prosseguirmos vamos recordar, ao leitor, uma característica fundamental das árvores binárias. Este esquema de representação de dados torna-se bastante útil quando queremos armazenar um grande número de dados, contudo as árvores binárias são sempre ordenadas tendo em consideração uma chave ou atributo específico. Todos os elementos à esquerda de um elemento da árvore têm uma chave inferior ao elemento em que estamos e todos os elementos à direita têm uma chave superior.

No exemplo implementado para este artigo, simulámos uma aplicação disponível numa rede de stand de automóveis, em que cada automóvel que essa rede detém, é identificado por um número de série (único), pela cor, marca, ano e ainda qual o número de jante que esse automóvel tem.

Listas Duplamente Ligadas

Conforme o prometido no artigo Listas Simplesmente Ligadas e Exemplo de Implementação em C da passada edição, aqui está o artigo das listas duplamente ligadas. Uma vez que este se engloba num mesmo tema, certos aspectos podem tornar-se um pouco repetitivos, isto porque a única diferença no nó entre os dois tipos de listas referidos é um apontador adicional nas segundas.

Para começar, vamos estudar as vantagens das listas duplamente face às simplesmente ligadas. Se bem se lembram uma lista simplesmente é possível percorre-la apenas num sentido. Nas que vamos ver de seguida é possível percorrê-las em ambos os sentidos e é essa a principal diferença entre o modo de funcionamento das segundas. Esta diferença é muito vantajosa. Imaginemos que estamos no nó número 1000 e queríamos imprimir o conteúdo do nó 999, com as listas simplesmente ligadas teríamos de voltar à cabeça da lista e percorrer os 999 nós até chegarmos ao pretendido, com as listas duplamente ligadas basta andar uma posição para trás.

O que muda na estrutura de cada nó relativamente às simplesmente ligadas, como já foi referido, é apenas a adição de um novo apontador, o qual irá apontar para o elemento da posição imediatamente anterior da lista.

Já que estamos a falar de apontadores convém alertar para uma situação muito específica desta estrutura de dados. Vamos focar-nos na primeira posição da lista. Se todas as posições têm um apontador para os elementos anterior e posterior, como será que definimos o apontador para elemento anterior ao da cabeça?

Debug de Aplicações em C

Neste artigo pretende-se dar ao iniciado na programação (e não só) uma ideia de como depurar os seus programas, seja com recurso à própria linguagem, introduzindo no programa código que permita despistar erros, seja com recurso a programas externos, neste caso o gdb.

É minha opinião que todos os iniciados na programação devem experimentar mover a sua aprendizagem para um sistema *nix (no meu caso, utilizo Linux), e assim sendo, este artigo assume que o leitor tem acesso a um sistema semelhante, embora isso não seja de todo um pré-requisito (o gdb também está disponível para Windows). Sendo a linguagem C bastante importante no currículo do programador e ubíqua no mundo da computação (especialmente no dos iniciados), este artigo foca-se na depuração de software escrito nessa linguagem e na utilização do gdb, um debugger poderoso e muito utilizado, disponível para imensas plataformas.

Todo o código apresentado neste artigo foi compilado com o gcc versão 4.6.3 e as sessões de debug foram levadas a cabo com o gdb versão 7.5.1 num sistema com Linux instalado (kernel 3.8.13, embora isto não seja muito importante). Os (pequenos) programas apresentados são compilados com as seguintes flags:

-Wall -Wextra -std=c99 -pedantic -O0 -ggdb3

Listas Simplesmente Ligadas e Exemplo de Implementação em C

O que será isto das listas? Uma lista é uma estrutura de dados sequencial que resolve o típico problema dos arrays. E qual é o problema do arrays (vectores) poderá pensar o leitor? Se pensarmos mais concretamente na linguagem C, o que precisamos para definir um array? O tipo de dados e o número de elementos que iremos ter! E no início da implementação de um programa, definir o número de elementos que o array poderá ter pode ser problemático. Ou porque não sabemos em definitivo quantos elementos vai ter o array ou porque depois poderemos querer adicionar ou remover elementos.

Mantendo sempre o nosso pensamento na linguagem C, temos uma forma de aumentar ou diminuir o número de elementos de um array usando a função realloc disponível na biblioteca stdlib.h, mas o que esta função faz na prática é realocar todos os elementos novamente, ou seja, se pensarmos no caso em que só queremos adicionar um elemento, e se o nosso array tiver vários elementos, realocar toda a memória novamente é um desperdício de recursos computacionais, recursos estes que poderíamos estar a utilizar noutra operação do nosso programa.

Para além do problema da realocação de memória ainda existe o facto de, na linguagem C, os elementos dos arrays serem alocados de forma sequencial, ou seja, se o array for grande só o conseguimos alocar havendo quantidade suficiente de memória contígua livre. Contudo, no caso das listas os elementos são alocados dinamicamente, não sendo preciso existir grandes quantidades de memória contígua.