Staffer Group BR™

Fórum interativo totalmente gratuito!


 VisualizaçõesPermissão deste fórum:
Não podes responder a tópicos


CurtirDiretório deste fórum:
Fóruns » Principal »  » Tutoriais » Programação Externa

#1
 D'Leandro™

D'Leandro™
Fundador
Olha eu aqui de novo. Como havia prometido, nessas férias vou movimentar um pouco as coisas por aqui, já que ao longo do ano a coisa vai ser feia. Último ano da faculdade, projeto de conclusão de curso, a minha tentativa de conseguir um mestrado vai ser colocada em prática, enfim, uma correria que só vendo.

Mas vamos parar com a conversa fiada e começar com a ação. Como prometido, nesta terceira e última parte da Introdução à Linguagem C, veremos os dois assuntos pendentes em relação a linguagem Pascal, tomando por base o ponto no qual nos encontramos: registros e as funções e procedimentos.

Bom, não vou me aprofundar muito no conceito do que seria um registro (há um post inteiro dedicado a eles), apenas vou citar as “novidades” na linguagem C. Bom, primeiramente, em C os registros são conhecidos como estruturas ou melhor, pela palavra chave struct. As structs são simplesmente agrupamentos variáveis. Vamos visualizar as diferenças de sintaxe, e em seguida explicaremos suas particularidades (utilizando o mesmo exemplo do post sobre registros):
Código:
[Definição de Tipos]
  Aluno = registro
      nome : literal[30]
      idade : inteiro
  fim-registro
 
[Declaração de Variáveis]
  umAluno : Aluno
Código:
type
  Aluno = record
      nome : string[30];
      idade : integer;
  end;
 
var
  umAluno : Aluno;
Código:
typedef struct
{
  char nome[30];
  int idade;
} Aluno;
 
// em algum lugar do código
Aluno umAluno;
Bom, no exemplo acima vocês tem a comparação entre o Algoritmo, a sintaxe em Pascal e a sintaxe em C. Neste caso citado acima, estamos utilizando registro para criar um novo tipo, chamado de Aluno (só relembrando, a linguagem C é case sensitive, ou seja, ao contrário da linguagem Pascal, Aluno e aluno são coisas diferentes!), criando em seguida uma variável desse novo tipo, com o nome umAluno. Posteriormente explicarei com mais detalhes o uso do typedef.

Utilizar um registro para definirmos um tipo é vantajoso apenas se utilizaremos esse tipo em vários locais do programa. Se fossemos utilizar apenas em um ponto do aplicativo, por exemplo, poderíamos fazer assim:
Código:
struct
{
  char nome[30];
  int idade;
} umAluno;
Isso também resultaria em uma variável de nome umAluno, com os campos nome e idade. “Certo… mas e se eu precisasse passar um registro desse por parâmetro para uma função? Como eu declararia isso?”. Bom, caso você precise passar um registro por parâmetro em uma função, precisaremos nomear essa nossa estrutura. De que forma? Adicionando um identificador entre a palavra reservada struct e o abre chaves. Por exemplo:
Código:
struct aluno {
  char nome[30];
  int idade;
} umAluno;
Lembrando apenas que, para que seja possível passar essa estrutura como parâmetro em funções, sua declaração deve ser feita de forma global (fora de qualquer função ou procedimento) e antes do seu primeiro uso. Ao final do post, quando exemplificarmos a declaração de funções, teremos um exemplo disso. ;)

Com relação a sintaxe dos registros em C, não há muito mistério. Iniciamos com a palavra reservada struct, seguida ou não do identificador daquela estrutura. Em seguida, temos a definição dos campos que comporão aquela estrutura. Isso é feito da mesma forma que declaramos variáveis (observe os exemplos citados acima). Após o fecha chaves, podemos ter um nome de variável, que terá como forma essa estrutura. No final, encerra-se a declaração com ponto e vírgula. Cabe frisar que, caso não haja um nome de variável após a definição dos campos, você terá declarado apenas a estrutura, e não uma variável com o formato da estrutura. Ficou um pouco confuso? Vou tentar explicar melhor. Ao declarar uma estrutura, o struct { … } apenas indica o formato dela, mesmo que você coloque o identificador entre o struct e o {. Digamos assim. Se escrevermos int a; teremos uma variável do tipo inteiro. Se escrevermos struct { … } a; teremos uma variável do tipo da estrutura que definimos. Um dos motivos de frequentemente utilizarmos o typedef é para evitarmos de ter que sempre colocar struct sempre que precisarmos utilizar essa estrutura em nosso programa. Para finalizar as dúvidas: o identificador entre o struct e o { é o nome da estrutura e o que vem depois do } e antes do ; é então a declaração de uma variável do tipo da estrutura. Quaisquer dúvidas sobre o assunto, deixem nos comentários que eu tento explicar melhor.

Para acessar os campos da estrutura, assim como na linguagem Pascal, utilizamos o . seguido do nome do campo. Por exemplo:
Código:
#include
 
struct aluno
{
  char nome[30];
  int idade;
};
 
int main(void)
{
  struct aluno umAluno;
 
  printf("Digite o nome do aluno: ");
  scanf("%s", umAluno.nome);
  printf("Digite a idade do aluno: ");
  scanf("%i", &umAluno.idade);
 
  printf("Aluno %s tem %i anos.", umAluno.nome, umAluno.idade);
 
  return 0;
}
Como pode ser visto, não tem nenhum mistério ao acessar os campos do registro. Esse tipo de acesso só não vai se alterar quando a struct for um ponteiro, mas isso discutiremos no post sobre ponteiros, mais adiante. Só atentem que o segundo argumento da chamada à função scanf, quando o valor é um vetor de caracteres (string), não usa-se o operador & (na 1ª parte desta introdução falei sobre isso).

Concluída então a nossa discussão a respeito de registros, falaremos então a respeito de funções e procedimentos. A primeira coisa que tenho a falar é que, em C, não há distinção entre função e procedimento. Como assim??? É. Ao contrário da linguagem Pascal que define uma palavra chave para função (function) e uma para procedimento (procedure), na linguagem C não há essa distinção. A único detalhe que definirá um procedimento de uma função, e o tipo void como retorno da função, pois em C os procedimentos também podem conter a palavra return ao final de seu escopo. Estranho, né? Vamos então a alguns exemplos de função, em Algoritmo, Pascal e C:
Código:
Função somar(n1, n2 : inteiro) : inteiro
[Início]
 
[Declaração de Variáveis Locais]
  resultado : inteiro
 
[Processamento]
  resultado ← n1 + n2
  retorne(resultado)
 
[Fim]
Código:
function somar(n1, n2 : integer) : integer;
var
  resultado : integer
 
begin
  resultado := n1 + n2;
  somar := resultado;
end;
Código:
int somar(int n1, int n2)
{
  int resultado;
 
  resultado = n1 + n2;
 
  return resultado;
}
A declaração de uma função inicia com o tipo de retorno, no caso deste exemplo, um valor inteiro (int). Logo em seguida, temos o nome de nossa função, seguida com a lista de argumentos, devidamente acompanhados de seus tipos, separados por vírgula (e não ponto e vírgula, como em Pascal) e circundados por parênteses. Logo em seguida, definimos o escopo de nossa função em um bloco entre chaves. O processamento ocorre da mesma maneira com que nas outras partes do programa. O bloco é encerrado pelo retorno, ou seja, a palavra chave return seguido do valor constante ou variável, entre parênteses ou não.

Como já adiantei anteriormente no post, a declaração de um procedimento apenas se diferencia pelo fato do tipo de retorno ser void (o tipo vazio, lembram-se?). Além disso, pode-se simplesmente omitir a linha de retorno ou colocar apenas return; como verificaremos no exemplo a seguir.
Código:
Procedimento somar(n1, n2 : inteiro)
[Início]
 
[Declaração de Variáveis Locais]
  resultado : inteiro
 
[Processamento]
  resultado ← n1 + n2
  escreva("O resultado é ", resultado)
 
[Fim]
Código:
procedure somar(n1, n2 : integer);
var
  resultado : integer
 
begin
  resultado := n1 + n2;
  writeln('O resultado é ', resultado);
end;
Código:
void somar(int n1, int n2)
{
  // Variáveis em C podem ser inicializadas logo na sua declaração
  int resultado = n1 + n2;
 
  printf("O resultado é %i\n", resultado);
 
  return; // Esta linha pode ser omitida!
}
Viu? Praticamente nenhuma diferença em relação às nossa funções.

Bom, então aqui finalmente encerramos a nossa Introdução à Linguagem C, depois de três longos posts. Quaisquer dúvidas que por acaso permanecerem, por favor postem nos comentários, pois a sua dúvida pode ser também a dúvida de outras pessoas. Mais uma vez peço encarecidamente que não me enviem programas para eu fazer. Esses exercícios que o curso técnico / faculdade pedem são de suma importância para fixar o conteúdo e desenvolver o seu raciocínio lógico. Devido ao grande número de e-mails que recebo desse tipo, tenho simplesmente que ignorá-los…

Espero ter ajudado com essa série de posts, e vamos que vamos. Em breve (ou não, vai depender do tempo), continuaremos com essa série de posts didádicos, falando sobre os temidos ponteiros!!! Até lá! :)

Procurando a parte 1 ou parte 2 dessa introdução?