1. Prof. José Augusto Cintra
http://www.josecintra.com/blog
Com exercícios resolvidos no GITHUB
Introdução à Linguagem de Programação
C
Revisão 2 – Julho/2020 (Quarto mês da quarentena)
2. Apresentação
Este curso de Introdução à Linguagem C é uma continuação do
curso Algoritmos e & Lógica de programação.
Supõe-se, portanto, que o estudante já possua conhecimento
teórico das estruturas básicas dos algoritmos, bem como noções
sobre os tipos e estruturas de dados elementares como Vetores e
Strings.
Para um melhor aproveitamento do curso acesse os exercícios
resolvidos no GITHUB
2
4. Histórico
Criada por Denis Ritchie na década de
1970 para uso em um computador DEC
PDP-7 em Unix, a linguagem C Foi
baseada na linguagem B, de Kenneth
Thompson.
4
O sistema Unix, assim como a maioria dos software de base foram
escritos em C, que ainda é uma das linguagens mais utilizadas no
mundo, existindo compiladores para praticamente todos os
processadores existentes.
Não confunda C e C++. A segunda é uma extensão orientada a
objetos da primeira e foi criada por Bjarne Stroustrup em 1985.
6. Ambientes de Desenvolvimento
Existem diversos compiladores e IDEs para a linguagem C. Neste
curso estou utilizando o GCC (The GNU Compiler Collection),
pré-instalado na maioria das distribuições LINUX, juntamente com
a IDE Geany. A Geany está disponível para sistemas Windows
também.
Outras opções open source:
Pelles C → Ambiente completo de desenvolvimento, exclusivo
para a linguagem C em Windows
Mingw64 → GCC para Windows
My-Dev-CPP → IDE que inclui o GCC para Windows
Além disso, é possível configurar a maioria das IDEs populares,
como o Visual Studio Code, para trabalhar com vários
compiladores C.
6
7. Estrutura Básica de um Programa C
Um arquivo de código-fonte padrão da linguagem C segue o
seguinte esqueleto:
// diretivas para o pré-processamento
// declaração de variáveis globais
main ()
{
// declaração de variáveis locais
// Sequência de comandos
}
A seguir, explicaremos cada uma dessas linhas...
→ 7
8. Diretivas de Pré-processamento
Antes de compilar a aplicação, o compilador C realiza algumas
tarefas iniciais chamadas de etapa de pré-processamento ou pré-
compilação.
O desenvolvedor pode então colocar no início do código-fonte
algumas instruções chamadas de diretivas.
Essas diretivas possuem o prefixo “#”.
Não é do escopo desse trabalho descrever todas as diretivas, mas vou
citar duas delas como exemplo.
A diretiva #define permite definir uma abreviatura conhecida como
MACRO.
Exemplo: #define MAX 100
Dessa forma, o pré-processador vai substituir no código todas as
ocorrências de MAX por 100.
Pode-se definir abreviaturas que envolvam inclusive comandos da
linguagem C 8
9. A Diretiva “include”
O núcleo da linguagem C é bem compacto e sua arquitetura é
modularizada. Dessa forma, grande parte das funcionalidades são
definidas em grupos de arquivos, os quais recebem o nome de
Biblioteca Padrão da Linguagem C.
A Diretiva de pré-processamento #include permite incluir uma
biblioteca que contenha funções pré-definidas que podem ser
utilizadas nos programas
Vejamos as principais:
Funções de texto
#include <string.h>
Funções matemáticas
#include <math.h>
Funções padrão
#include <stdlib.h>
Funções de entrada e saída
#include <stdio.h>
9
10. Considerações Sobre o “include”
Uma biblioteca é um conjunto de funções agrupadas em um arquivo fonte. Em C é
comum, porém opcional, a criação de arquivos de cabeçalho (extensão .h). Esses
arquivos agrupam as definições das funções utilizadas em cada pacote de
biblioteca
A diretiva #include é usada para avisar ao compilador que vamos usar uma
biblioteca externa no nosso programa. Dessa forma, o código dessa biblioteca é
incluído na compilação e seus comandos/funções serão validados e ficarão
disponíveis para utilização.
Exemplo:
#include <stdio.h>
#include “my_library.h”
Quando usamos < >, avisamos ao compilador para procurar o arquivo na pasta
padrão das bibliotecas do seu compilador (bibliotecas do sistema).
Quando usamos “ ”, avisamos ao compilador que vamos usar uma biblioteca
definida pelo usuário ou de terceiros. Nesse caso, o compilador vai procurar no
caminho que está definido dentro das aspas, que pode ser a pasta atual.
10
11. Comentários
Os comentários, em qualquer linguagem, são inserções explicativas
no código fonte que são ignoradas pelo compilador, mas ajudam a
documentar as aplicações. No entanto, excesso de comentários ou
explicações óbvias, mais atrapalham que ajudam. Por isso use com
moderação e sabedoria.
Em C, os comentários, são identificados por // ou /* */.
Veja:
/*Isto é um comentário ocupando várias
linhas */
// Isto é um comentário de uma linha só
11
12. // Alô Mundo na linguagem C
#include <stdio.h>
int main()
{
printf("Alô Mundo!");
}
Um programa em C é composto por um conjunto de funções. A função pela
qual o programa começa a ser executado deve chamar-se main.
As chaves {} marcam o início e fim de funções e blocos de código
A função printf, definida em stdio.h, imprime uma expressão no dispositivo
padrão (Tela do Monitor).
As instruções C são sensíveis ao caso. PRINTF é diferente de printf.
Todos os comandos devem terminar com ponto e virgula (;).
Um arquivo de código deve possuir a extensão C. Nesse exemplo, alo.c
Alô Mundo!
12
Comentário
Inclusão da biblioteca de IO
Função principal
Imprime a mensagem
Demarca o início da função principal
Demarca o fim da função principal
13. Compilando...
Na IDE Geany em Linux ou Windows, o processo de compilação
consiste simplesmente em selecionar a opção Build (Construir) no
menu e depois a opção Execute.
Para quem está usando GCC no Windows e quer compilar “na
mão”:
gcc alo.c –o alo.exe
13
14. Tipos de Dados
• O modificador UNSIGNED define um número positivo (sem faixa negativa)
• O tamanho do tipo int depende do processador 14
Tipo Tamanho Faixa de valores
char 1 byte -128 até 127
unsigned char 1 byte 0 até 255
signed char 1 byte -128 até 127
int 2 ou 4 bytes -32,768 até 32,767 ou -2,147,483,648 até 2,147,483,647
unsigned int 2 ou 4 bytes 0 até 65,535 ou 0 até 4,294,967,295
short 2 bytes -32,768 até 32,767
unsigned short 2 bytes 0 até 65,535
long 8 bytes -9223372036854775808 até 9223372036854775807
unsigned long 8 bytes 0 até 18446744073709551615 - 6 decimal places
float 4 byte 1.2E-38 até 3.4E+38 - 6 decimal places
double 8 byte 2.3E-308 até 1.7E+308 - 15 decimal places
long double 10 byte 3.4E-4932 até 1.1E+4932 - 19 decimal places
15. Declaração de variáveis
Diferentemente do Portugol, a variáveis em C podem ser
declaradas em qualquer ponto do programa. Não existe uma área
VAR para declarações.
Os nomes das variáveis devem conter apenas letras, dígitos ou o
underscore. E devem iniciar com letra ou underscore.
C diferencia letras maiúsculas de minúsculas!
De início, trabalharemos com os tipos abaixo:
Portugol C
inteiro int
real float
15
16. Declaração de variáveis
Em Portugol
var
media : real
idade : inteiro
Na Linguagem C
float media;
int idade;
16
Obs: O processo de declarar uma variável consiste em definir seu
nome e tipo de dado. O compilador então irá reservar um espaço
na memória de acordo com tipo da variável.
O processo de inicialização é outra etapa e consiste em atribuir um
valor inicial para a variável declarada.
O compilador C, diferente do VisuALG, não inicializa as variáveis
com nenhum valor. Dessa forma as variáveis declaradas no
exemplo acima conterão o que chamamos de LIXO em seu
conteúdo. Ou seja, CUIDADO, a inicialização precisa ser feita
pelo programador
17. Operação de Atribuição
A operação de atribuição consiste em fornecer um valor para a
variável. Como vimos, a declaração apenas reserva um espaço em
memória, sem atribuir nenhum valor. Para atribuir um valor para a
variável, usamos o operador de atribuição
O operador de atribuição do C é o sinal de igual (=) que seria o
equivalente ao <- do Portugol.
Exemplo:
int idade, nova_idade;
idade = 18;
nova_idade = nova_idade + 1;
Ocorrerá um erro, caso o valor atribuído seja de um tipo
diferente do declarado.
Podemos declarar e inicializar a variável no mesmo comando:
int idade = 18 17
18. Operadores de atribuição
Equivale a x = x % y
x %= y
%=
Equivale a x = x / y
x /= y
/=
Equivale a x = x * y
x *= y
*=
Equivale a x = x – y
x -= y
-=
Equivale a x = x + y
x += y
+=
Atribui o valor de y a x
x = y
=
Comentário
Exemplo
Operador
18
19. Entrada de Dados
O que chamamos aqui de entrada de dados seria a atribuição de
um valor para a variável pelo próprio usuário do programa em
tempo de execução. Para isso usaremos a função “scanf” que será o
equivalente à função “leia” do Portugol.
scanf ("formatos", &var1, &var2,...)
O primeiro parâmetro da função scanf, chamado de string de
formato descreve como deve ser convertida a sequência de
caracteres da entrada. O prefixo “&” na frente dos nomes da
variáveis é um operador de endereço e é obrigatório. Veremos mais
detalhes sobre esse operador quando falarmos de ponteiros
De início, usaremos os seguintes formatos
“%d” → Números inteiro (int)
“%f” → Números de ponto flutuante(float)
19
20. Entrada de Dados
Em Portugol
Para as variáveis
N1 do tipo inteiro e
N2 do tipo real
leia(N1)
leia(N2)
leia(N1,N2)
Na Linguagem C...
Para as variáveis
n1 do tipo int e
n2 do tipo float
scanf ("%d",&n1);
scanf ("%f",&n2);
scanf (“%d%f”,&n1,&n2);
20
21. Saída de dados
Para exibir uma expressão no dispositivo padrão (tela do
computador) usaremos a função printf que será o equivalente à
função escreva do Portugol.
printf ("formatos", var1, var2,...)
Os formatos que usaremos, por enquanto são:
“%d” → inteiro (int)
“%f” → Ponto Flutuante (float)
Obs: Veja que as variáveis do printf não são precedidas de “&”.
21
22. Saída de Dados
Em Portugol
Para as variáveis
N1 do tipo inteiro e
N2 do tipo real
escreva(N1)
escreva(N2)
escreva(N1,N2)
Na Linguagem C...
Para as variáveis
N1 do tipo int e
N2 do tipo float
printf ("%d“,n1);
printf ("%f“,n2);
printf (“%d%f”,n1,n2);
22
23. Considerações sobre a Função “printf”
Como vimos, a função printf é usada para imprimir qualquer tipo
de expressão envolvendo variáveis e constantes literais e aceita
alguns caracteres de controle para formatar a saída. As constantes
literais, como vimos na aplicação Alô Mundo, devem estar entre
aspas duplas e podem incluir caracteres ESCAPE de controle que
devem ser precedidos do sinal “”.
Os principais são:
n – NewLine = Pula uma linha
t - Tabulação horizontal = Equivale à tecla TAB
O sinal de % , como vimos, é para formatação de variáveis
Exemplos:
printf(“Alô Mundon”); // Imprime a frase e pula linha
printf(“O valor da variável x é igual a %d”,x);
Nesse exemplo, veja que a variável x não está entre aspas e vai ser
impressa na posição onde aparece o código %d (inteiros)
23
24. O tipo de dado char, como vimos representa um único caractere
de texto, mas internamente são tratados como um tipo inteiro de
um byte e, inclusive, podemos realizar operações aritméticas com
eles.
Exemplo:
char c = 'A’;
c++;
printf ("%c n",c);
printf ("%d n",c);
Irá imprimir:
B
66
O tipo “char”
24
Veja que valores do tipo char devem
ser delimitados por aspas simples
Imprimindo a variável com o
formato de caracteres
Imprimindo a mesma variável
com o formato de inteiros
Código ASC da letra ‘B’
Somando 1 ao caractere ‘A’
25. Operações e Operadores matemáticos
Decrementa em 1 o valor de x
x--
--
Incrementa em 1 o valor de x
x++
++
Resto da divisão de x por y
x % y
%
Divide x por y
x / y
/
Multiplica x e y
x * y
*
Subtrai y de x
x – y
-
Soma x e y
x + y
+
Comentário
Exemplo
Operador
25
26. Exemplo de um Programa C Típico
// Cálculo da média entre 2 números informados pelo usuário
#include <stdio.h>
main()
{
//Declaração de variáveis
float nota1, nota2, media;
//Entrada de dados
printf ("Digite primeira nota: ");
scanf ("%f" ,¬a1);
printf ("Digite segunda nota: ");
scanf ("%f" ,¬a2);
//Processamento
media = (nota1 + nota2) / 2;
// Saída de dados
printf (“A média é igual a %f", media);
} 26
Confira mais exercícios resolvidos no GITHUB
28. Estruturas de Decisão
28
São estruturas que, dada a avaliação de uma expressão lógica
(condição), permitem a escolha de um fluxo de instruções a ser
executado
No máximo só podem existir dois fluxos de instruções:
Um, se a condição for Verdadeira, e outro se a condição for Falsa
Para avaliar as expressões, podemos usar os operadores relacionais
e os operadores lógicos
29. Operadores Relacionais (Comparação)
29
O conteúdo de x é maior que o de y?
x > y
>
O conteúdo de x é menor que o de y?
x < y
<
O conteúdo de x é maior ou igual ao de y?
x >= y
>=
O conteúdo de x é menor ou igual ao de y?
x <= y
<=
O conteúdo de x é diferente do de y?
x != y
!=
O conteúdo de x é igual ao de y?
x == y
==
Significado
Exemplo
Operador
Importante: Não confunda o operador de atribuição (=) com o
operador comparação por igualdade (==)
30. && (E lógico): retorna verdadeiro se ambos os operandos são
verdadeiros e falso nos demais casos.
Exemplo: if (a > 2 && b < 3).
|| (OU lógico): retorna verdadeiro se pelo menos um dos
operandos é verdadeiro, e falso se ambos são falsos.
Exemplo: if (a > 2 || b <3).
! (NÃO lógico): usada com apenas um operando. Retorna
verdadeiro se o operando é falso ou vice-versa.
Exemplo: if (!(a > 2)).
As expressões lógicas em C retornam:
0 = Falso
Qualquer outro valor = Verdadeiro.
Operadores Lógicos
30
31. F ou F → F
F e F → F
F ou V → V
F e V → F
Não V → F
V ou F → V
V e F → F
Não V → F
V ou V → V
V e V → V
Tabela NÃO
Tabela OU
Tabela E
Tabela Verdade
31
32. Em portugol, o
comando de decisão
tem a seguinte
sintaxe:
se <condição> entao
<bloco de comandos>
senao
<bloco de comandos>
fimse
Estrutura de Decisão
Na linguagem C a
sintaxe é esta:
if (<condiçao>) {
<bloco de comandos>
}
else {
<bloco de comandos>
}
32
33. Observações:
Em C, a condição deve estar entre parênteses;
Não existe a cláusula entao ou fimse;
O bloco de comandos deve estar entre chaves{} (a menos que
seja um único comando);
A cláusula else é opcional;
A expressão é avaliada. Se ela for verdadeira, o bloco if é
executado. Caso contrário, o bloco do else (se existir) é
executado;
Lembre-se: Apenas o código associado ao if ou else será
executado, nunca ambos.
Estrutura de Decisão
33
34. // Ler uma idade e determinar se é maior de idade
#include <stdio.h>
main (){
int idade;
printf ("Digite a idade da pessoa: ");
scanf ("%d", &idade);
if (idade >= 18) {
printf ("Pessoa é maior de idade.n");
} else {
printf ("Pessoa é menor de idade.n");
}
}
Exemplo “if-else”
34
35. A estrutura if-else-if em C permite selecionar entre mais de duas Alternativas
de decisão.
Exemplo: Determinar se um número é positivo, negativo ou zero (três
alternativas):
#include <stdio.h>
int main ()
{
int num;
printf ("Digite um numero: ");
scanf ("%d",&num);
if (num>0) {
printf ("O numero e Positivo");
} else if (num == 0) {
printf ("O numero e igual a 0");
} else {
printf ("O numero e negativo");
}
}
Exemplo “if-else-if”
35
Confira mais exercícios resolvidos no GITHUB
36. É uma forma de reduzir a complexidade de decisões encadeadas.
O conteúdo de uma variável é comparado sucessivamente com
um valor constante, e caso a comparação seja verdadeira, um
determinado comando é executado.
switch (variável){
case constante1:
Instruções;
break;
case constante2:
Instruções;
break;
default
Instruções;
}
Estrutura de Decisão “switch case”
36
37. #include <stdio.h>
main () {
int valor;
printf ("Digite um valor de 1 a 7: ");
scanf("%d", &valor);
switch ( valor ) {
case 1 :
case 7 :
printf ("Fim de semanan");
break;
case 2 ... 5 :
printf ("Dia de semanan");
break;
default :
printf ("Valor invalido!n");
}
Exemplo “switch case”
37
39. São estruturas que permitem executar um trecho de código várias
vezes de acordo com uma condição de parada.
Na linguagem C podemos escolher entre três tipos de estruturas de
repetição:
while (avalia a condição no início do laço)
do while (avalia a condição no fim do laço)
for (usada principalmente em contagens)
Como veremos a seguir...
Estruturas de Repetição
39
40. while (condição){
<blocos de comandos>
}
Não esquecer dos parênteses;
O bloco de comandos será executado enquanto a
condição for verdadeira;
O programador deve cuidar para que a condição fique
falsa em algum momento, do contrário o programa
fica indefinidamente repetindo os comandos.
Estrutura “while”
40
41. Exemplo “while”
//Exibir números de 1 a 10 usando while
#include <stdio.h>
main()
{
int cont = 1 ;
while(cont <= 10) {
printf ("%d n", cont);
cont++;
}
}
Pergunta: O que vai acontecer se você inicializar a variável cont
com o valor 11?
41
42. do {
<blocos de comandos>
} while (condição);
• Não esquecer dos parênteses;
• Os comandos serão executados pelo menos uma vez. E
continuarão sendo executados enquanto a condição for
verdadeira;
• O programador deve cuidar para que a condição fique falsa em
algum momento, do contrário o programa fica indefinidamente
repetindo os comandos.
Estrutura “do while”
42
43. Exemplo “do while”
//Exibir números de 1 a 10 usando while
#include <stdio.h>
main()
{
int cont = 1 ;
do {
printf ("%d n", cont);
cont++;
} while (cont <=10)
}
Pergunta: O que vai acontecer se você inicializar a variável cont
com o valor 11?
43
44. for (var=inicio; condição; incremento){
<bloco de comandos>
}
Não esquecer dos parênteses;
Os comandos serão executados enquanto a condição for
verdadeira
O incremento ou decremento é executado automaticamente
após a execução dos comandos
Estrutura “for”
44
45. //Exibir números de 1 a 10 usando FOR
#include <stdio.h>
main()
{
int cont ;
for (cont = 1; cont <= 10; cont++ )
{
printf ("%d n", cont);
}
}
Exemplo “for”
45
46. E para forçar o término da repetição? Use um break.
Exemplo: Saída:
1
2
3
4
5
Após o FOR: 5
#include <stdio.h>
#include <stdlib.h>
main(){
int i;
for (i=1; i<=10; i=i+1){
printf ("%dn",i);
if (i==5) break;
}
printf(“Após o FOR: %dn",i);
}
Comando “break”
46
Confira mais exercícios resolvidos no GITHUB
48. As estruturas de dados básicas, disponibilizadas nativamente na
linguagem C são os tipos de dados compostos, que são formados
a partir dos tipos de dados primitivos.
São divididos em Homogêneos, quando compostos de apenas um
tipo e Heterogêneos, com tipos de dados diferentes:
Homogêneos: Arrays (Vetores e Matrizes) e Strings (Cadeias de
caracteres).
Heterogêneos: Structs (Registros) e Unions (Não abordada
nesse curso).
Estruturas de Dados Básicas
48
49. Vetores (Array)
Um vetor (= array de uma dimensão) é uma estrutura de dados
que armazena uma sequência de valores (variáveis), todos do
mesmo tipo, em posições consecutivas da memória.
Cada elemento do vetor é identificado por sua posição dentro do
vetor (índice do vetor).
São conhecidos como Estruturas de Dados Unidimensionais
Homogêneas. Unidimensionais, pois forma uma sequência
linear de valores consecutivos. Homogêneas, pois todos os
valores são do mesmo tipo
49
50. Vetores (Arrays)
A quantidade de elementos (tamanho do vetor) e seu tipo devem
ser definidas no momento da declaração e são imutáveis;
Os elementos possuem ordinalidade, cada um pode ser
identificado pela sua posição (índice do vetor);
Em C, os índices dos vetores começam em 0 (zero) e vão até
(tamanho-1)
Cada elemento do vetor, por meio do seu índice, pode ser
acessado como uma variável individual.
No vetor abaixo de nome “idades”, o valor do elemento de índice
4 é 81.
idades
Índices
Valores
50
17 33 21 67 81 10 45 29 79 98
0 1 2 3 4 5 6 7 8 9
51. Sintaxe: <tipo> <nome> [ tamanho];
Exemplo:
int vet[5];
vet[0] = 3;
vet[1] = 5;
vet[2] = 13;
vet[3] = 10;
vet[4] = 5;
Declaração e Inicialização deVetores
51
Endereço Conteúdo Índice vet
0022FF74 3 0 vet[0]
0022FF76 5 1 vet[1]
0022FF78 13 2 vet[2]
0022FF80 10 3 vet[3]
0022FF82 5 4 vet[4]
Localização na memória
Nome do vetor
Cada uma
das variáveis
identificadas
pelo índice
Declaração
Inicialização de cada elemento do vetor.
Veja que o índice vai de 0 até tamanho - 1
No exemplo acima,
declaramos e
inicializamos um vetor de
nome vet com
capacidade para 5
números inteiros. Outra
forma rápida de fazer
isso, seria:
int vet[] = {3,5,13,10,5};
52. Leitura e Escrita deVetores
Podem ser manipulados como variáveis comuns, bastando indicar
o índice.
Exemplo:
int vet[5];
printf("Digite o valor do primeiro elemento: ");
scanf("%d",&vet[0]);
printf("O valor do primeiro elemento é %d",vet[0]);
52
53. #include <stdio.h>
int main()
{
int vet[10];
int i = 0;
for(i = 0; i < 5; i++) {
vet[i] = i * 2;
printf(“índice = %d e valor = %d n",i,vet[i]);
}
} Na tela: Na memória:
Resultado:
Exemplo de Algoritmo comVetor
53
indice = 0 e valor = 0
indice = 1 e valor = 2
indice = 2 e valor = 4
indice = 3 e valor = 6
indice = 4 e valor = 8
Este exemplo cria um vetor inteiro com 5 elementos
e inicializa cada elemento com o valor do dobro de
seu próprio índice, usando uma estrutura for.
Repetição variando i de 0 até 4
0 1 4 6 8
0 1 2 3 4
Confira mais exercícios resolvidos no GITHUB
54. De forma abstrata, Uma string é um tipo de dado que representa
um texto, uma palavra ou frase qualquer, ou seja, um conjunto de
caracteres.
A linguagem C não possui um tipo específico para strings. Ao
invés disso uma string é um vetor de caracteres (array of chars)
terminada pelo caractere nulo (0).
Por exemplo: A string “ALGORITMO” seria representada na
memória como:
Strings
54
A L G O R I T M O 0
0 1 2 3 4 5 6 7 8 9
Índices
String
Terminador
55. As strings em C devem ser inicializadas na declaração, de
modo similar aos vetores, de acordo com os exemplos:
char frase[] = “minha string”;
OU
char frase[13] = “minha string”;
OU
char frase[20] = “minha string”;
OU
char frase[6] = {‘t’, ‘e’, ‘s’, ‘t’, ‘e’, 0};
A operação abaixo NÃO é permitida:
char frase[];
frase = “minha string”;
Declaração e Inicialização de Strings
55
56. Para ler e imprimir strings podemos usar as funções printf e
scanf com o código de formatação “%s”.
Exemplo:
#include <stdio.h>
main() {
char nome[50];
printf("Digite seu nome: ");
scanf(“%s”,&nome);
printf("Olá %s!",nome);
}
Leitura e Impressão de Strings
56
Cuidado com a função scanf com strings.
Essa função não verifica se a entrada
ultrapassou o tamanho da string.
Uma alternativa para isso é a função fgets
que toma esse cuidado.
57. A biblioteca padrão da linguagem C, através do header string.h,
oferece uma série de funções para manipulação de strings que.
Citaremos, a seguir as principais:
Função: strlen
Protótipo: int strlen (char *string)
Descrição: Retorna o número de caracteres de uma string (exceto o
caractere de fim de string).
Exemplo:
char nome[] = “José Cintra”;
printf (“O nome possui %d letras”, strlen(nome));
Manipulação de Strings
57
58. Função: strcpy
Protótipo:
char *strcpy (char *string1, char *string2)
Descrição:
Copia o conteúdo de string2 em string1
Exemplo:
char str1[10];
char str2[] = “Palavra”;
strcpy(str1, str2); // str1 também contém “Palavra”
Manipulação de Strings
58
59. Função: strcat
Protótipo:
int strcmp (char *string1, char *string2)
Descrição: Compara os conteúdos de string1 e string2 e retorna:
= 0 se string1 = string2
< 0 se string1 < string2
> 0 se string1 > string2
Manipulação de Strings
59
Exemplo:
char nome1[] = “José da Silva”
char nome2[] = “José Silva”;
if (strcmp (nome1, nome2) == 0) {
printf (“Nomes são iguais”);
} else {
printf (“Nomes são diferentes);
}
61. /* Concatena 2 strings informadas pelo usuário
e exibe a string resultante com o seu tamanho */
#include <stdio.h>
#include <string.h>
main () {
char str1[20],str2[20],str3[40];
int tamanho ;
printf("Informe a string 1: "); scanf("%s",&str1);
printf("Informe a string 2: "); scanf("%s",&str2);
strcat( str3, str1); strcat( str3, str2);
printf("%sn", str3 );
tamanho = strlen(str3);
printf("Tamanho: %dn", tamanho );
}
Strings - Exemplo
61
Confira mais exercícios resolvidos no GITHUB
62. Structs são estruturas de dados compostas heterogêneas formadas
por um conjunto de variáveis, possivelmente, de tipos diferentes,
mas relacionadas entre si.
São muito parecidas com registros em tabelas de bancos de dados
e, por isso as variáveis que as compõem são comumente chamadas
de campos.
Sintaxe:
struct <identificador> {
<listagem dos tipos e campos>;
};
Para definir a variável do tipo struct:
struct <identificador> <variavel>;
Structs
62
63. Uma struct para representar uma pessoa poderia possuir a seguinte
definição:
struct registro_pessoa {
char[50] nome;
float peso;
float altura;
};
Para criar uma variável desse tipo, fazemos:
struct registro_pessoa joao;
Dessa forma, os campos podem ser acessados individualmente, por
exemplo, da seguinte forma:
joao.peso = 72.5;
printf(“%d”,joao.peso);
Structs
63
65. Structs são úteis quando utilizadas em conjunto com vetores para
utilização em arquivos ou bancos de dados:
struct registro_pessoa pessoas[10];
strcpy(pessoas[0].nome,"José Cintra");
pessoas[0].peso = 72.5;
pessoas[0].altura = 1.68;
printf("Nome: %sn",pessoas[0].nome);
printf("Peso: %fn",pessoas[0].peso);
printf("Altura: %fn",pessoas[0].altura);
Nesse exemplo atribuímos valores apenas para o primeiro elemento
do vetor. O ideal seria trabalhar com estruturas de repetição para
manipular um grande números de registros.
Vetores de Structs
65
Criando um vetor de
nome pessoas com
10 elementos do tipo
struct
66. Ponteiros não são estruturas de dados compostas, mas são
importantíssímos para desenvolvermos programas profissionais em
C. Vamos dar uma visão geral sobre eles nesse curso.
Como sabemos, toda variável é armazenada em um local de
memória e todo local de memória tem um endereço bem definido.
Um ponteiro é uma variável cujo valor é o endereço de outra
variável, isto é, o endereço direto da localização da memória.
Existem dois operadores em C para manipularmos ponteiros e
endereços de memória:
Ponteiros
66
Operador Nome Objetivo
* “Derreferência”
Retorna o valor armazenado em um endereço da
memória
& Referência Retorna o endereço de memória de uma variável
67. O operador de “derreferência” pode ser usado também para
declaramos um ponteiro, de acordo com o seguinte exemplo:
#include <stdio.h>
int main () {
int var = 5; // Declaração de uma variável simples
int *ip; // Aqui declaramos um ponteiro para int
ip = &var; // Atribuímos para ip o endereço da variável var
printf("Endereço da variável var: %xn", &var );
printf("Endereço armazenado na ponteiro ip: %xn", ip );
printf("Valor armazenado no ponteiro ip: %dn", *ip );
printf("Valor armazenado na variável var: %dn", var);
}
Endereço da variável var: 61fe14
Resultado: Endereço armazenado no ponteiro ip: 61fe14
Valor armazenado no ponteiro ip: 5
Valor armazenado na variável var: 5
Ponteiros Exemplo
67
%x é o formato para hexadecimal
em minúsculas
69. Funções
Como vimos na apostila de algoritmos, uma função é uma técnica
de modularização que consiste em encapsular um bloco de
código que possui uma determinada funcionalidade de tal modo
que possa ser reutilizado por outros módulos do sistema.
Uma função C possui as seguintes características:
Possui um nome
Pode, opcionalmente, receber parâmetros de entrada de diversos
tipos
Retorna um único valor de um determinado tipo
Pode ser declarada dentro do próprio módulo que a chamou ou
ficar em módulos separados
Pode ser usada em expressões
Sua interface pode ser descritas em protótipos
69
70. Funções
Uma função em C é definida através da seguinte sintaxe:
<tipo_retorno> <nome_funcao>( [lista_parametros]) {
[corpo da função]
[return valor_retorno]
}
tipo_retorno → É o tipo de dado retornado pela função. Caso a
função não retorne valores, o tipo será void.
nome_função → É o nome da função que deve seguir as regras de
nomeação de identificadores.
lista_parâmetros → consiste na declaração dos parâmetros de
entrada recebidos pela função.
return → Determina o valor que será retornado para o módulo
chamador, quando o tipo do retorno é diferente void. 70
71. Exemplo de uma função sem parâmetros de entrada nem valores de
retorno. Essa função imprime um asterisco na tela
#include <stdio.h>
void imprime() {
printf("*");
}
main () {
imprime();
}
Funções - Exemplos
71
Função sem retorno (void).
Função sem parâmetros de entrada.
Os parênteses são obrigatórios.
Chamada da função no código principal.
A função será executada e o programa
prosseguirá
Vai imprimir:
*
72. Com a mesma função definida anteriormente, vamos agora chamá-
la 5 vezes pelo programa principal:
#include <stdio.h>
void imprime() {
printf("*");
}
main () {
int i;
for(i = 1; i <= 5; i++){
imprime();
}
}
Funções - Exemplos
72
Vai imprimir:
*****
73. Vamos agora inverter a lógica. Alteramos a função para imprimir 5
vezes o asterisco. A função será chamada apenas 1 vez pelo
programa principal:
#include <stdio.h>
void imprime() {
int i;
for(i = 1; i <= 5; i++){
printf(“*”);
}
}
main () {
imprime();
}
Funções - Exemplos
73
Vai imprimir:
*****
74. Agora alteramos a função e colocamos um parâmetro de entrada
para que ela imprima o asterisco o número de vezes solicitado:
#include <stdio.h>
void imprime(int vezes) {
int i;
for(i = 1; i <= vezes; i++){
printf("*");
}
}
main () {
imprime(3);
}
Funções - Exemplos
74
Vai imprimir:
***
O parâmetro inteiro vezes
será usado na repetição for
para determinar o número de
vezes que o texto será impresso
Aqui chamamos a função imprime passando
o valor 3 que será atribuído para o parâmetro
vezes da função
75. Dessa vez alteramos a função e colocamos um segundo parâmetro
de entrada para que ela imprima qualquer caractere e não mais só o
asterisco:
#include <stdio.h>
void imprime(int vezes, char chr) {
int i;
for(i = 1; i <= vezes; i++){
printf("%c",chr);
}
}
main () {
imprime(7,'@');
}
Funções - Exemplos
75
Vai imprimir:
@@@@@@@
76. Como vimos até agora, quando trabalhamos com funções existem
dois momentos distintos:
A definição da função (sua assinatura).
A chamada à função que pode ser na função main ou qualquer
outra função do sistema.
Na definição da função podemos especificar os parâmetros que
serão usados no corpo da função
Na chamada da função Podemos passar os valores para os
parâmetros. Esses valores recebem o nome de argumentos.
Argumentos e parâmetros não precisam possuir o mesmo nome
(identificador) mas precisam ser do mesmo tipo.
Vamos ver a seguir um exemplo de função que possui parâmetros
de entrada e valor de retorno e poderemos entender melhor os
conceitos aqui apresentados.
Funções – Parâmetros e Argumentos
76
77. #include <stdio.h>
// Função que soma dois números passados como parâmetros
float soma(float n1, float n2){
float resultado = n1 + n2;
return resultado;
}
main () {
float v1,v2,r;
printf("Informe o primeiro número: ");
scanf("%f",&v1);
printf("Informe o segundo número: ");
scanf("%f",&v2);
r = soma(v1,v2);
printf("a soma dos números %f e %f é: %f",v1,v2,r);
}
Funções – Parâmetro e Argumentos
77
Aqui definimos uma função de nome soma
com 2 parâmetros do tipo float e retorno do
tipo float.
No corpo da função é calculada a soma
dos parâmetros e o resultado é retornado
para a função main.
Na chamada da função são passados 2 argumentos
do tipo float: v1 é atribuído ao parâmetro n1 e
v2 ao parâmetro n1
O valor de retorno da função soma é atribuído à
variável r
78. Existem duas formas de passarmos os valores dos argumentos para
os parâmetros das funções:
Passagem por valor: o valor das variáveis dos argumentos não se
alteram, mesmo que os parâmetros sejam modificado na função.
Passagem por referência: Os valores das variáveis dos
parâmetross refletem nos argumentos.
Na linguagem C, as variáveis passadas como argumentos para as
funções são sempre passados por valor e, portanto, seus valores
não são alterados dentro da função.
Para passamos valores por referência, Podemos usar o operadores
de referência (&) que vimos no estudo dos ponteiros. Dessa forma
passamos o endereço da variável.
Passagem por Valor ou Referência
78
79. #include <stdio.h>
void f(int a, int *b){
a = 2;
*b = 2;
printf("%dn",a); // Imprime: 2
printf("%dn",*b); // Imprime: 2
}
main () {
int c = 1;
int d = 1;
f(c,&d);
printf("%dn",c); Imprime: 1
printf("%dn",d); Imprime: 2
}
Passagem por Valor ou Referência
79
Neste exemplo, o parâmetro a é passado
por valor e o parâmetro b por referência.
Veja que o valor da variável d foi alterado
pela função f() pois foi passado por referência
O mesmo não aconteceu com a variável
c que foi passada por valor.
80. O escopo de variáveis tem a ver com o princípio do ocultamento
de informações e permite que as variáveis só possam ser acessadas
de dentro da função que as criou. Isso é mais seguro, pois não
permite que módulos externos interfiram na lógica das funções.
A linguagem C possui os seguintes escopos de variáveis:
Global: São as variáveis declaradas fora de qualquer função e
são acessíveis em todo o Sistema. O tempo de vida dessas
variáveis se encerra quando o programa se encerra.
Local: São variáveis declaradas dentro de uma função ou bloco
de Código e são vistas somente na função/bloco em que foram
declaradas. O tempo de vida dessas variáveis se encerra quando
a função/bloco se encerra
Estática: Variáveis locais que mantém seus valores entre as
chamadas. São identificadas pelo modificador static. Tempo de
vida: “Global”.
Escopo de Variáveis e Tempo de Vida
80
81. #include <stdio.h>
int a = 1; int b = 1;
void f(){
int c = 2;
static int d = 3;
printf("%dn",c);
printf("%dn",d);
c++; d++;
}
main () {
int a = 4; int e = 5;
printf("%dn",a);
printf("%dn",b);
//printf("%dn",c);
//printf("%dn",d);
printf("%dn",e);
f(); f();
}
Escopo de Variáveis Exemplo
81
Variáveis a e b são globais, visíveis em todo módulo
Variável c é local e visível somente na função f()
A variável d é local e estática, visível somente
na função f()
Somente a variável d vai ser incrementada, pois
é estática. A variável c vai manter sempre o
mesmo valor
As variáveis a e e são locais,
As variáveis c e d não são acessíveis aqui.
Vai ocorrer um erro. Por isso estão comentados
O valor da variável local a vai prevalecer
sobre a variável global a
As chamadas para a função f() vão mostrar que
somente a variável d será incrementada
82. Outras considerações:
Parâmetros de funções são variáveis locais.
Variáveis criadas dentro de blocos de códigos são locais.
Exemplo:
#include <stdio.h>
int main(int argc, char **argv)
{
int i = 1;
for (int i = 0; i <= 10; i++){
printf("%dn",i); // O valor final da variável i é 11
}
printf("%dn",i); // Imprime 1
return 0;
}
Escopo de Variáveis e Tempo de Vida
82
Nesse caso, a variável i declarada
na função main é diferente da variável i
declarada dentro do bloco for
O tempo de vida da variável i do bloco
termina quando termina o for
83. Vetores são passados, por padrão, por referência. Vamos modificar
a função imprime para receber um vetor de caracteres (uma
string) ao invés de um char:
void imprime(int vezes,char *texto) {
int i;
for(i = 1; i <= vezes; i++){
printf(texto);
}
}
main () {
char str[] = “abc";
imprime(2,str);
}
Passando Vetores como Parâmetros
83
Vai imprimir:
abcabc
84. Considerações Sobre a Função “main”
A função main é uma função como todas as outras, mas tem um
comportamento especial. Ela é obrigatória em programas
executáveis e indicam o ponto de partida onde a execução do
programa vai iniciar.
Quando a função main se encerra, o programa também se encerra e
o valor de retorno de main será recebido pelo sistema operacional
indicando se o programa executou com sucesso ou não. Um
retorno 0 (zero) indica que o programa foi executado sem erros.
Ela pode receber parâmetros de entrada que representam os
parâmetros da linha de comando passados quando o programa foi
executado. Uma assinatura completa da função main então seria:
int main(int argc, char **argv)
E, no corpo da função main, deve haver um comando de retorno:
return 0; 84
85. Exercícios Propostos
1) Um sistema de equações lineares do tipo: pode ser resolvido
segundo:
Escreva um algoritmo em C que lê os coeficientes a,b,c,d,e e f e calcule de x e y.
2) Escreva um algoritmo em C que leia 3 números inteiros e mostre o maior deles.
3) Leia um número N e escreva os N número maiores que N.
Exemplo: N = 4 → escrever: 5,6,7,8
4) Leia um vetor com 5 números inteiros e um número inteiro N. Calcule o produto
escalar entre o número N e o vetor.
5) Escreva uma função em C para verificar se uma palavra informada pelo usuário é
palíndroma ou não. 85
86. FIM
Obrigado!
Neste curso fizemos uma pequena introdução à linguagem C com o
objetivo de dar condições ao aluno para se aprofundar nos estudos e
nos assuntos não abordados aqui, tais como:
Aritmética de ponteiros
Headers e protótipos de funções
Estruturas de dados complexas
Manipulação da linha de comando
Etc...
Veja a bibliografia a seguir para mais informações.
86
87. Saiba mais...
Links
https://www.tutorialspoint.com/cprogramming/index.htm
https://www.learn-c.org/
https://www.pucsp.br/~so-comp/cursoc/index.html
https://www.it.uc3m.es/pbasanta/asng/course_notes/ctut.pdf
Livros
Linguagem C, por Luis Damas
C: Como Programar, por Deitel
Exercícios resolvidos
GitHub
http://www.josecintra.com/blog 87