Você está na página 1de 42

Universidade de Passo Fundo

Instituto de Ciências Exatas e Geociências


Curso de Ciência da Computação

Programação I

CCC011 – Programação I
Prof. Marcos José Brusso
Linguagem C 2 Prof. Marcos José Brusso

Índice
HISTÓRICO......................................................................................................................................3
PROGRAMANDO EM C...................................................................................................................3
DIRETIVA #INCLUDE.....................................................................................................................4
VARIÁVEIS......................................................................................................................................4
TIPOS DE DADOS............................................................................................................................4
MODIFICADORES DE TIPO...........................................................................................................5
LITERAIS..........................................................................................................................................6
CARACTERES DE ESCAPE............................................................................................................6
VETORES E MATRIZES..................................................................................................................7
ESCREVENDO VALORES...............................................................................................................7
LENDO VALORES...........................................................................................................................8
OPERAÇÕES ARITMÉTICAS.........................................................................................................10
OPERADORES ARITMÉTICOS.......................................................................................................10
OPERADORES COMBINADOS.......................................................................................................11
OPERADORES RELACIONAIS.......................................................................................................11
OPERADORES LÓGICOS................................................................................................................11
OPERADOR TERNÁRIO..................................................................................................................11
OPERADOR SIZEOF........................................................................................................................12
MOLDAGEM OU CAST...................................................................................................................12
COMANDO IF...................................................................................................................................12
COMANDO DO WHILE...................................................................................................................13
COMANDO WHILE..........................................................................................................................14
COMANDO FOR...............................................................................................................................15
DIRETIVA #DEFINE........................................................................................................................15
DECLARAÇÃO DE FUNÇÕES........................................................................................................16
PONTEIROS......................................................................................................................................17
OPERAÇÕES COM PONTEIROS....................................................................................................17
PASSAGEM DE PARÂMETROS POR VALOR...............................................................................18
PASSAGEM DE PARÂMETROS POR REFERÊNCIA....................................................................19
FUNÇÕES E VETORES...................................................................................................................19
ALOCAÇÃO DINÂMICA DE MEMÓRIA.......................................................................................20
FUNÇÕES DE MANIPULAÇÃO DE STRINGS...............................................................................20
FUNÇÕES DE TRATAMENTO DE CARACTERES.......................................................................21
ARGUMENTOS DE LINHA DE COMANDO..................................................................................22
ESTRUTURAS..................................................................................................................................23
PONTEIROS PARA ESTRUTURAS.................................................................................................25
FUNÇÕES DE ENTRADA E SAÍDA EM ARQUIVOS SEQUENCIAIS..........................................26
FUNÇÕES DE ENTRADA E SAÍDA ALEATÓRIA EM ARQUIVOS.............................................28
EXERCÍCIOS....................................................................................................................................30
Linguagem C 3 Prof. Marcos José Brusso

Histórico
A linguagem C foi criada por Dennis M. Ritchie. Seu desenvolvimento foi influenciado pela linguagem B
implementada por Ken Tompson, que por sua vez foi influenciada pela linguagem BCPL criada por Martin
Richards. O sistema operacional UNIX, boa parte do Windows e muitos de seus aplicativos, assim como muitos dos
softwares básicos e aplicativos existentes no mercado foram escritos em C.

C é uma linguagem estruturada, de relativo baixo nível e que garante portabilidade do código fonte e um programa
objeto muito eficiente, rápido e compacto.

Programando em C

Todo programa em C é composto de uma ou mais funções, que são blocos de código independentes. Uma função
denominada main deve ser definida em cada programa, pois é o seu ponto de entrada. Isto não quer dizer que ela
deva ser a primeira no arquivo fonte, uma vez que a ordem em que as funções foram escritas não interfere na
execução do programa.

Uma função pode efetuar operações e pode chamar outras funções, sendo que estas podem fazer parte do próprio
programa ou ser alguma das diversas funções pré-definidas na biblioteca padrão do C. Assim que a execução de uma
função é concluída, o programa retorna para a próxima instrução após a chamada a esta função. Ao concluir a
função main o próprio programa é finalizado.

Deve-se tomar muito cuidado ao se criar chamadas recursivas, isto é, funções que chamem a si mesma ou uma
função de nível superior.

/* prog001.c */
#include <stdio.h>
#include <conio.h>

void tela(void);

/* Meu primeiro programa */


void main(void)
{
clrscr();
gotoxy(30,11);
printf("Estou na funcao main");
tela();
gotoxy(28, 13);
printf("Voltei para a funcao main");
getch();
}

void tela(void)
{
gotoxy(27,15);
printf("Agora estou na funcao tela");
}

O compilador C diferencia letras maiúsculas de minúsculas, portanto TESTE é diferente de teste, que por sua vez é
diferente de Teste. Todas as palavras reservadas da linguagem devem ser digitadas em letra minúscula.

Qualquer comentário pode ser colocado entre os símbolos /* e */. Um comentário pode aparecer em qualquer lugar
no programa onde possa aparecer um espaço em branco e pode se estender por mais de uma linha.
Linguagem C 4 Prof. Marcos José Brusso

Diretiva #include

Inclui (copia) o conteúdo do arquivo especificado para dentro programa atual.

#include <arquivo.ext>

Usado para arquivos próprios da linguagem com extensão .h (header) que contêm declaração das funções da
biblioteca padrão, definição de tipos compostos e de macros. O arquivo é procurado no diretório padrão de includes
do compilador. Deve-se incluir o arquivo apropriado sempre que for utilizada alguma função própria da linguagem.

Alguns dos principais .h do C:

Arquivo Descrição
stdio.h Funções de entrada e saída (I/O)
string.h Funções de tratamento de strings
math.h Funções matemáticas
ctype.h Funções de teste e tratamento de caracteres
stdlib.h Funções de uso genérico

#include "arquivo.ext"

Usado para incluir arquivos criados pelo próprio programador. Geralmente arquivos .c com declaração de funções.
O arquivo é procurado no diretório atual.

Variáveis

Toda a variável deve ser definida antes de ser usada como sendo de um tipo. O tipo vai definir o tamanho em bytes
da variável e o intervalo de valores que ela poderá armazenar. O nome da variável poderá ter até 32 caracteres, sendo
que o primeiro deverá ser letra ou _ e os demais caracteres podem ser letras, números ou _. Todas as variáveis
devem ser declaradas antes de qualquer comando executável na função.

Um programa pode ter variáveis globais, que são definidas fora de qualquer função e podem ser referenciadas em
qualquer uma delas, ou variáveis locais que são declaradas internamente a uma função, sendo visível apenas na
função em que foi declarada. Funções distintas podem ter variáveis locais com o mesmo nome. Se uma função
declarar uma variável com o mesmo nome de uma variável global, a prioridade é da variável local.

Tipos de Dados
Existem 4 tipos básicos que podem ser utilizados para a declaração de variáveis:

Tipo Descrição
char Armazena um único caracter ou números inteiro pequeno
int Números inteiros (sem casas decimais)
float Números em ponto flutuante (com casas decimais) com precisão simples
double Números em ponto flutuante (com casas decimais) com precisão dupla
Linguagem C 5 Prof. Marcos José Brusso

Modificadores de Tipo
Os modificadores de tipo servem para definir as características da variável sendo declarada quanto ao seu tamanho
em bytes e forma de representação dos valores (inteiros sem sinal ou com sinal em complemento de 2).

Quanto ao sinal (podem ser usados com char ou int):

Modificador Descrição
signed A variável pode receber valores negativos ou positivos. Padrão.
unsigned A variável somente pode receber valores positivos.

Quanto ao tamanho (podem ser usados com int.):

Modificador Descrição
short Formato curto (2 bytes). Padrão para compiladores de 16 bits
long Formato longo (4 bytes). Padrão para compiladores de 32 bits.

Tipo Bytes Intervalo Casas Decimais


unsigned char 1 0 a 255 0
signed char 1 -128 a 127 0
unsigned short int 2 0 a 65535 0
signed short int 2 -32768 a 32767 0
unsigned long int 4 0 a 4294967295 0
signed long int 4 -2147483648 a +2147483647 0
float 4 3.4E-38 a 3.4E+38 7
double 8 1.7E-308 a 1.7E+308 15
long double 10 3.4E-4932 a 1.1E+4932 17
void - Nenhum valor -

O tipo padrão (default) em C é int, por isso sempre que a declaração tiver apenas modificadores é assumido o tipo
int. Por exemplo, long é equivalente a signed long int. Toda a função sem tipo declarado é assumida como
sendo int.

A inicialização de uma variável pode ser feita com uma constante, expressão ou função.

int var1=10, var2=var1*5, var3=abs(var2);

Na falta de inicialização explícita, variáveis globais são inicializadas automaticamente com zero. Variáveis locais
tem valor indefinido (lixo) quando não inicializadas na declaração.
Linguagem C 6 Prof. Marcos José Brusso

Literais
Os literais são usados para especificar valores constantes dentro de programas. A linguagem C possibilita uma
grande variedade na codificação destes valores, seja quanto a base numérica utilizada ou quanto ao tamanho e
formato utilizado para seu armazenamento.

Formato Codificação Exemplo


Decimal Números sem 0 inicial 10
Octal Prefixo 0 010
Hexadecimal Prefixo 0x 0xFF
Ponto Flutuante iiii.ddd 3.14159265
Caracter Um caractere entre ' ' ou seu código ASCII 'A' , 65
String Sequência de caracteres entre " " "Computação"

Caracteres de Escape

Os caracteres de escape são usados para representar alguns caracteres que, ou não estão disponíveis diretamente no
teclado do computador ou em determinadas situação não podem ser inseridos diretamente dentro de um programa
fonte C. Outra vantagem do uso desta forma codificada é que a portabilidade do programa é garantida. Estes
caracteres podem aparecer tanto dentro de literais do tipo caracter como string.

Caracter Descrição
\a Campainha ou Bell
\b Retrocesso ou Backspace
\n Alimentação de Linha
\r Retorno do Carro
\t Tabulação Horizontal (TAB)
\' Aspa Simples
\" Aspa Dupla
\\ Contrabarra
\0 Caracter Nulo (ASCII 0)
Linguagem C 7 Prof. Marcos José Brusso

Vetores e Matrizes

Todos os vetores em C começam com o índice 0 e não é verificado limite para um vetor. Vetores em C são
freqüentemente chamados de arranjo.

int ivetor[10]; /* declara um vetor de 10 elementos do tipo int */


float fmatriz[2][5]; /* matriz de 2 linhas com 5 colunas tipo float */

Strings em C são simplesmente vetores de caracteres. Toda string deve ser finalizada pelo caracter '\0'. String entre
aspas duplas ("") o C coloca automaticamente \0 no final.

Vetores podem ser inicializados na declaração. Neste caso a declaração do tamanho é opcional, pois o compilador
pode calcular. Para a inicialização de vetores, se coloca os valores entre {}. Para strings usa-se um literal entre "".

int vetor[5] = {2,4,6,8,10};


int matriz[3][3] = {{2,15,0},{33,4,900},{-1,12,50}};
char nome[]= {'C','O','M','P','U','T','A','C','A','O','\0'};
char texto[10]="exemplo";

Escrevendo Valores
A Função printf()

A função printf é uma função da biblioteca padrão C que escreve valores. Ela pode receber diversos parâmetros,
sendo que o primeiro deverá ser uma string. Cada especificador de formato encontrado nesta string é substituído pelo
parâmetro seguinte na lista de argumentos. Tudo o que aparecer nesta string que não for um especificador de formato
será impresso literalmente. A função printf está definida em stdio.h.

Especificadores de Formato

Formato Descrição
%d Número decimal
%ld Número decimal longo
%o Notação octal sem sinal
%x Hexadecimal sem sinal
%u Decimal sem sinal
%c Um único caracter
%s String
%f Ponto flutuante
%% Imprime um %

Pode-se especificar o tamanho do campo a ser impresso, colocando um número entre o % e o caracter de formato.
Por exemplo %5d indica que o valor a ser impresso vai ocupa 5 posições na tela. As posições em excesso são
preenchidas com brancos. Por padrão o valor é alinhado a direita do campo. Se o tamanho do campo for precedido
por - (menos), então é alinhado à esquerda. Se for colocado um 0 em frente ao tamanho o campo é preenchido com
zeros. Sempre que o tamanho do campo for insuficiente para exibir o valor solicitado, o tamanho é ignorado. Assim
um valor nunca é truncado.

Pode-se usar dois números separados por ponto. Para valores numéricos a primeira parte indica o tamanho do
campo, e a segunda parte o número de casas decimais. O tamanho do campo inclui as casas decimais e o ponto. Para
Linguagem C 8 Prof. Marcos José Brusso

strings a primeira parte indica o tamanho do campo e a segunda o número máximo de caracteres da string a
imprimir.

/* prog004.c */
#include <stdio.h>
#include <conio.h>

void main(void)
{
char val_c = 'A';
int val_i = 100;
double val_d = 50.5;
char frase[]="COMPUTACAO";

clrscr();
printf("[%c] [%c] [%d]\n",val_c, val_c+1 ,val_c);
printf("[%d] [%5d] [%-5d] [%05d]\n",val_i, val_i, val_i, val_i);
printf("[%5.2f]\n",val_d);
printf("[%15s]\n", frase);
printf("[%-15s]\n", frase);
printf("[%3.4s]\n", frase);
printf("[%15.3s]\n", frase);
printf("[%-15.3s]\n", frase);
}

Lendo Valores
Para a entrada de dados (leitura de valores) em C, pode-se usar diversas funções, dependendo do tipo da variavel que
vai ser lida.

Função getche()
Usada para a entrada de variáveis char, lê um caracter e exibe na tela o caracter digitado. Está definida em conio.h

letra = getche();

Função getch()
Usada para a entrada de variáveis char, lê um caracter e não exibe na tela o caracter digitado (entrada invisível).
Está definida em conio.h

letra = getch();
Linguagem C 9 Prof. Marcos José Brusso

Função scanf()
Deve ser utilizada para a entrada de variáveis numéricas (int, float e double). O mode de utilizar é semelhante à
função printf, porém colocar obrigatóriamente o símbolo & em frente ao nome da variável sendo lida. Está definida
em stdio.h

scanf("%d", &varint);

Com a função scanf deve-se utilizar os seguintes especificadores de formato:

Formato Tipo
%d int
%ld long int
%u unsigned int
%f float
%lf double

Função gets()
Usada para a entrada de string. Está definida em stdio.h

gets(nome);

/* prog005.c */
#include <stdio.h>
#include <conio.h>

void main(void)
{
char varc;
int vari;
float varf;
char nome[80];

clrscr();
printf("Digite seu nome: ");
gets(nome);
printf("Digite um numero inteiro: ");
scanf("%d", &vari);
printf("Digite um numero real: ");
scanf("%f", &varf);
printf("Digite um caracter: ");
varc = getche();
printf("\n%s, voce digitou %d, %f e %c", nome, vari, varf, varc);
getch();
}
Linguagem C 10 Prof. Marcos José Brusso

Operações Aritméticas
Operações aritméticas com diferentes tipos de dados são permitidas em C. Todo char é convertido para int antes de
efetuar uma operação e todo float é convertido para double. O tipo de dado resultante de uma operação é igual ao
tipo de dado de maior intervalo entre seus operadores.

Por exemplo, operação entre int e long o resultado é long e operação entre double e char o resultado é double.

Dentro de uma operação complexa, cada operação é tratada em separado, podendo afetar o resultado final. No
exemplo a seguir, o valor exibido é 3.5, e não 4.0 como seria esperado. Isto porque na divisão entre operandos
inteiros o resultado resulta em um valor inteiro. Portanto 5/2 é igual a 2 e não 2.5.

/* prog006.c */
#include <stdio.h>

void main(void)
{
int dividendo=5,divisor=2;
float resultado=0.0;

resultado = (dividendo/divisor)+1.5;
printf("Resultado: %5.1f\n",resultado);
}

Operadores Aritméticos
Realizam as operações aritméticas normais sobre os seus operandos. Podem ser utilizados com qualquer tipo de
dados, exceto o resto da divisão, o qual não pode ter operandos em ponto flutuante.

Operador Função
= Atribuição
+ Soma
- Subtração
* Multiplicação
/ Divisão (se os dois valores forem int, o resultado não terá casas decimais)
% Resto da Divisão
++ Incremento pré ou pós-fixado
-- Decremento pré ou pós-fixado

/* prog007.c */
#include <stdio.h>

void main(void)
{
int n1,n2,n3;

n1=n2=n3=1;
n2= ++n1;
n3= n2++;
printf("%d %d %d", n1, n2, --n3);
}
Linguagem C 11 Prof. Marcos José Brusso

Operadores Combinados
Sempre que em um programa C aparece uma expressão como a seguinte:
operando1 = operando1 op operando2;
onde o resultado da operação está sendo atribuída para o seu primeiro operando, esta expressão pode ser
simplificada para a seguinte forma:
operando1 op= operando2;

Expressão Normal Expressão Simplificada


a = a + b; a+=b;
a = a - b; a-=b;
a = a * b; a*=b;
a = a / b; a/=b;

Operadores Relacionais
Os operadores relacionais são utilizados em expressões condicionais para comparar o valor de duas expressões.

Operador Função
> Maior que
>= Maior ou Igual à
< Menor que
>= Menor ou igual à
== Igual à
!= Diferente de

Operadores Lógicos
Os operadores lógicos são utilizados para conectar expressões lógicas sendo geralmente utilizados em expressões
condicionais.

Operador Função
&& AND lógico
|| OR lógico
! NOT lógico

Operador Ternário

Sintaxe:
(exp1)?exp2:exp3

A expressão exp1 é avaliada, se for verdadeira o conjunto assume o valor da expressão exp2 senão assume o valor
da expressão exp3.
Linguagem C 12 Prof. Marcos José Brusso

/* prog008.c */
#include <stdio.h>

void main(void)
{
int n1=5, n2=20, maior;

maior = (n1>n2)?n1:n2;
printf("%03d",maior);
printf("O maior e' %s", (maior==n1)?"N1":"N2");
}

Operador sizeof

Sintaxe:
sizeof(expressão) ou sizeof(tipo)

Este operador retorna o tamanho em bytes ocupados pela expressão ou tipo. O tamanho de uma variável não depende
do seu conteúdo, mas apenas do tipo que ela foi declarada. O tamanho de um vetor é igual a soma do tamanho de
seus elementos.

int n, s;
s = sizeof(n);
n = sizeof(float);

Moldagem ou Cast

Sintaxe:
(tipo) expressão

Força a expressão a assumir um determinado tipo. Não altera o tipo da variável, apenas converte o valor naquele
ponto do programa.

/* prog009.c */
#include <stdio.h>

void main(void)
{
int dividendo=5,divisor=2;
float resultado=0.0;

resultado = ((float)dividendo/divisor)+1.5;
printf("Resultado: %5.2f\n",resultado);
}

Comando if

Sintaxe:
if(condição)
comando1;
else
comando2;

Se condição for verdadeira (diferente de 0) é executado comando1, senão é executado comando2. Quando mais de
um comando for utilizado, devem estar agrupados entre { e }.O else, que é opcional, eqüivale sempre ao último if
Linguagem C 13 Prof. Marcos José Brusso

pendente (sem else).

/* prog010.c */
#include <stdio.h>
#include <conio.h>

void main(void)
{
int num;

clrscr();
printf("Digite um numero: ");
scanf("%d", &num);
if(num%2==0){
printf("%d e' par\n", num);
printf("A metade e' %d", num/2);
}
else
printf("%d e' impar", num);
getch();
}

Comando do while

Sintaxe:
do
comando;
while(condição);

Executa o comando enquanto a condição for verdadeira. Como a condição é avaliada no final de cada passagem, o
comando é executado pelo menos uma vez.

/* prog011.c */
#include <stdio.h>
#include <conio.h>

void main(void)
{
int soma = 0, i=10, final=15;

clrscr();
do{
soma += i;
i++;
}while(i<=final);

printf("Soma dos numeros entre [10 e 15] = %d\n", soma);


getch();
}
Linguagem C 14 Prof. Marcos José Brusso

Comando while

Sintaxe:
while(condição)
comando;

Executa o comando enquanto a condição for verdadeira. Como a condição é avaliada no início de cada passagem, o
comando não será executado nenhuma vez se, ao entrar neste laço, a condição for falsa.

/* prog012.c */
#include <stdio.h>

void main(void)
{
int n1=5, n2=3, produto=0;

/* Multiplica dois inteiros positivos por somas sucessivas */


while(n2>0){
produto+=n1;
n2--;
}
printf("5 x 3 = %d\n", produto);
}

Pode-se utilizar os seguintes comandos dentro de um laço para controlar a sua execução:

continue; Salta o restante do laço e testa novamente a condição.


break; Finaliza o laço atual, pulando para o primeiro comando após o final deste.

/* prog012b.c */
#include <stdio.h>
#include <conio.h>

void main(void)
{
int num, i=0, vet[5];

clrscr();
printf("Digite 5 numeros entre 1 e 100 (0 para parar)\n");
while(i<5){
printf("%d> ", i+1);
scanf("%d", &num);
if(num==0)
break;
if(num<0 || num > 100){
printf("Redigite...\n");
continue;
}
vet[i] = num;
i++;
}
}
Linguagem C 15 Prof. Marcos José Brusso

Comando for

Sintaxe:
for(exp1;exp2;exp3)
comandos;

Define um laço for-next onde exp1é a expressão executada antes de entrar no laço. Usado geralmente para atribuir
um valor inicial para a variável de controle do laço. A expressão exp2 é avaliada no inicio de cada iteração, sendo
que o laço será executado enquanto exp2 for verdadeira. Ao final de cada passagem, exp3 é executada. Normalmente
usa-se para incrementar (ou decrementar a variável de controle).

Para exp1 e exp3 pode-se usar mais de uma expressão separadas por vírgula. Qualquer uma das partes do comando
é opcional. Se exp2 for omitida o laço é executado indefinidamente (laço infinito).

/*
prog013.c
Exibe o conteudo de um vetor, a soma e a media seus elementos
*/

#include <stdio.h>
#include <conio.h>

void main(void)
{
int i, vetor[6]={12,3,1,2,10,9};
long soma;
float media;
clrscr();
for(soma=0,i=0;i<6;i++){
printf("vetor[%d]: %d\n", i , vetor[i]);
soma += vetor[i];
}
media = soma/6.0;
printf("Soma: %ld\nMedia: %f", soma, media);
getch();
}

Diretiva #define

Sintaxe:
#define nome valor

Substitui toda a ocorrência de nome no programa-fonte por valor. É a chamada substituição de macro. Por
convenção todo o nome de macro é escrito em letras maiúsculas.

#define PI 3.14159265358979323846

Uma macro pode conter argumentos, que são substituidos na ordem em que aparecem, independente de seu nome.
Por exemplo:

#define dobro(a) (a*2)


#define maior(x,y) ((x>y)?x:y)

Se for necessário mais de uma linha para um define deve-se colocar uma contrabarra \ no final da linha.
Linguagem C 16 Prof. Marcos José Brusso

/* prog015.c */
#include <stdio.h>

#define TAMANHO 10
#define odd(n) (n%2!=0)
#define quadrado(n) (n*n)
#define cubo(n) (n*n*n)

void main(void)
{
int vetor[TAMANHO],i;

for(i=0;i<TAMANHO;i++){
if(odd(i))
vetor[i]=quadrado(i);
else
vetor[i]=cubo(i);

printf("%02d\n",vetor[i]);
}
}

Declaração de Funções
A declaração completa de uma função em C segue a seguinte sintaxe:

tipo nome_da_funcao(lista de argumentos)


{
declaração das variáveis locais;

corpo da função;
return(valor); /* Somente se a função não for void */
}

O tipo padrão de função é int. Se a função não retornar valor ela deve ser declarada com sendo do tipo void. Deve-se
declarar toda a função que não for int antes de usar (pode-se somente declarar, não é necessário escrevê-la).O valor
retornado deve ser sempre do mesmo tipo da função, e é passado para a função chamadora. Os parâmetros da função
são variáveis locais inicializadas com os valores passados na posição correspondente no momento da sua chamada.

/* prog016.c */
#include <stdio.h>
#include <conio.h>

long fatorial(int x);

void main(void)
{
int num;
long resultado;

clrscr();
printf("Digite um Numero: ");
scanf("%d", &num);
resultado = fatorial(num);
printf("O Fatorial de %d e' %ld\n",num, resultado);
getch();
}
Linguagem C 17 Prof. Marcos José Brusso

long fatorial(int x)
{
long temp=1;

while(x>1){
temp*=x;
x--;
}
return(temp);
}

Ponteiros

Por padrão, toda variável C é declarada para armazenar um valor: variáveis int servem para armazenar valores
inteiros, float para armazenar valores numéricos com precisão simples, etc... Toda a vez que o nome de uma variável
é inserido em um programa, está se fazendo referência ao seu valor, ou seja, o conteúdo daquela variável.

Existe um tipo especial de variável em C que ao invés de conter valores, armazena endereços de memória: São os
ponteiros.

Declarações de ponteiros são precedidas do símbolo * (asterísco), como no exemplo:


long *var;
onde é declarada uma variável var, que pode conter qualquer endereço de memória onde esta armazenado um inteiro
longo.

Variáveis ponteiro não podem ser usadas antes de serem inicializadas, isto é, enquanto não apontarem para um
endereço de memória válido. Para inicializar uma variável ponteiro podemos atribuir o endereço de outra variável ou
então alocar memória dinamicamente para ela.

Para trabalhar com ponteiros utilizamos 2 operadores unários especiais:

Operador Função
& (Endereço de) Fornece o endereço de memória onde está armazenada uma variável.
* (Valor apontado por) Valor armazenado na variável referenciada por um ponteiro.

/* prog017.c */
#include <stdio.h>

void main(void)
{
int variavel, *ponteiro;

variavel = 10;
ponteiro = &variavel;
printf("\n%d %d", variavel, *ponteiro);
*ponteiro = 50;
printf("\n%d %d", variavel, *ponteiro);
}

Operações com Ponteiros


Pode-se fazer somas e subtrações com um ponteiro. Incrementar um ponteiro que aponta para um elemento de um
vetor fará com que ele passe a apontar para o próximo elemento, e decrementá-lo fará com que ele aponte para o
elemento anterior. Ponteiros void podem apontar para qualquer tipo de dado, mas não se pode fazer operações com
ponteiros este tipo de ponteiro, nem mesmo referência indireta.
Linguagem C 18 Prof. Marcos José Brusso

void *buffer;

Um ponteiro, após inicializado, pode ser usado como se fosse um vetor do tipo de dados que foi declarado. Sempre
que um vetor aparece em um programa sem um subscrito (índice), apenas o nome, é assumido o endereço do
primeiro elemento deste vetor.

/* prog018.c */
#include <stdio.h>
#include <conio.h>

void main(void)
{
char frase[]="teste";
char *p;
int i;

clrscr();
printf("%s\n",frase);
p=frase; /* Mesmo que ponteiro=&nome[0]; */
printf("Usando o indice\n");
for(i=0; p[i]!='\0'; i++)
printf("%c\n",p[i]);
printf("Incrementando o ponteiro\n");
while(*p!='\0'){
printf("%c\n", *p);
p++;
}
}

Passagem de Parâmetros por Valor

Por padrão, os parâmetros são passados para as funções por valor, isto é, apenas uma cópia do valor do argumento é
passado para a função chamada e se esta função alterar o valor recebido, esta modificação não afetará a variável
usada por quem chamou.

/* prog019.c */
# include <stdio.h>
void dobro(int valor);

void main(void)
{
int num=3;

printf("%d\n",num);
dobro(num);
printf("%d\n",num);
}

void dobro(int valor)


{
valor = valor*2;
printf("%d\n",valor);
}
Linguagem C 19 Prof. Marcos José Brusso

Passagem de Parâmetros por Referência


Se no lugar de passar o valor de uma variável, for passado o seu endereço de memória como argumento de uma
função, qualquer alteração feita usando referência indireta irá modificar o valor da variável na função chamadora.
Isto é passagem de parâmetro por referência. Para passarmos o endereço de uma variável, o parâmetro deve ser
declarado como um ponteiro.

/* prog020.c */
# include <stdio.h>
void dobro(int *ref);

void main(void)
{
int num=3;

printf("%d\n",num);
dobro(&num);
printf("%d\n",num);
}

void dobro(int *ref)


{
*ref= *ref * 2;
printf("%d\n", *ref);
}

Funções e Vetores
Vetores obrigatóriamente devem ser passados como parâmetro por referência. É então passado o endereço do
primeiro elemento do vetor. Uma função não pode retornar um vetor, mas pode retornar um ponteiro para este.

/* prog021.c */
# include <stdio.h>

char *troca(char *str, int atual, int novo);

void main(void)
{
char nome[80]="exemplo";

printf("%s\n", nome);
printf("%s\n", troca(nome,'e','a'));
printf("%s\n", nome);
}

char *troca(char *str, int atual, int novo)


{
int i;

for(i=0;str[i]!='\0';i++){
if(str[i]==atual)
str[i]=novo;
}
return(str);
}
Linguagem C 20 Prof. Marcos José Brusso

Alocação Dinâmica de Memória


Pode-se alocar, isto é, reservar áreas de memória dinamicamente durante a execução de um programa e atribuir o
endereço alocado para um ponteiro. Isto é útil quando não se conhece o tamanho necessário para um vetor em tempo
de compilação ou quando se quer criar ou destruir variáveis em qualquer parte do programa. As funções para
alocação de memória estão definidas em stdlib.h.

void *malloc(unsigned tamanho)


Aloca memória (tamanho em bytes) e retorna um ponteiro para a memória alocada.
Retorna NULL se não existir memória disponível suficiente.

void *realloc(void *prt, unsigned tamanho)


Altera o tamanho da área alocada por malloc(). Se o bloco não puder ser realocado retorna NULL.

void free(void *ptr)


Libera a memória alocada por malloc().

/* prog022.c */
#include <stdlib.h>
#include <stdio.h>

void main(void)
{
int *vetor, num;
int i;
long soma=0;

printf("Numero de elementos do vetor:");


scanf("%d", &num);
vetor = malloc(num*sizeof(int));

if(vetor==NULL){
printf("Sem Memoria!\a\n");
return;
}

for(i=0;i<num;i++){
printf("Informe vetor[%d]:", i);
scanf("%d", &vetor[i]);
soma += vetor[i];
}

printf("Total: %ld", soma);


free(vetor);
}

Funções de Manipulação de Strings

Alguns cuidados devem ser tomados ao se lidar com strings em C. Por serem vetores char, as strings estão sujeitas a
todas as regras pertinentes aos vetores normais. Todas as strings devem ser passadas por referência para funções,
uma função não pode retornar uma strings, mas pode retornar o endereço de uma string (char *) e o C não faz
verificação de limite para vetores.

Outras limitações decorrentes e muito importantes são as seguintes:

1. Strings não podem ser atribuídas com o operador de atribuição = (embora possam ser inicializadas)
2. Strings não podem ser comparadas com o operador de comparação ==

Para contornar estes problemas pode-se usar algumas funções da biblioteca padrão C, definidas em string.h
Linguagem C 21 Prof. Marcos José Brusso

char *strcpy(char *destino, char *origem)


Copia uma string em outra (origem para destino). Retorna destino.
Ex: strcpy(nome,"computação");

char *strncpy(char *destino, char *origem, unsigned n)


Copia no máximo n caracteres de origem para destino. Não coloca \0 no final de destino. Retorna destino.
Ex: strcpy(nome,"computação",3); /* copia "com" */

int strcmp(char *s1, char *s2)


Compara s1 com s2. Retorna < 0 se s1 < s2, 0 se s1==s2 ou >0 se s1>s2.
Ex: if(strcmp(opcao,"FIM")==0) return;

int strncmp(char *s1, char *s2, unsigned num)


Compara no máximo num caracteres de s1 com s2.
Retorna < 0 se s1 < s2, 0 se s1==s2 ou >0 se s1>s2.
Ex: if(strncmp(endereco,"http",4)==0) flag = 1;

char *strcat(char *destino, char *origem)


Concatena origem a destino. Retorna destino. Destino deve ter tamanho suficiente para receber a string
concatenada.
Ex: strcat(cidade," - RS");

unsigned strlen(char *string)


Retorna o número de caracteres da string, sem contar o '\0'.
Ex: strcpy(nome,"COMPUTACAO");
printf("%d",strlen(nome)); /* 10 */

Funções de Tratamento de Caracteres


A biblioteca padrão da linguagem C provêm um conjunto de funções para teste e conversão de caracteres. Estas
funções estão definidas em ctype.h.

int isalnum(int caracter)


Retorna verdadeiro se caracter é letra ou número.

int isalpha(int caracter)


Retorna verdadeiro se caracter é uma letra.

int isdigit(int caracter)


Retorna verdadeiro se caracter é um número ('0'..'9').

int islower(int caracter)


Retorna verdadeiro se caracter é letra minúscula.

int isupper(int caracter)


Retorna verdadeiro se caracter é letra maiúscula.

int isspace(int caracter)


Retorna verdadeiro se caracter é espaço (' ').

int tolower(int caracter)


Se caracter for letra, retorna-o convertido para minúsculo, senão retorna o próprio caracter.

int toupper(int caracter)


Se caracter for letra, retorna-o convertido para maiúsculo, senão retorna o próprio caracter.
Linguagem C 22 Prof. Marcos José Brusso

/* prog023.c */

#include <ctype.h>
#include <stdio.h>

void nomeproprio(char *destino, char *origem);

void main(void)
{
char nome[80], temp[80];

printf("Digite um Nome:");
gets(nome);
nomeproprio(temp, nome);
printf("Original:[%s] \nAlterado:[%s]", nome, temp);
}

void nomeproprio(char *destino, char *origem)


{
int i;
char ant=' ';

for(i=0; origem[i]!='\0'; i++){


destino[i] = (ant==' ')?toupper(origem[i]):tolower(origem[i]);
ant = origem[i];
}
destino[i] = '\0';
}

Argumentos de Linha de Comando


Os programas escritos em C podem receber parâmetros a partir da linha de comando. Um exemplo de uso de
argumento para programa é o comando DIR, que pode receber nenhum, um ou mais parâmetros:

DIR
DIR *.C
DIR A: /S /W

Este argumentos são utilizados com muita freqüencia no sistema operacional Unix e suas variantes, como Linux,
onde praticamente todos os programas aceitam argumentos, que servem para informar ao programa o que o usuário
deseja que ele faça.

ls
ls *.C
ls -l *.c

Para acessar os parâmetros passados a partir do sistema operacional deve-se definir 2 argumentos para a função
main().O primeiro é um inteiro (geralmente chamado de argc), que irá conter o numero de parâmetros passados. O
segundo parâmetro (argv), é um vetor de strings (ponteiros para char) que contêm cada um dos argumentos
passados.Como argv[0] contêm o nome do programa, então argc é sempre pelo menos igual a 1.
Linguagem C 23 Prof. Marcos José Brusso

/* prog024.c */
#include <stdio.h>
#include <string.h>
#define TAMANHO 10

void main(int argc, char **argv)


{
int vetor[TAMANHO]={5,2,8,10,1,12,9,5,4,6};
int mostra_soma=0, mostra_media=0, i;
long soma=0;
float media=0.0;

for(i=1;i<argc;i++){
if(strcmp(argv[i], "-s")==0 || strcmp(argv[i], "-S")==0)
mostra_soma=1;
else
if(strcmp(argv[i], "-m")==0 || strcmp(argv[i], "-M")==0)
mostra_media=1;
else{
printf("Argumento %s invalido\a", argv[i]);
return;
}
}

for(i=0; i<TAMANHO; i++){


printf("vetor[%d]=%d\n", i, vetor[i]);
soma += vetor[i];
}
if(mostra_soma)
printf("Soma: %ld\n", soma);
if(mostra_media){
media = (float)soma/TAMANHO;
printf("Media: %f\n", media);
}
}

Estruturas

Sintaxe:
struct etiqueta_da_estrutura {
tipo membro_1;
tipo membro_2;
tipo membro_n;
};

Estrutura é o conjunto de uma ou mais variáveis colocadas sob um nome único. Estrutura implementa em C a idéia
de registro.

struct data{
int dia;
int mes;
int ano;
};

Para acessar um membro da estrutura deve-se usar o operador . (ponto), unindo o nome da variável de estrutura com
o nome do campo (ou membro).
Linguagem C 24 Prof. Marcos José Brusso

struct data nascimento;


nascimento.dia = 10;

O tamanho total de uma estrutura é igual a soma do tamanho de seus itens. Estruturas podem ser aninhadas, isto é,
estruturas podem fazer parte de outras estruturas.Pode-se criar vetores de estruturas e estruturas podem ser
inicializadas na declaração.

/* prog025.c */
#include <conio.h>
#include <stdio.h>
#include <string.h>
#define TAMANHO 4

struct data{
int dia, mes, ano;
};

struct aluno{
int matricula;
char nome[30];
struct data nascimento;
};

void main(void)
{
struct aluno turma[TAMANHO] = {
{9991, "Fulano", {10,5,1965}},
{9992, "Cicrano", {23,8,1977}},
{9993, "Beltrano", {14,1,1970}},
{9994, "Individuo", {2,10,1969}},
};
int i, achou;
int quem;
char escolha;

do{
clrscr();
printf("Matricula: ");
scanf("%d", &quem);
achou = 0;
for(i=0; i<TAMANHO; i++)
if(quem==turma[i].matricula){
printf("Nome: %s\n", turma[i].nome);
printf("Nascimento: %02d/%02d/%04d\n",
turma[i].nascimento.dia,
turma[i].nascimento.mes,
turma[i].nascimento.ano);
achou = 1;
break;
}
if(!achou)
printf("Nao Encontrado\n");
printf("\nContinuar? [S/N]");
escolha=getche();
}while(escolha=='s' || escolha=='S');
}
Linguagem C 25 Prof. Marcos José Brusso

Ponteiros para estruturas

Pode ser criados ponteiros para estruturas como no exemplo:


struct data *ptr_data;

Para acessar o membro de uma estrutura através de um ponteiro usa-se o operador -> (seta). Neste caso, o ponteiro
deve estar, obrigatoriamente, apontando para uma variável de estrutura do mesmo tipo do ponteiro.
ptr_data->dia = 10;

Estruturas não podem ser passadas por valor para funções, deve-se passar um ponteiro para a estrutura. Também
não podemos retornar uma struct em uma função mas pode-se retornar o endereço da estrutura.

/* prog026.c */
#include<stdio.h>
#include<conio.h>

struct data{
int dia, mes, ano;
};

void exibedata(struct data *pd)


{
char *meses[12]={"Janeiro", "Fevereiro", "Marco", "Abril", "Maio",
"Junho", "Julho", "Agosto", "Setembro", "Outubro",
"Novembro", "Dezembro"};

printf("%02d de %s de %04d", pd->dia, meses[pd->mes-1], pd->ano);


}

void main(void)
{
struct data dt1;

clrscr();
printf("Informe uma data:");
scanf("%d/%d/%d", &dt1.dia, &dt1.mes, &dt1.ano);
exibedata(&dt1);
getch();
}
Linguagem C 26 Prof. Marcos José Brusso

Funções de Entrada e Saída em Arquivos Sequenciais

O tipo FILE, definido em <stdio.h> é uma definição de estrutura usado pelas funções de acesso a arquivos com
buffer em C.

FILE *fopen(char *nome_do_arquivo,char *modo_de_abertura)


Abre o arquivo e retorna um ponteiro para a estrutura do arquivo aberto, ou NULL em caso de erro.

A string modo_de_abertura pode conter alguns dos seguintes caracteres:

Caracter Finalidade
"r" Abre para leitura
"w" Cria um novo arquivo para escrita. Se já existe é eliminado e recriado.
"a" Abre para escrita no final do arquivo (append).
"+" Em conjunto com "r" permite acesso de leitura e escrita (I/O).
"b" O arquivo é um arquivo binário.
"t" Arquivo texto. (Linha finalizadas com '\n' e arquivo com EOF)

Alguns arquivos são associados à dispositivos e definidos automaticamente pelo C, e podem ser usados por qualquer
programa:

Arquivo Descrição
stdin Dispositivo de entrada padrão (geralmente teclado)
stdout Dispositivo de saída padrão (geralmente o vídeo)
stderr Dispositivo de saída de erros (sempre o vídeo)

int fprintf(FILE *arquivo,char *formato,...)


Semelhante a printf(), mas pode-se especificar o arquivo de saída.

int fclose(FILE *arquivo)


Fecha o arquivo. Retorna 0 se OK ou EOF se algum erro ocorreu.

int fgetc(FILE *arquivo)


Lê um caracter do arquivo. Retorna o caracter lido ou EOF no final do arquivo ou em caso de erro.

int fputc(int caracter, FILE *arquivo)


Escreve um caracter no arquivo. Retorna o caracter gravado ou EOF em caso de erro.
Linguagem C 27 Prof. Marcos José Brusso

/* prog028.c */
#include <stdio.h>
#include <stdlib.h>

void main(int argc, char *argv[])


{
FILE *origem,*destino;
int temp;
if(argc!=3){
fprintf(stderr, "Numero de parametros incorreto\a");
exit(1);
}
if((origem=fopen(argv[1],"rb"))==NULL){
fprintf(stderr, "Nao consegui abrir %s",argv[1]);
exit(1);
}
if((destino=fopen(argv[2],"wb"))==NULL){
fprintf(stderr, "Nao consegui abrir %s",argv[2]);
exit(1);
}
do{
temp=fgetc(origem);
if(temp==EOF) break;
temp=fputc(temp,destino);
}while(temp!=EOF);
fclose(origem);
fclose(destino);
}

char *fgets(char *linha, int tamanho, FILE *arquivo)


Lê uma linha de texto de um arquivo. retorna um ponteiro para a string lida ou NULL em caso de erro ou final de
arquivo. O parâmetro tamanho limita o numero máximo de bytes que se quer ler por linha(tamanho-1). Se a linha
no arquivo for maior que tamanho, lê apenas a parte inicial. O restante será lido na próxima chamada à fgets().

int fputs(char *linha,FILE *arquivo)


Escreve uma string em um arquivo. Retorna o último caracter gravado ou EOF em caso de erro.

/* prog029.c */
#include <stdio.h>
#include <stdlib.h>

void main(int argc, char *argv[])


{
FILE *arq;
char linha[255];
if(argc!=2){
fprintf(stderr, "Numero de parametros incorreto\a");
exit(1);
}
if((arq=fopen(argv[1],"rt"))==NULL){
fprintf(stderr, "Nao consegui abrir %s",argv[1]);
exit(1);
}
while(fgets(linha,sizeof(linha),arq)!=NULL)
printf("%s",linha);
fclose(arq);
}
Linguagem C 28 Prof. Marcos José Brusso

Funções de Entrada e Saída Aleatória em Arquivos

Para acesso randômico a arquivos, é mantido um cursor que indica a posição do arquivo a partir do qual será feita a
próxima leitura/escrita no arquivo. Cada vez que se lê/escreve n bytes no arquivo este cursor é incrementado em n.

int fread(void *buffer, int tamanho, int num, FILE *arquivo)


Lê bytes de um arquivo e armazena-os na posição de memória apontada por buffer. A função retorna o número de
itens realmente lidos e avança o cursor de arquivo tamanho*num bytes.

Parâmetro Descrição
buffer Ponteiro para uma área de memória onde serão armazenados os dados lidos do arquivo.
tamanho Numero de bytes a ler. Geralmente sizeof(buffer).
num Numero de itens a ler. Geralmente 1.
arquivo Ponteiro FILE para um arquivo aberto anteriormente por fopen().

int fwrite(void *buffer, int tamanho, int num, FILE *arquivo)


Escreve bytes em um arquivo. A função retorna o número de itens realmente gravados e avança o cursor
tamanho*num bytes. Se o cursor estiver apontando a uma área já gravada do arquivo, então os novos dados irão
sobrescrever os anteriores. Se estiver apontando para o final do arquivo então os os novos dados serão anexados.

Parâmetro Descrição
buffer Ponteiro para uma área de memória onde estão armazenados os dados a serem gravados no arquivo.
tamanho Numero de bytes a gravar. Geralmente sizeof(buffer).
num Numero de itens a gravar. Geralmente 1.
arquivo Ponteiro FILE para um arquivo aberto anteriormente por fopen().

int fseek(FILE *arquivo,long deslocamento, int apartir)


Altera a posição do cursor de um arquivo. Retorna 0 se OK.

Parâmetro Descrição
arquivo Ponteiro FILE para um arquivo aberto anteriormente por fopen().
deslocamento Número de bytes a deslocar, relativos a apartir. Deve ser um inteiro positivo.
apartir Define o ponto inicial do deslocamento.

Para o parâmetro apartir, pode ser uma das seguintes macros definidas em stdio.h:

Valor Descrição
SEEK_SET Posiciona a partir do inicio do arquivo.
SEEK_CUR Relativo a posição atual.
SEEK_END Retrocede do final do arquivo.

void rewind(FILE *arquivo)


Posiciona o cursor no inicio do arquivo.É identico a fseek(arquivo,0L,SEEK_SET).

long ftell(FILE *arquivo)


Retorna o valor atual do cursor de arquivo, isto é a posição da próxima escrita ou leitura.

int feof(FILE *arquivo)


Retorna diferente de zero se foi tentado ultrapassar o final do arquivo.
#include <stdio.h>
Linguagem C 29 Prof. Marcos José Brusso

#include <conio.h>
#include <stdlib.h>

struct cidades{
int codigo;
char nome[50];
char uf[3];
};

void main(void)
{
FILE *arquivo;
struct cidades cidade;
int achou, cod_temp;

/*TENTA ABRIR PARA LEITURA/GRAVACAO*/


arquivo=fopen("cidades.dat","r+b");
if(arquivo==NULL){ /* SE NAO CONSEGUIR CRIA O ARQUIVO */
arquivo = fopen("cidades.dat","w+b");
if(arquivo==NULL){
fprintf(stderr,"Nao consegui criar o arquivo");
exit(1);
}
}
do{
clrscr();
gotoxy(10,10); printf("Codigo : ");
gotoxy(10,11); printf("Nome.. : ");
gotoxy(10,12); printf("Estado.: ");
gotoxy(19,10); scanf("%d", &cod_temp); fflush(stdin);
if(cod_temp==0) break;
/* POSICIONA NO INICIO DO ARQUIVO */
rewind(arquivo);
achou = 0;
while(fread(&cidade,sizeof(cidade),1,arquivo)==1 && !feof(arquivo))
/* LE ATE O FINAL PROCURANDO CODIGO */
if(cidade.codigo==cod_temp){
gotoxy(25,10);
printf("Codigo ja cadastrado. Tecle Algo...");
getch();
achou = 1;
break;
}
if(!achou){
cidade.codigo = cod_temp;
gotoxy(19,11); gets(cidade.nome);
gotoxy(19,12); gets(cidade.uf);
/* POSICIONA NO FINAL PARA INCLUSAO E GRAVA NOVO REGISTRO */
fseek(arquivo,0L,SEEK_END);
fwrite(&cidade,sizeof(cidade),1,arquivo);
}
}while(1);
fclose(arquivo);
}
Linguagem C 30 Prof. Marcos José Brusso

Exercícios

1) Mostrar ao lado de cada chamada à função printf o que será exibido na execução do programa. Substituir
espaços em branco por sublinhado.

#include <stdio.h>
void main(void)
{
int n1=15, n2=4;
char txt[]="ASDFGHJKL";
float vf=9.5;

printf("[%4d]", n1);
printf("[%03d]", n2);
printf("[%12s]", txt);
printf("[%c]", txt[1]);
printf("[%c]", txt[n2]);
printf("[%-6.4s]", txt);
printf("[%10.2f]", vf);
printf("%-8.1f", vf);
}

2) Mostrar ao lado de cada chamada à função printf o que será exibido na execução do programa. Substituir
espaços em branco por sublinhado.
#include <stdio.h>
void main(void)
{
int m[2][2] = {{10, 32}, {500,41}};
int v1 = 0, v2 = 1;
char str[] = "TCLITE";

printf("[%05d]", m[++v1][v2++]);
printf("[%-4d]", v2);
v1 += v2;
printf("[%04d]", v1);
printf("[%4.3s]", str);
v1 = (m[0][1]>m[1][0])? 4: 1;
printf("[%c]", str[v1]);
}

3) Escrever um programa que declara um vetor de 20 elementos inteiros, lê um valor qualquer para cada posição do
vetor e após exibe cada valor do vetor em decimal, octal e hexadecimal, um elemento do vetor por linha, em colunas
de 5 caracteres alinhadas a esquerda.

4) Escrever um programa que lê uma matriz float de 20 linhas e 20 colunas e a seguir exibe toda a coluna onde está
o menor valor da matriz. O programa deve ter pelo menos um laço do tipo do while

5) Escrever um programa que declara uma matriz float com 4 linhas e 5 colunas, lê um valor para cada posição da
matriz e no final exibe a média dos valores para cada coluna da matriz. Estes valores devem ser exibidos com 3
casas decimais.
Linguagem C 31 Prof. Marcos José Brusso

6) O seguinte programa deveria ler os valores para um vetor int de 10 elementos e no final mostrar a soma dos
valores informados. Encontre os erros no programa, corrija-os e justifique cada correção feita.

#include <stdio.h>
#include <conio.h>

void main(void);
{
int vet[10], i;
long soma=0;

clrscr;
for(i=0; i==10; i++){
printf("Digite o ", i+1, " numero: ");
scanf("%d", vet[i]);
soma+=vet[i];
}

printf("Soma dos valores digitados: %ld", soma);


}

7) Escrever um programa que declara uma matriz de 4 linhas e 3 colunas de números inteiros, lê uma valor para
cada posição da matriz e mostra os valores da matriz que são iguais ao seu índice de linha ou o seu índice de coluna.
Mostrar com seguinte formato:
Linha 0, Coluna 1 : Valor 1
Linha 2, Coluna 2 : Valor 2

8) Escrever um programa que declara três variáveis int (n1, n2 e n3), lê um valor maior que zero para cada variável
e exibe o valor da menor variável multiplicado pela maior e o valor da maior variável dividido pela menor.

9) Escrever um programa que declara um vetor de 20 inteiros, lê um valor para cada posição e no final mostra
quantos elementos possuem valor maior, menor e igual ao primeiro elemento do vetor.

10) Escrever uma função int calcula(int n1, int n2, int n3), que recebe três números inteiros
como parâmetro e retorna o maior valor passado multiplicado pelo menor.
var = calcula(10, 5, 8); /* var recebe 50 (10 * 5) */
var = calcula(0, -1, 20); /* var recebe -20 (20 * -1) */
var = calcula(5, 6, 7); /* var recebe 35 (7 * 5) */

11) Escrever uma função long somaintervalo(int n1, int n2) que retorna a soma dos número
inteiros que existem entre n1 e n2 (inclusive ambos). A função deve funcionar inclusive se o valor de n2 for menor
que n1.
n=somaintervalo(3, 6); /* n recebe 18 (3 + 4 + 5 + 6) */
n=somaintervalo(5,5); /* n recebe 10 (5 + 5) */
n=somaintervalo(-2,3); /* n recebe 3 (-2 + -1 + 0 + 1 + 2 + 3) */
n=somaintervalo(4, 0); /* n recebe 10 (4 + 3 + 2 + 1 + 0) */

12) Escrever um programa que lê quatro números inteiros (4 variáveis separadas) e exibe a média dos valores
digitados. A leitura deve ser feita na função main() e a exibição em uma função chamada calcula(). O programa não
pode ter variáveis globais.

13) Escrever um programa que lê quatro valores float e exibe o maior e o menor valor digitado. A leitura deve ser
feita em uma função chamada ler() e o resultado deve ser exibido em uma função chamada exibe(), sendo que não
pode ser declarada nenhuma variável global.
Linguagem C 32 Prof. Marcos José Brusso

14) Mostrar ao lado de cada chamada à função printf o que será exibido na execução do programa. Substituir
espaços em branco por sublinhado (_):

#include <stdio.h>
#define macro(n) (n)?n*2:n*n

void main(void)
{
int a=2, b=9, vt[3]={6,2,4};
float fv=5.0;
char txt[]="ASDFGHJKL";

printf("[%-4d]", sizeof(txt));
b=macro(vt[1]);
printf("[%04d]", b);
fv/=a;
printf("[%8.5f]", fv);
txt[--b]='X';
printf("[%8.5s]", txt);
printf("[%4d]", b);
printf("[%c]", txt[a]);
}

15) Mostrar ao lado de cada chamada à função printf o que será exibido na execução do programa. Substituir
espaços em branco por sublinhado (_):

#include <stdio.h>
void main(void)
{
int vet[5]={9,4,6,2,5};
char str[]="boa sorte";
int num=1,i=0;
int *ptr;

ptr=&num;
*ptr = vet[3];
printf("[%-5d]", num);
ptr = vet;
vet[0] = --num;
printf("[%4d]", ptr[0]);
printf("[%c]", str[num]);
num=0;
while(i<3){
num+=vet[i];
i++;
}
printf("[%03d]", num);
printf("[%5.2s]", str);
}
Linguagem C 33 Prof. Marcos José Brusso

16) Mostrar ao lado de cada chamada à função printf o que será exibido na execução do programa. Substituir
espaços em branco por sublinhado (_):

#include <stdio.h>

void main(void)
{
float vetor[]={3.5, 2.0, 4.5, 9.0};
float var=0.0;
float *p;
int x, y;

y=sizeof(vetor);
printf("[%d]", y++);
p = vetor;
x = (int) *p;
printf("[%04d]", x);
p++;
*p += y;
printf("[%8.3f]", vetor[1]);
x=0;
while(var < 15.0){
var+= vetor[x];
x++;
}
printf("[%10.1f]", var);
printf("[%-5d]", x);
}

17) Mostrar o que seria exibido após cada chamada à função printf. Substituir brancos por sublinhado.

#include <stdio.h>
void main(void)
{
char c0;
int num=5, teste=55, *ptr;
char linha[]="final";

ptr = &num;
c0 = (num/2)?'3':'9';
*ptr += sizeof(c0);
printf("[%-5d]", num);
printf("[%c]", c0);
ptr = &teste;
*ptr = -1;
printf("[%3d]", ++teste);
for(num=0, teste=1; linha[num] !='\0';num++)
teste += num;
printf("[%d]", teste);
printf("[%c]", linha[--num]);
}
Linguagem C 34 Prof. Marcos José Brusso

18) Mostrar o que seria exibido após cada chamada à função printf. Substituir brancos por sublinhado.

#include<stdio.h>
void main(void)
{
int t1=1,i=0,vet[3]={3,2,4};
int *p;
char str[]="outubro";

do{
t1 *= vet[i++];
}while(i<3);
p=&t1;
printf("[%-5d]",*p);
t1 = sizeof(str) + i;
printf("[%4d]",t1);
printf("[%c]",str[i]);
*p = 0;
printf("[%d]",vet[t1]);
printf("[%5.2s]",str);
}

19) Mostrar ao lado de cada chamada à função printf o que será exibido na execução do programa. Substituir
espaços em branco por sublinhado (_):

#include <stdio.h>
void main(void)
{
char texto[]="THINK!";
int a=10, b=2, c=0;
int *pin;
float vf=0.0;

pin = &a;
a = ++b;
printf("[%-3d]", *pin);
c = (b>2)?15:25;
printf("[%04d]", c);
pin = &b;
printf("[%-10.4s]", texto);
*pin = 1;
printf("[%c]", texto[b]);
a-=1;
vf = c/a;
printf("[%6.2f]", vf);
}
Linguagem C 35 Prof. Marcos José Brusso

20) Escrever ao lado de cada função printf deste programa o que será exibido na sua execução.

#include <stdio.h>

void main(void)
{
int i, n, x, vet[]={3, 5, 9, 0, 4};
int *ptr;

ptr = vet;
printf("[%3d]", *ptr);
*ptr = 2;
for(i=n=x=0; i<4; i++){
n+=vet[i];
x = (i%2)?x+1:x+2;
}
printf("[%-4d]", n);
printf("[%d]", i*sizeof(vet));
printf("[%d]", x);
ptr++;
printf("[%03d]", *ptr);
}

21) Mostrar ao lado de cada chamada a função printf o que será exibido na execução deste programa. Substituir
espaços em branco por um traço.

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void main(void)
{
int a=1, b=0, vet[4] = {6, 9, 2, 5}, *ptr;
char txt[10]="1prova";

ptr = &a;
b = *ptr;
printf("[%04d]", vet[b]);
ptr = vet;
a = ++b;
printf("[%d]", a);
ptr++;
printf("[%-5d]", *ptr);
printf("[%3d]", sizeof(txt) - strlen(txt));
for(a=1, b=0; txt[b]!='\0'; b++)
if(isalpha(txt[b]))
a*=2;
printf("[%d]", a);
}

22) Escrever uma função int divisao(int dividendo, int divisor, int *resto), que retorna
a divisão inteira (sem casas decimais) de dividendo por divisor e armazena no parâmetro resto, passado por
referência, o resto da divisão.
int r, d,
d = divisao(5, 2, &r);
printf("Resultado:%d Resto:%d", d, r); /* Resultado:2 Resto:1 */
Linguagem C 36 Prof. Marcos José Brusso

23) Escrever um programa que declara um vetor int com 30 elementos na função main e atribui 0 (zero) para todos
os elementos com um laço for. Em seguida, em uma função chamada leitura, deve ler um valor maior que 0 e menor
que 1000 para cada posição do vetor. Finalmente, em uma função chamada calculo, deve ser exibido o maior e o
menor valor armazenado no vetor. Não pode ser declarada nenhuma variável global.

24) Escrever um programa que declara um vetor int com 20 elementos na função main e lê um valor para cada
posição do vetor na mesma função. Em seguida exibir o conteúdo do vetor em uma função chamada exibe, seguindo
a seguinte lógica: Se a soma dos valores armazenados no vetor for um número par, mostrar o vetor a partir do
primeiro elemento até o último. Se a soma dos valores armazenados no vetor for um número impar, mostrar o vetor
a partir do último elemento até o primeiro. O programa não pode utilizar nenhuma variável global.

25) Escrever uma função int ultima(char *string, char c) que retorna qual a última posição na
string em que aparece o caracter c. Se o caracter não estiver na string, retornar –1.
char str[]=”teste”;
int q;
q=ultima(str, ‘t’); /* q recebe 3 */
q=ultima(str, ‘x’); /* q recebe –1 */

26) Escrever uma função int substitui(char *string, char c1, char c2), que troca, na string
recebida como parâmetro, toda a ocorrência do caracter c1 pelo caracter c2. A função deve retornar o número de
substituições que foram feitas.
char txt[] = "recupera";
int num;
num = substitui(txt, 'e', 'X');
printf("%d - %s", num, txt); /* 2 - rXcupXra */

27) Escrever a função char *right(char *destino, char *origem, int num) que copia para a
string destino os últimos num caracteres da string origem. Retornar destino.
char str[80];
right(str, "testando", 2); /* str recebe "do" */
right(str, "abcdefgh", 4); /* str recebe "efgh" */

28) Escrever uma função int totalpos(char *string, char c), que retorna a soma das posições
(índices) da string onde aparece o caracter c. Se o caracter não aparece na string, retornar -1.
num = totalpos(“internet”, ‘e’); /*retorna 9 (3+6) */
num = totalpos(“internet”, ‘i’); /*retorna 0 (0) */
num = totalpos(“internet”, ‘a’); /*retorna -1 */

29) Escrever uma função int contadepois(char *string, char c) que retorna quantos caracteres a
string possui após a primeira posição onde aparece o caracter c. Se a string não possuir o caracter c a funcão deve
retornar -1.
var = contadepois(“avaliando”, ‘n’); /* var recebe 2 */
var = contadepois(“avaliando”, ‘a’); /* var recebe 8 */
var = contadepois(“avaliando”, ‘o’); /* var recebe 0 */
var = contadepois(“avaliando”, ‘x’); /* var recebe -1 */

30) Escrever uma função int primeira(char *string, char c) que retorna qual a primeira posição na
string em que aparece o caracter c. Se o caracter não estiver na string, retornar –1.
char str[]=”teste”;
int q;
q=primeira(str, ‘e’); /* q recebe 1 */
q=primeira(str, ‘x’); /* q recebe –1 */

31) Escrever um programa que declara uma string de 80 caracteres na função main, lê a string, e depois exibe a
string informada, um caracter em cada linha em uma outra função chamada mostra. Não pode ser declarada
Linguagem C 37 Prof. Marcos José Brusso

nenhuma variável global.

32) Escrever um programa que inicialmente pede ao usuário qual o tamanho do vetor que ele quer usar. Então cria
dinamicamente um vetor float do tamanho informado, lê um valor para cada posição do vetor e no final exibe a soma
e a média do vetor, ambas com 3 casas decimais e todos os valores do vetor que forem maior que a média calculada.
O programa deve ter no mínimo 2 funções e não pode declarar variáveis globais.

33) Escrever um programa que aloca dinamicamente um vetor double de 50 posições na função main. A seguir, lê
um valor para cada posição na função leitura. Finalmente mostra a soma dos valores que estão armazenados em
posição pares do vetor na função exibe. Não pode ser declarada nenhuma variável global.

34) Escrever um programa que declara dois vetores int com 20 elementos, vet1 e vet2. Lê um valor para cada
posição de vet1, copia vet1 invertido (de trás para frente) em vet2 e exibe os dois vetores. A leitura deve ser feita em
uma função chamada leitura, a inversão em função chamada inverte e a exibição em uma função chamada exibe.
Não pode ser declarada nenhuma variável global.

35) Escrever ao lado de cada chamada à função printf o que será exibido na execução deste programa. Substituir
espaços em branco por _

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define dif(y, z) (y>z)?y-z:z-y

void main(void)
{
int a=6, i=1, *ptr;
char frase[]="a*b23*z", outra[20]="0123456789ABCDEF";

ptr = &i;
for(i=0; frase[i]!='\0'; i++)
if(isdigit(frase[i])) a+=i;
printf("[%-4d]", a++);
printf("[%03d]", *ptr);
*ptr = strlen(frase)-2;
printf("[%c]", outra[--i]);
printf("[%3d]", dif(a, i));
outra[1] = '&';
printf("[%-6.3s]", outra);
}

36) Escrever uma função void copialn(char *destino, char *origem), que copia apenas os
caracteres da string origem que são letra ou número para a string destino.
char s1[20]=”Por $17,00”, char s2[20];
copialn(s2, s1); /* s2 recebe “Por1700” */

37) Escrever um programa que declara uma string palavra com 80 caracteres. A seguir o programa deve ler
repetidamente esta string (usar gets) e mostrar a string e o seu tamanho (número de caracteres ocupados) até que o
valor digitado seja “FIM”. No final mostrar quantas leituras foram feitas e o número total de caracteres.
Digite uma string: AULA
String: [AULA] Caracteres: 4
Digite uma string: TESTANDO
String: [TESTANDO] Caracteres: 8
Digite uma string: FIM
String: [FIM] Caracteres: 3
Strings Lidas: 3 Total de Caracteres: 15
Linguagem C 38 Prof. Marcos José Brusso

38) Mostrar ao lado de cada chamada a função printf o que será exibido na execução do programa abaixo. Substituir
espaços em branco por _

#include <stdio.h>
#include <ctype.h>
#include <string.h>

void main(void)
{
int a=0, b=2, c=10;
char txt1[80]="A*E*I*O*U", txt2[80]="X:Y:Z";
char *ptr;

ptr=txt1;
ptr++;
a=(isalpha(*ptr))?b:c;
printf("[%03d]", --a);
strcpy(txt2, txt1);
*ptr = '$';
printf("[%-12s]", txt1);
b = a-strlen(txt2);
printf("[%-5d]", b++);
printf("[%c]", txt2[1]);
if(strcmp(txt1, txt2)==0)
c = b + sizeof(txt1);
printf("[%6d]", c);
}

39) Mostrar ao lado de cada chamada à função printf o que será exibido na execução do programa. Substituir
espaços em branco por sublinhado (_):

#include <stdio.h>
#include <string.h>

void main(void)
{
char frase[]="computacao";
char *p;
float var=0.0;
int i, k;

p = frase;
k=strlen(frase);
printf("[%04d]", ++k);
while(*p != '\0'){
p++;
var += 1.5;
}
printf("[%7.2f]", var);
i = (int) var - k;
printf("[%-5d]", i);
k = sizeof(var);
printf("[%c]", frase[k]);
printf("[%-7.5s]", frase);
}
Linguagem C 39 Prof. Marcos José Brusso

40) Escrever uma função void stringup(char * destino, char *origem), que copia todos os
caracteres da string origem para destino, convertendo-os para maiúscula.
char s1[20], s2[20]=”aula de c”;
stringup(s1, s2);
printf(“%s”, s1); /* AULA DE C */

41) Escrever uma função void removeb(char *str1, char *str2) , que recebe duas strings como
parâmetro e copia para a primeira string (str1) todos os caracteres da segunda (str2) que não são brancos.
char txt1[80]=" a b c d”, txt2[80];
removeb(txt2, txt1);
printf("[%s]", txt2); /* Exibe [a b c d] */

42) Escrever um programa que lê repetidamente uma string em um laço. Se o valor digitado for igual a “exit”, deve
parar, senão exibe-a um caracter por linha.
Digite uma string: aula
a
u
l
a

Digite uma string: abc


a
b
c

Digite uma string: exit

43) Mostrar ao lado de cada chamada a função printf o que será exibido na execução do programa abaixo. Substituir
espaços em branco por _

#include <stdio.h>
#include <ctype.h>
#include <string.h>

void main(void)
{
char sa[20]="A1B2C3D4", sb[10]="Z9";
char *p;
int i=1, j;

p=sa;
j=(isdigit(sa[--i]))?sizeof(sa):sizeof(sb);
printf("[%-5d]", j);
strcat(sa, sb);
p++;
*p = 'H';
printf("[%12s]", sa);
i+=strlen(sb);
printf("[%06d]", i++);
if(strcmp(sa, sb) < 0)
i*=2;
printf("[%c]", sa[i]);
printf("[%-5.1s]", sb);
}
Linguagem C 40 Prof. Marcos José Brusso

44) Escrever ao lado de cada chamada à função printf o que será exibido na execução deste programa. Substituir
espaços em branco por _

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define dif(y, z) (y>z)?y-z:z-y


void main(void)
{
int a=2, i=1, *ptr;
char frase[]="PROGRAMA.C", outra[20]="abcdefghijklmn";

ptr = &i;
for(i=0; frase[i]!='\0'; i++)
if(isalnum(frase[i])) a+=i;
printf("[%-4d]", --a);
printf("[%03d]", *ptr);
*ptr = strlen(frase);
printf("[%c]", outra[i]);
printf("[%3d]", dif(8, 25));
outra[1] = '#';
printf("[%-8.4s]", outra);
}

45) Mostrar ao lado de cada chamada à função printf o que será exibido na execução do programa. Substituir
espaços em branco por sublinhado (_):

#include <stdio.h>
#include <ctype.h>
#include <string.h>

struct produto{
int codigo;
char nome[30];
float preco;
};

void main(void)
{
struct produto reg={10,"Caneta", 2.5};
char c, teste[30]="abc";
int v=2, i;

printf("[%-5d]", --v);
c = reg.nome[v];
v = (islower(c)) ? strlen(teste) : sizeof(teste);
printf("[%d]", v);
reg.preco += v;
printf("[%10.3f]", reg.preco);
strcpy(teste, reg.nome);
printf("[%10.3s]", teste);
for(i=0,v=1; teste[i]!='\0'; i++)
if(teste[i]=='a')
v++;
printf("[%-4d]", v);
Linguagem C 41 Prof. Marcos José Brusso

46) Mostrar ao lado de cada chamada à função printf o que será exibido na execução do programa. Substituir
espaços em branco por sublinhado (_):

#include <stdio.h>
#include <string.h>

struct pessoa{
char nome[40];
int idade;
float peso;
};

void main(void)
{
struct pessoa reg={"Fulano", 20, 60.5};
int var=0;
int *p;
char c;
char linha[40]="Beltrano";

p = &var;
var=strlen(reg.nome);
printf("[%d]", var++);
var/=2;
c = reg.nome[var];
printf("[%c]", c);
*p=(strcmp(linha,reg.nome)!=0)? sizeof(linha) : strlen(linha);
printf("[%-6d]", --var);
reg.peso += *p;
printf("[%7.2f]", reg.peso);
for(var=0; linha[var]!='\0'; var++)
reg.idade = reg.idade - 1;
printf("[%04d]", reg.idade);
}

47) Escrever uma funcão int ultimodomes(struct data *dt) que retorna qual o ultimo dia do mes em
que se encontra a data passada por parâmetro.
struct data teste={15, 4, 1999};
int ult;
ult = ultimodomes(&teste); /*ult recebe 30 */

48) Escrever uma funcao void datecpy(struct data *dt1, struct data dt2), que atribui o
conteúdo de dt2 para dt1.
struct data da={1,5,1999}, db={15,8,1980};
datecpy(&da, &db); /* copia db para da */

49) Escrever um programa que recebe o nome de 2 arquivos como argumento de linha de comando. O programa deve
criar o segundo arquivo e gravar nele todos os caracteres do primeiro que forem letras ou números e no final, mostrar
na saída padrão quantos caracteres foram copiados. Qualquer mensagem de advertencia ao usuário (número inválido
de argumentos, não pode abrir o arquivo, etc...) deve ser exibida na saída de erros.
c:\> copialn aula.txt aula.ltr
Foram copiados 71 caracteres
Linguagem C 42 Prof. Marcos José Brusso

50) Escrever um programa que recebe o nome de dois arquivos como argumento na linha de comando (origem e
destino) e copia o conteúdo do primeiro arquivo para o segundo, eliminando os espaços em branco. O programa
somente deve aceitar um número válido de argumentos.
c:\> copiasem aula.txt limpo.txt

51) Escrever um programa que recebe o nome de um arquivo como argumento na linha de comando, e conta e exibe
quantos caracteres o arquivo contêm, quantos são espaços, quantos são letras, quantos são números e quantos são
outro tipo de caracter. O programa somente deve aceitar um número válido de argumentos.
c:\> conta teste.txt
teste.txt possui 110 caracteres, sendo 10 espaços, 55 letras, 15
números e 30 outros caracteres.

52) Escrever um programa que recebe o nome de um arquivo texto como argumento na linha de comando e conta
quantas linhas o arquivo contêm. O programa somente deve aceitar um número válido de argumentos.
c:\> conta teste.txt
teste.txt possui 15 linhas

53) Escrever um programa que recebe o nome de um arquivo como argumento na linha de comando, e exibe o
conteúdo do arquivo convertendo todas as letras para maiúsculas. O programa somente deve aceitar um número
válido de argumentos.

54) Escrever um programa que recebe o nome de 2 arquivos texto pela linha de comando e copia o conteúdo do
primeiro arquivo para o segundo convertendo todas as letras maiúsculas para minúsculas e as minúsculas para
maiúsculas.
C:\> COPIAMM arq1.txt arq2.txt

55) Escrever um programa que recebe o nome de um arquivo texto como argumento de linha de comando e exibe o
seu conteúdo no seguinte formato: o caracter e seu codigo ASCII em hexadecimal, um caracter por linha. Validar o
número de argumentos passados.

56) Escrever um programa que receba o nome de um arquivo texto como argumento de linha de comando e, lendo o
seu conteúdo, conta e exibe o número de linhas que o arquivo contêm. Qualquer mensagem de advertência ao usuário
(parâmetros inválidos ou não pode abrir o arquivo) deve ser exibida na saída padrão de erros.
C:\> contalin teste.txt
teste.txt possui 19 linhas.

57) Escrever um programa que recebe o nome de 2 arquivos como argumento de linha de comando. O programa deve
criar o segundo arquivo e gravar nele todos os caracteres do primeiro que forem letras e no final, mostrar na saída
padrão quantos caracteres foram copiados. Qualquer mensagem de advertencia ao usuário (número inválido de
argumentos, não pode abrir o arquivo, etc...) deve ser exibida na saída de erros.
c:\> copialetras aula.txt aula.ltr
Foram copiados 71 letras