As funções sprintf e sscanf

Maio 5th, 2010 - postado por: Gabriel

O objetivo deste post é estudar essas duas funções que operam sobre strings, ambas as funções estão na biblioteca padrão stdio.h.

Todo programador em C deve saber pra que serve e como utilizar as funções printf e scanf. Pois bem, sprintf e sscanf funcionam praticamente da mesma forma, só que em vez de operarem sobre os streams de entrada e saída padrão (stdin e stdout, respectivamente) operam sobre strings (por isso o s na frente do nome).

Definições:

int sprintf(char *string, char *formato, lista de argumentos);
int sscanf(char *string, char *formato, lista de argumentos);

Ambas as funções operam sobre o parâmetro char *string. Assim como printf escreve na tela, sprintf escreve na string. Assim como scanf lê informações do teclado, sscanf lê informações da string.

A função sscanf retorna quantos parâmetros foram lidos com sucesso da string. Uma boa prática de programação é verificar se este número é o esperado.

A função sprintf retorna o tamanho (sem contar com o ‘/0′) da nova string. Repare que fica a cargo do programador verificar se a nova string cabe no espaço alocado para ela.

Veja um exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
 
int main(void)
{
    char s[] = "31/05/1989";
 
    int dia, mes, ano;
 
    sscanf(s,"%d/%d/%d",&dia,&mes,&ano); /* Tenta ler três inteiros da string e armazenar nas variáveis */
 
    printf("%d %d %d\n",dia,mes,ano);
 
    dia = 4;
    mes = 5;
    ano = 2010;
 
    sprintf(s,"%d/%d/%d",dia,mes,ano); /* Escreve uma nova string em s */
 
    printf("%s",s);
 
    return 0;
}

Struct e typedef

Maio 4th, 2010 - postado por: Gabriel

Neste post veremos como utilizar e ver alguns exemplos de struct (Geralmente livros em português chamam de registro) e como utilizar o typedef .

Registros (struct):

Os tipos de dados fundamentais do C são dados homogêneos(int, float, char, etc), com struct o programador pode combinar esses tipos fundamentais para criar novos tipos. Sua forma de utilização é a seguinte:

struct IDENTIFICADOR{
    lista de dados fundamentais;
}Nome_da_variavel;

IDENTIFICADOR: Não da pra ser mais claro, é um nome que identifica o tipo de registro que você está criando. É isso.

Nome_da_variavel: Este campo é opcional, ele associa uma variável ao tipo de registro que você criou.

Exemplos de struct:

struct nome{
    int a;
    float b;
    char c;
};
/* Neste caso struct nome passa a ser um tipo de dados, abaixo vemos a declaração de uma variável deste tipo */
 
struct nome var;
struct {
    int a;
    float b;
    char c;
}var;
 
/* Neste caso a struct não tem identificação, no entanto a variável var já está associada a este tipo, a desvantagem deste tipo de declaração é não poder ter mais variáveis deste tipo */
struct nome{
    int a;
    int b;
    int c;
}var1
 
/* Neste caso a variável var1 é associada a struct, mas como a struct possui identificador é possível declarar mais variáveis deste tipo */
 
struct nome var2;

Acessando campos de uma struct:

Existem duas formas de acessar campos de uma struct, cada uma é usada em uma situação diferente. A primeira delas é o “.”, este operador é usado quando a variável em questão é alocada pelo compilador. Vamos supor a seguinte struct:

struct nome{
    int a;
    float b;
};

Agora vamos declarar uma variável associada a ela:

struct nome var;

Como var foi alocada pelo compilador podemos acessar seus elementos assim:

var.a = 2;
var.b = 3.2;

Aqui vai um pequeno exemplo do uso do operador “.”:

#include <stdio.h>
 
struct nome{
    int a;
    float b;
};
 
int main(void)
{
    struct nome var;
 
    var.a = 2;
    var.b = 3.5;
 
    printf("%d\n",var.a);
    printf("%f\n",var.b);
 
    return 0;
}

Quando há um ponteiro apontando para um registro se usa o operador “->”. Exemplo:

#include <stdio.h>
 
struct nome{
    int a;
    float b;
};
 
int main(void)
{
    struct nome *var; /* Ponteiro para o registro */
 
    var = (struct nome *)malloc(sizeof(struct nome)); /* Aloca espaço para a estrutura e retorna o endereço de memória para o ponteiro */
 
    var->a = 2;
    var->b = 3.5;
 
    printf("%d\n",var->a);
    printf("%f\n",var->b);
 
    return 0;
}

Obviamente as duas formas são importantes, aqui vai um trecho de código em que uma estrutura é tratada de ambas as formas:

#include <stdio.h>
 
struct nome{
    int a;
    float b;
};
 
void mudaValores(struct nome *v, int a, float b)
{
    v->a = a;
    v->b = b;
 
    printf("%d\n",v->a);
    printf("%.2f\n",v->b);
}
 
int main(void)
{
    struct nome var; /* Ponteiro para o registro */
 
    var.a = 2;
    var.b = 3.5;
 
    printf("%d\n",var.a);
    printf("%.2f\n\n",var.b);
 
    mudaValores(&var,21,43.2);
 
    return 0;
}

Uma estrutura pode conter qualquer tipo de dados, inclusive outra estrutura. Veja um exemplo:

struct nome1{
    int a;
    int b;
};
 
struct nome2{
    int c;
    struct nome1 d;
};

Para acessar os elementos da estrutura interna usam-se os mesmos operadores, exemplos:

struct nome1 var1;
struct nome1 *var2
 
var1.d.a = 2;
var2->d.a = 2; /* Supondo que var2 já esteja alocada */

Uma estrutura não pode conter um elemento do próprio tipo, no entanto ela pode conter um ponteiro para um elemento do seu próprio tipo.
Permitido:

struct nome{
    int a;
    struct nome *p;
};

Não permitido:

struct nome{
    int a;
    struct nome p;
};

Typedef:

O comando typedef serve para renomear um tipo de dado, seja ele fundamental (int, float, etc) ou criado por você (uma estrutura ou um tipo criado por outro typedef).
Sua utilização é bastante simples:

typedef tipo novo_nome;

Um exemplo bem simples é a tradução dos tipos para o portugûes:

typedef int inteiro;
typedef float real;
 
inteiro a;
real b;

Typedef é muito utilizado em conjunto com struct:

#include <stdio.h>
 
struct _Data
{
    int dia;
    int mes;
    int ano;
};
 
typedef struct _Data data;
 
int main(void)
{
    data nasc;
 
    nasc.dia = 31;
    nasc.mes = 5;
    nasc.ano = 1989;
 
    return 0;
}

Outra forma de utilizar typedef e struct em conjunto:

#include <stdio.h>
 
typedef struct
{
    int dia;
    int mes;
    int ano;
}data;
 
int main(void)
{
    data nasc;
 
    nasc.dia = 31;
    nasc.mes = 5;
    nasc.ano = 1989;
 
    return 0;
}

Code::Blocks e ponteiros

Maio 3rd, 2010 - postado por: Gabriel

Em todos os tutoriais usarei a IDE Code::Blocks. É mil vezes melhor do que o popular Dev C/C++ e é igualmente gratuito, além de ter a enorme vantagem de ser “cross-platform”, ou seja, você pode instalar ele em mais de um sistema operacional. No caso do Code::Blocks ele pode ser instalado no Windows, no Linux e no Mac OS X.

Link para download: http://www.codeblocks.org/downloads

Não vou dar detalhes sobre a instalação, talvez em um post futuro. Também está no projeto uma explicação de como usar o debugger, que no Code::Blocks funciona efetivamente.

Criando um projeto no Code::Blocks:

Clique no botão New e em seguida em Project…:

Em seguida aparece uma janela para a seleção do tipo de projeto, na maioria dos tutoriais usaremos “Console Application”, selecione esta opção e clique em Go. Também pretendo fazer tutoriais sobre a biblioteca gráfica Gtk+.

Um assistente para criação do projeto irá abrir, clique em Next. Na tela de seleção de linguagem, selecione C. No próximo passo coloque o nome do projeto e escolha o local onde os arquivos serão salvos, recomendo criar uma pasta só para o projeto.

Na próxima tela deixa as opções como na imagem:

Clique em Finish e pronto, o projeto está criado e já com um arquivo main.c.

Ponteiros

Como quase todo tutorial aqui vai ser na linguagem C, é de fundamental importância o pleno entendimento dos ponteiros, tão detestados pelos iniciantes, e tão fundamentais.

Como o próprio nome diz, um ponteiro é um tipo de dado que aponta para uma posição da memória, ou seja, a informação que ele guarda é um endereço de memória, não um dado em si.

Falando grosseiramente sobre arquitetura de computadores, cada posição de memória tem um número que a identifica, por exemplo, se você está trabalhando com uma memória de 1 gb, a primeira posição será a 1 e a última será a 1.073.741.824 (muita coisa hein?), e é exatamente essa identificação que um ponteiro guarda.

Notação:

Um ponteiro pode ser de qualquer tipo, abaixo estão algumas declarações de ponteiros:

int *p;
float *f;
char *s;

Essa é a forma de declarar um ponteiro, que não tem nada haver com a forma de se usar um ponteiro. Vamos supor que declaramos um ponteiro para inteiro (int *p).

Observação: Em C quando declaramos uma variável, seja ela de que tipo for, ela não é zerada, o que significa que a posição de memória que foi alocada para ela tem o que chamamos de lixo, uma informação que não foi o seu programa que criou, simplesmente foi largada na memória por outro programa.

O operador & e o operador *:

Quando você aplica o operador & sobre uma variável, você recebe o endereço de memória onde ela está armazenada, vejamos o seguinte trecho de código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
int main(void)
{
    int *p=NULL; /* Declaramos p inicialmente apontando para nada */
    int a=10;
 
    printf("Valor do ponteiro: %p",p); /* Aqui o valor do ponteiro será NULL */
    printf("\nEndereço de a: %p",&a);
 
    p = &a; /* O ponteiro p recebe o endereço de memória de a */
 
    printf("\nValor do ponteiro: %p",p);
    printf("\nConteudo do ponteiro: %d",*p); /* O operador * recupera a informação armazenada no endereço de memória apontado por p */
 
    return 0;
}

Como comentado no código, o operador * recupera a informação armazenada no endereço de memória apontado por p. No exemplo acima, p aponta para a, que armazena o valor 10, portando *p será 10.

Agora vamos analisar o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
 
int main(void)
{
    int *p=NULL; /* Declaramos p inicialmente apontando para nada */
    int a=100,b=200,c=300,d=400,e=500;
 
    p = &a; /* p aponta para a */
    printf("\n*p = %d",*p);
 
    *p = c; /* O conteudo de p recebe c, mas como p aponta para a, a recebe c */
    printf("\n*p = %d",*p);
    printf("\n a = %d\n",a);
 
    p = &b; /* p aponta para b */
    printf("\n*p = %d",*p);
 
    *p = d; /* O conteudo de p recebe d, mas como p aponta para b, b recebe c */
    printf("\n*p = %d",*p);
    printf("\n b = %d\n",b);
 
    p = &e; /* p aponta para e */
    printf("\n*p = %d",*p);
 
    *p = 600; /* O conteudo de p recebe o valor 600, mas como p aponta para e, e recebe c */
    printf("\n*p = %d",*p);
    printf("\n e = %d\n",e);
 
    e = 700; /* e recebe 700, como p aponta para e, *p será 700 */
    printf("\n*p = %d",*p);
    return 0;
}

Na linha 8 p recebe o endereço de a, ou seja, p aponta para a:

Na linha 11 o conteúdo de p recebe c, mas como p aponta para a, a recebe c:

Na linha 15 p recebe o endereço de b, ou seja, p aponta para b:

Na linha 18 o conteúdo de p recebe d, mas como p aponta para b, b recebe d:

Na linha 22 p recebe o endereço de e, ou seja, p aponta para e:

Na linha 25 o conteúdo de p recebe o valor 600, mas como p aponta para e, e recebe o valor 600:

Na linha 29 e recebe o valor 700, portanto *p será 700 também.

Observação: Veja como o modo de declarar ponteiros é diferente do modo de usá-los. Quando declaramos um ponteiro, se fizermos int *p = 2341, significa que o ponteiro está apontando para a posição 2341 da memória, mas se fizermos *p = 2341 em outra parte, significa que o conteúdo de p recebe 2341.

Curiosidade: Quando um vetor é declarado, por exemplo, int a[10], “a” contem o endereço do primeiro elemento do vetor, logo a == &a[0].

Em breve postarei algumas aplicações práticas de ponteiros, como listas encadeadas.

Retomada e novo rumo

Maio 2nd, 2010 - postado por: Gabriel

A última vez que atualizei este blog ainda nem tinha entrado na faculdade, de lá pra cá muita coisa mudou, inclusive a quantidade de tempo livre, que foi reduzido consideravelmente. O que posso dizer é que essa redução de tempo foi muito proveitosa, pois apesar da dificuldade eu realmente tenho aprendido bastante. E é justamente com o intuito de compartilhar esse aprendizado que volto as atualizações, o foco principal do blog agora é programação (principalmente na linguagem C), pretendo escrever tutoriais sobre os mais diversos tópicos dentro deste assunto, do mais básico ao mais avançado. Claro que de vez em quando farei post’s mais aleatórios, mas com pouca freqüência. É isso.

AC/DC – Black Ice

Outubro 9th, 2008 - postado por: Gabriel

Finalmente o novo álbum do AC/DC vazou na net, eu estava esperando ansiosamente por este CD. Pelo que pude ouvir até agora o rock dos caras continua igualzinho (alguns reclamam quanto a isso, mas eu até gosto). Meus destaques até agora são Rock’N'roll Train, Skies on Fire, War Machine, She Likes Rock’N'roll, Money Made e Rock’n'roll Dream, curiosamente todas que eu ouvi até agora, enfim, deve ser a empolgação inicial.

Espero que a turnê passe pelo Brasil.

Download (128 Kbps)* Senha: www.keepersofmetal.ipbfree.com

Download (? Kbps)

Download (224 Kbps)*

Download música por música (224 Kbps)

*Testado por mim

Documentário sobre o LHC

Outubro 8th, 2008 - postado por: Gabriel

Já que o assunto ta na moda:

O professor Brian Cox visita Genebra para dar uma olhada ao redor do CERN LHC(Large Hadron Collider),ao redor de 27 km a longa máquina é selada e à experiência para criar a simulação do big bang começa.
Quando estiver instalado e funcionando, ele será capaz de criar as condições que existiam apenas um bilionésimo de segundo depois do Big Bang. Brian junta-se a cientistas que esperam que o LHC vai mudar a nossa compreensão do Universo primordial e resolver alguns de seus mistérios.

Tamanho Total: 746 MB
Legendado (PT-BR)

Parte 1
Parte 2
Parte 3
Parte 4
Parte 5
Parte 6
Parte 7
Parte 8
Legenda PT-BR

Nova categoria: Ciência

Outubro 8th, 2008 - postado por: Gabriel

Eu gosto muito de ciência, principalmente assuntos relacionados a física moderna, então resolvi criar uma nova categoria para colocar algumas coisas interessantes que eu acho no meio das minhas pesquisas.

Download Fifa 09 completo

Outubro 8th, 2008 - postado por: Gabriel

Lembrando que essa versão requer uma maquina muito boa, se o seu PC não rodou Fifa 08, pode esquecer o Fifa 09.

Para ver os links, imagens e mais informações clique em “Leia o artigo inteiro”.

Leia o artigo inteiro »

Um espetáculo improvável

Outubro 7th, 2008 - postado por: Gabriel

Um espetáculo de comédia muito bom, certamente muitos de vocês já sabem da existência dele, mas vale à pena postar.

A base de tudo é o improviso, são vários jogos como o “cenas improváveis” e o “frases improváveis”, pelo menos pra mim é hilariante. Geralmente eles pegam sugestões da platéia e tem que se virar pra fazer a galera rir. O apresentador do espetáculo geralmente é o Rafinha Bastos do CQC.

Aqui um vídeo do jogo “abecedário”:

Espetáculo com Marco Luque (29 de maio de 2008)

Espetáculo com Marcela Leal (26 de junho de 2008)

Espetáculo com Marcio Ballas (31 de julho de 2008)

Winrar 3.8 em português

Outubro 7th, 2008 - postado por: Gabriel

Programa muito importante, inclusive usado para descompactar vários arquivos disponíveis aqui no blog. Vale lembrar que essa versão já vem crackeada, não é necessário baixar nenhum crack ou keygen na internet.

Winrar 3.8 crackeado (Megaupload)

Link Alternativo (Rapidshare)

Agora uma pequena descrição copiada do www.superdownloads.com.br:

WinRAR é o mais popular compressor RAR para Windows com gerenciador de arquivos integrado. Ele oferece uma compactação entre 8% e 15% maior que seu concorrente direto, o Winzip. Oferece suporte para RAR e ZIP, além de ACE, ARJ, BZ2, GZ, ISO, JAR, LZH, TAR e 7Z.

Conta com a opção de recuperação de dados, testado para suportar o processamento de mais de 10 milhões de arquivos, de até 8,589,934,591 GB!

Possui encriptação, comentários ANSI com cores, SFX para Windows, DOS e OS/2 e ferramenta de conversão de arquivos RCVT.

Suporta skins.