Enviar um café pro programador

Pode me ajudar a transformar cafeína em código?

typedef: Como 'declarar' seus próprios tipos

Nos artigos passados, além de aprendermos como declarar uma struct na linguagem C, aprendemos a acessar e alterar os dados de uma estrutura.

Através de exemplos, vimos que podemos declarar várias variáveis de uma struct previamente declarada:
struct Aluno joaozinho;
struct Funcionario secretaria;

É como se tivéssemos criados tipos novos.
Assim como o 'int', 'float' ou 'char', é como se existisse o tipo 'struct Aluno' e 'struct Funcionario'.

Vamos entrar mais a fundo nesses detalhes e aprender como declarar structs através do atalho typedef.

O que é typedef

A palavra reservada typedef nada mais é do que um atalho em C para que possamos nos referir a um determinado tipo existente com nomes sinônimos.

Por exemplo, com o typedef, em vez de termos que nos referir como 'struct Aluno', poderíamos usar somente 'Aluno' para criar structs daquele tipo.
Em vez de escrever sempre 'struct Funcionario', poderíamos escrever apenas 'Funcionario' e então declarar várias structs do tipo 'Funcionario'.

Embora possamos criar atalhos com typedef para outros tipos, o typedef é comumente usado com structs.


Como declarar tipos com typedef

A sintaxe do typedef é bem simples:
typedef tipo_existente nome_que_voce_escolheu;

Onde 'tipo_existente' é um tipo já existente, como 'int' ou 'char'.
Agora, podemos passar a nos referir ao tipo 'tipo_existente' com outro nome, como 'nome_que_voce_escolheu'.

Exemplos de uso do typedef:
typedef int meuInteiro;
typedef char* String;
typedef unsigned short int idade;

Por exemplo, um aplicativo que cria atalhos para inteiro e ponteiro de char (vetor de caracteres):
#include <stdio.h>
 
int main(void)
{
    typedef int meuInteiro;
    typedef char String[20];
 
    meuInteiro numero = 1;
    String nome;
    scanf("%[^\n]s", nome);
 
    printf("A variavel do tipo 'meuInteiro' eh um int e vale %d\n", numero);
    printf("Ja a variavel 'nome' eh uma String e armazena \"%s\"\n", nome);
 
    return 0;
}

Como usar typedef para structs

Como já havíamos dito no começo desse tutorial, o uso do atalho typedef é bem comum com structs, e a sintaxe é análoga ao que já foi apresentado, com alguns detalhes especiais que vamos explicar.

Quando formos usar o typedef com estruturas, não podemos declarar variáveis após o ponto-e-vírgula.
Colocamos apenas a palavra sinônima que vamos usar:
typedef struct Alunos
{
//código da
//struct
} Aluno;

Pronto, agora podemos fazer algo do tipo:
Aluno joao, maria;

Esse código faz com que possamos chamar "struct Alunos" apenas por 'Aluno'.
Note que 'Aluno' não é uma variável do tipo struct, é apenas um atalho, uma maneira mais simples de dizer 'struct Alunos'.

Outro exemplo de sintaxe de typedef com estruturas é a seguinte, onde não precisamos criar o nome da struct, apenas do sinônimo:
typedef struct
{
//código da
//struct
} Alunos;

Agora a podemos definir structs desse tipo apenas usando a palavra 'Alunos'.
Como exemplo do uso do typedef para deixar mais fácil a declaração de structs e outros tipos, vamos refazer o exemplo anterior com os conhecimentos aprendidos nesse tutorial de C.

Exemplo: Como declarar, preencher e acessar elementos de uma struct em C
Defina uma struct para tratar de alunos. Dentro dessa struct, crie uma variável para armazenar o nome do aluno, e outras para armazenar as notas de Matemática, Física e a média dessas duas notas.
Após definir a struct, crie três variáveis do tipo struct que você criou.
Preencha os nomes e notas dos alunos, calculando automaticamente a média deles.
Depois exiba tudo isso.
#include <stdio.h>
#define DIM 5
// Curso C Progressivo: www.cprogressivo.net
// Curso online e gratuito de C.
// Artigos, tutoriais e aulas sobre a linguagem C
 
int main(void)
{
    typedef struct
    {
        char nome[30];
        float matematica, fisica, media;
    }Alunos;
 
    Alunos alunos[DIM];
    int count;
 
    for(count = 0 ; count < DIM ; count++)
    {
        fflush(stdin);
        __fpurge(stdin);
        printf("\nNome do aluno %d: ", count+1);
        gets(alunos[count].nome);
 
        printf("Nota de matematica: ");
        scanf("%f", &alunos[count].matematica);
 
        printf("Nota de fisica: ");
        scanf("%f", &alunos[count].fisica);
 
        alunos[count].media = (alunos[count].matematica + alunos[count].fisica)/2;
    }
 
    printf("\nExibindo nomes e medias:\n");
 
    for(count = 0 ; count < DIM ; count++)
    {
        printf("nAluno %d\n", count+1);
        printf("Nome: %s\n",alunos[count].nome);
        printf("Media: %.2f\n", alunos[count].media);
    }
 
    return 0;
}

6 comentários:

iKillerx disse...

Eu executo o primeiro código normal, mas quando digito algo e dou enter o programa para de funcionar.


Se troco:

gets(nome);

por:

scanf("%c", &nome);

funciona em partes, mas quando vai exibir o valor da variável 'nome' na tela o programa fecha, ai tenho que trocar o '%s' por '%c' no printf...


Porque isso acontece??? se estou usando uma string não deveria que apontar com o '&' no scanf e poder usar o '%s' no lugar de '%c', mas se coloco o programa fecha.

Apostila de C disse...

Olá iKillerx,

Demos uma alterada no código, pra evitar que ocorra qualquer tipo de erro.

Lembrando que usamos %c para pegar somente um caractere.

Para pegar strings, usamos %s (na scanf), e não usamos &.

Pra saber, em detalhes, o motivo disso, você pode dar uma lida em nossa seção de Strings.

E isso de gets(), scanf() é um pouco complicadinho mesmo, há todo um rigor por trás, mas você pode entender bem isso nesse artigo de nossa apostila:
Como ler e escrever Strings em C

Qualquer dúvida, não deixe de perguntar.

iKillerx disse...

Obrigado, agora funcionou!!!(estou em outro dispositivo mas em breve testo no outro)...

Mas o que isso: "[^\n]" faz?? Penso que e para aceitar caracteres ate achar um '\n'. Mas de padrão essa função já não faz isso??


E uma correção. Aqui:

printf("Ja a variavel 'nome' eh uma String e armazena "%s"\n", nome);

Tem de tiras as aspas ao redor do %s ... Ficando assim:

printf("Ja a variavel 'nome' eh uma String e armazena %s \n", nome);


Mas fora essas duvidas eu estou gostando muito dessa apostila/site. Melhor que eu ja vi. Estou estudando C pra um projeto escolar com Arduino e aqui estou aprendendo o basico da linguagem, pra depois me aprofundar em funções especificas. Em breve estudarei java.... E queria sugerir que criassem apostilas de desenvolvimento movel, web e software graficos.

Apostila C Progressivo disse...

Olá iKillerx,

Se você usar a função scanf() pra pegar uma string, ela vai pegar tudo até o primeiro espaço. Tipo, se você digitar seu nome completo, ela só armazena o primeiro nome, pois para de armazenar quando você digita um espaço.

Esse é o padrão da função.

Ao colocar [^\n] estamos mudando o comportamento dela, pra ela parar somente quando você digitar enter (\n). Você pode ter mais informações sobre isso no link que te passei.

Obrigado por mostrar o erro. Na verdade colocamos \" para aparecer as aspas no printf(), mas na hora de formatar, botar as cores e tal pra publicar aqui no site, saiu sem as barras.

Agradecemos também a sugestão que nos enviou. Temos um site, com pouco conteúdo, sobre Eletrônica de um modo geral, onde já falamos sobre o 8086, e planejamos fazer algo com PIC e Arduíno.

Abraços e bom estudo.

Anônimo disse...

Apenas uma observação: quando vc diz "Quando formos usar o typedef com estruturas, não podemos declarar variáveis após o ponto-e-vírgula", não serias ANTES do ponto e virgula?
E vou aproveitar tambem para agradecer pelo curso que voce disponibilizou de graça para todos, aprendi muito com ele, voces ensinam muito bem, vlw :)

Anônimo disse...

A página é incrível, e a iniciativa de compartilhar tudo isso é única - o maior site brasileiro de ensino de Linguagem C.

Quanto ao typedef, francamente, sou professor e, para iniciantes, minha opinião é de que é uma grande perda de tempo. É divertido poder criar seus próprios dados, mas não vejo utilidade alguma em um comando assim para pequenos e até mesmo códigos medianos.

Obrigado novamente pelo material.