Buscar

Apostila de Linguagem C

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 64 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 64 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 64 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Apostila
de
L I N G U A G E M C
(Com Exercícios Adicionais)
 
 
 
 
 
 
 
 
 
 
 
 
 
Prof. Jorge Viana Doria Junior, M.Sc. – UFRJ.
Fevereiro 2016.1
	 
	SUMÁRIO
	
	
	
	
	
	PARTE I – A LINGUAGEM C
	
	
	
	
	1
	Introdução Linguagem C ..............................................................................................
	04
	1.1
	Características & histórico .............................................................................................
	04
	1.2
	Características de um programa C ................................................................................
	04
	1.3
	Formato de um programa em C .....................................................................................
	04
	
	
	
	2
	Identificadores .................................................................................................................
	05
	
	
	
	3
	Tipos de Dados Para Variáveis e Funções ......................................................................
	05
	3.1
	Standard (já definidos na linguagem) .........................................................................
	05
	3.2
	Modificadores de tipo .................................................................................................
	05
	
	
	
	4
	Declaração de variáveis ....................................................................................................
	06
	4.1
	Variáveis locais ...........................................................................................................
	06
	4.2
	Parâmetros formais ......................................................................................................
	07
	4.3
	Variáveis globais .........................................................................................................
	07
	4.4
	Modificadores de classe de armazenamento ...............................................................
	07
	4.4.1
	Variáveis automáticas – auto – modificadores de classe de armazenamento ...........
	07
	4.4.2
	Variáveis externas – extern – modificadores de classe de armazenamento ...............
	08
	4.4.3
	Variáveis estáticas – statics ........................................................................................
	08
	4.4.4
	Variável register .........................................................................................................
	08
	
	
	
	5
	Operadores ........................................................................................................................
	08
	5.1
	Aritméticos ..................................................................................................................
	08
	5.2
	Lógicos ou Booleanos .................................................................................................
	09
	5.3
	Relacionais ..................................................................................................................
	09
	5.4
	Entre bits .....................................................................................................................
	09
	5.5
	Outros operadores .......................................................................................................
	09
	5.6
	Precedência .................................................................................................................
	09
	5.7
	Pré-processador e diretivas .........................................................................................
	10
	5.8
	Diretiva #define .........................................................................................................
	10
	5.9
	Diretiva #include ........................................................................................................
	10
	5.10
	namespace, using namespace, comandos cin e cout do C++ .......................
	11
	
	
	
	6
	Entrada e saída de dados pela console – funções printf e scanf ....................................
	12
	6.1
	printf ...........................................................................................................................
	12
	6.2
	scanf ............................................................................................................................
	12
	
	
	
	7
	Instruções de controle .......................................................................................................
	13
	7.1 
	O comando if ...............................................................................................................
	13
	7.2
	O operador ? (substitui o if) ........................................................................................
	14
	7.3
	O comando switch .......................................................................................................
	14
	
	Exercícios de fixação ........................................................................................
	14
	7.4
	O comando for ............................................................................................................
	15
	7.5
	O comando while ........................................................................................................
	15
	7.6
	O comando do { ... } while ..........................................................................................
	16
	7.7
	O comando continue ...................................................................................................
	16
	7.8
	O comando break ........................................................................................................
	17
	7.9
	O comando goto< label> .............................................................................................
	17
	
	Exercícios de fixação .......................................................................................
	19
	
	
	
	8
	Arrays unidimensionais – Vetores ...................................................................................
	20
	
	Exercícios de fixação ........................................................................................
	21
	8.1
	Arrays unidimensionais de caracteres – Strings ................................................................
	22
	
	Funções getchar, putchar, getchar e gets ......................................................
	22
	9
	Arrays bidimensionais – Matrizes ...................................................................................
	24
	
	Exercícios de fixação ........................................................................................
	26
	
	
	
	10
	Funções ..............................................................................................................................
	27
	
	
	
	11
	O tipo Pointer – Ponteiro ..................................................................................................
	28
	11.1
	Definição .....................................................................................................................
	28
	11.2
	Iniciação de ponteiros na definição .............................................................................
	29
	11.3
	Passagem de parâmetros por endereço (por referência) ..............................................
	29
	
	
	
	12
	A relação entre ponteiros e arrays ...................................................................................
	30
	
	
	
	13
	Ponteiros e arrays bidimensionais ...................................................................................
	32
	13.1
	Arrays tridimensionais ................................................................................................
	34
	13.2
	Arrays de ponteiros – ragged arrays ..........................................................................35
	
	
	
	14
	Alocação dinâmica de memória ..........................................................................................
	36
	
	A função malloc ..........................................................................................................
	36
	
	Vetores gerados dinamicamente .......................................................................
	37
	
	A função calloc ...........................................................................................................
	37
	
	A função realloc .........................................................................................................
	38
	
	A função free ...............................................................................................................
	38
	
	
	
	15
	Definição de novos tipos ...................................................................................................
	39
	
	
	
	16
	Estruturas – structs ..........................................................................................................
	39
	16.1
	Iniciação de estruturas .................................................................................................
	41
	16.2
	Campos de bits ...........................................................................................................
	41
	16.3
	Uniões .........................................................................................................................
	41
	16.4
	Ponteiros para estruturas .............................................................................................
	43
	16.5
	Ponteiro para percorrer array de ponteiros .................................................................
	44
	
	
	
	17
	Ponteiros para funções .....................................................................................................
	45
	
	
	
	18
	Tipos enumerados .............................................................................................................
	46
	
	
	
	19
	Arquivos .............................................................................................................................
	47
	19.1
	Funções para Abertura e fechamento de arquivos .................................................
	47
	19.1.1
	Função para abertura de arquivos .....................................................................
	47
	19.1.2
	Função para afechamento de arquivos ..............................................................
	49
	19.2
	Principais funções para leitura e gravação seqüenciais .........................................
	49
	19.3
	Principais funções para leitura e gravação direta (tipos texto e binário) .............
	50
	
	
	
	
	
	
	
	Referências Bibliográficas ..............................................................................................
	55
	
	Exercícios Adicionais ........................................................................................................
	56
	
	
	
 
 
 
A Linguagem C
1.	Introdução a linguagem C
Características & Histórico
SYMBOL 183 \f "Symbol" \s 10 \h	linguagem de médio nível;
SYMBOL 183 \f "Symbol" \s 10 \h	linguagem estruturada;
SYMBOL 183 \f "Symbol" \s 10 \h	versátil (aplicação em várias áreas);
SYMBOL 183 \f "Symbol" \s 10 \h	portável;
SYMBOL 183 \f "Symbol" \s 10 \h	código eficiente;
SYMBOL 183 \f "Symbol" \s 10 \h	compilação condicional;
SYMBOL 183 \f "Symbol" \s 10 \h	compilação separada (funções em vários arquivos);
SYMBOL 183 \f "Symbol" \s 10 \h	linguagem para o programador.
SYMBOL 183 \f "Symbol" \s 10 \h	BCPL ( B ( C ( C++
SYMBOL 183 \f "Symbol" \s 10 \h	C - 1971 - Kernighan e Ritchie (K & R)
SYMBOL 183 \f "Symbol" \s 10 \h	C ANSI (American National Standards Institute) - 1989
Características de um programa
SYMBOL 183 \f "Symbol" \s 10 \h	Um programa em C é composto por pelo menos uma função, a função "main";
SYMBOL 183 \f "Symbol" \s 10 \h	Todo programa em C começa a sua execução a partir da função "main";
SYMBOL 183 \f "Symbol" \s 10 \h	Normalmente, um programa em C é uma coleção de funções de pequeno tamanho;
SYMBOL 183 \f "Symbol" \s 10 \h	Toda função tem um tipo;
SYMBOL 183 \f "Symbol" \s 10 \h	Palavras reservadas e funções da biblioteca do C são sempre escritas com letras minúsculas.
1.3. 	Formato de um programa em C
"definições"
função_1
função_2
	 . . .
função_n
funcão_main /	 A ordem das funções dentro de um programa pode ser qualquer
( Exemplo de um programa
#include <stdio.h>					//	Instrução para o pré-processador
void 	main ( )						//	Início da função main
{										// 	Início de bloco
    		int i;							//	Define “i” como uma variável do tipo inteiro
    		i = 10;						//	Iinicia “i” 
    		printf ("i = %d\n", i);   	//	Chama função de impressão
}										//	Fim de bloco
//	Toda instrução termina por ” ; “ e o protótipo de printf está em stdio.h (standard IO)
 
 
 
2.	Identificadores
São usados em nomes de funções e variáveis.
A maioria dos compiladores reconhece 31 caracteres tanto para variáveis quanto para funções, e:
SYMBOL 183 \f "Symbol" \s 10 \h	Devem começar por letra ou '_';
SYMBOL 183 \f "Symbol" \s 10 \h	Normalmente se usam letras minúsculas;
SYMBOL 183 \f "Symbol" \s 10 \h	Não podem ser iguais às palavras reservadas;
SYMBOL 183 \f "Symbol" \s 10 \h	Minúsculas são compredidas como diferentes de maiúsculas (e.g.: ABC (Abc ( ABc ( abc).
 
3.	Tipos de Dados para Variáveis e Funções
3.1.	Standard (já definidos na linguagem)
caracter				char			(1 caractere)
inteiro				int				(2 bytes)
inteiro duplo		long int		(4 bytes)
real					float			(4 bytes)	
real duplo			double		(8 bytes)
nada					void			(0 bytes)
O tipo inteiro possui o tamanho da palavra da CPU.
	Tipo
	Tamanho em Bits
	Faixa
	Char
	8
	0 a 255
	int 
	16
	-32768 a 32767
	long int 
	32
	–2,147,483,648 a 2,147,483,647
	Float
	32 
	6 dígitos
	Double
	64 
	12 dígitos
	Void
	0
	Sem valor
3.2.	Modificadores de tipo
Alteram o significado do tipo standard.
SYMBOL 183 \f "Symbol" \s 10 \h	signed (com sinal)
SYMBOL 183 \f "Symbol" \s 10 \h	unsigned (sem sinal)
SYMBOL 183 \f "Symbol" \s 10 \h	long (passa inteiro de 2 bytes para 4 bytes)
SYMBOL 183 \f "Symbol" \s 10 \h	short (passa inteiro de 4 bytes para 2 bytes)
 
Se tipo int: 	long int 	= 	long 		( 		4 bytes
				short int	=	 int 		( 		2 bytes
Exemplos:	signed char 				( 		(128 a 127
				unsigned int				( 		0 a 65535
 
 
 
 4.	Declaração de Variáveis
Variáveis devem ser declaradas antes de serem usadas.
Formato:	<tipo> <lista de variáveis>;
Exemplos:	int 		a, b, c;
				float 		soma;
				double 	somatorio, raiz_quadrada;
				char 		sim, nao;
As variáveis podem ser definidas dentro de qualquer bloco:
{
		int x, y;
		< bloco de comandos >;
}
4.1.	Variáveis locais
São as declaradas dentro de blocos e só são reconhecidas dentro do bloco de declaração.
// Exemplo:
#include <stdio.h>
void 	main ( )
{		int i = 2, j;
    		j = 2 * i;
    		printf ("O dobro de %d = %d\n", i, j);
}
/* No exemplo acima, “ i “ e “ j “ são variáveis locais da função “main” . */
 
// Exemplo:
void 	f1 ( )
{		int x;
    		x = 5;
     	. . .
    		if (a > 10)
        	{		int x, y;
        			x = 20;
        			y = 40;
         		. . .
        	}
}
//	No exemplo, a variável x tem o valor 5 quando sair do bloco mais interno.
 
 
 
 
 
4.2.	Parâmetros formais – os parâmetros das funções.
Quando parâmetros são passados por valor a função só recebe cópia do conteúdo da variável.
Exemplo:	int soma (int a, int b)
    				{return (a + b);
    				}
No exemplo, a e b são parâmetros formais e a função soma poderia ser chamadadas seguintes formas:
j = soma (2, 3); 		ou		x = soma (a, b);
4.3.	Variáveis globais
São reconhecidas por todas as funções de um programa ou de um arquivo.
// Exemplo:
#include <stdio.h>
int cont;
void f ( void );
void 	main ( )
{
    	cont = 100;
    	printf("cont em main = %d\n", cont);
    	cont = cont + 1;
    	f ( );
}
void f ( )
{
    printf("cont em f = %d\n", cont);
}
4.4.	Modificadores de classe de armazenamento
Indicam como as variáveis devem ser armazenadas.
Exemplo de mapa da memória de um programa em C em um equipamento genérico:
	Stack
	
Heap 
	Variáveis Estáticas e Globais 
	Área de Código 
 
4.4.1.	Variáveis automáticas – auto – são as variáveis definidas normalmente.
Exemplo:	int x;	<=>	auto int x;
A palavra auto não é necessária.
4.4.2. Variáveis externas – extern – são variáveis globais definidas em arquivos diferentes.
// Exemplo:	arquivo 1:
void main ( )
{
	    						int x, y;
 				y = 30;
	    						x = 10;
	    						f ( );
	    						. . .
}
// arquivo 2:
extern int x, y;
void f ( )
{	
 				. . .
	    						printf ("%d %d\n", x, y);
	    						. . .
	    				}
 
4.4.3.	Variáveis estáticas - static
A variável não perde o seu valor dentro da função ou arquivo. 
Este tipo de variável é mais empregado para definição de strings.
Quando uma função é definida como static, ela só pode ser ativada por uma função que esteja no mesmo arquivo.
4.4.4	Variáveis register
A variável é colocada em um dos registradores da CPU e, por isso, dve ser bem escolhida 
Ex.:	register int i, j;
Este tipo de variável é mais usada em casos nos quais a velocidade é importante, como, por exemplo, em variáveis que controlam laços.
 
5.	Operadores
Um operador é um caracter ou grupo de caracteres que causará uma manipulação matemática ou lógica.
Em C, os operadores podem ser aritméticos, relacionais e lógicos e entre bits.	
5.1.	Aritméticos
	+			(			+=				( 		adição
	(			(			( =			( 		subtração (e menos unário)
	*			(			* =			( 		multiplicação
	/			(			/ =				( 		divisão
	%										( 		resto divisão
	((										( 		decremento
	++										( 		incremento
 
5.2.	Lógicos ou boleanos
		&&	( e
		| |	( ou
		!	( não
5.3.	Relacionais
		>			( 		maior
		<			( 		menor
		==			( 		igual
		!=			( 		diferente
		>=			( 		maior ou igual
		<=			( 		menor ou igual
5.4.	Entre bits
		&			( 		e
		 |			( 		ou
		^			( 		ou exclusivo
		~			( 		complemento (NOT)
		>>			( 		deslocamento para direita
		<<			( 		deslocamento para esquerda
5.5.	Outros operadores 
		*			( 		retorna o valor contido em um endereço
		&			( 		retorna o endereço de uma variável
		sizeof		( 		retorna o tamanho de uma variável ou tipo
		?			( 		avalia expressão verdadeira
		,			( 		equivalente a "faça isto e isto e isto ..."
		.			( 		membro de estrutura ou união
		((			( 		ponteiro para membro de estrutura ou união
		(type)		( 		cast (altera tipo do dado)
5.6.	Precedência (da maior para a menor)
		( )	[ ]	((
		!		~		++	 	( (	( type )	*	&		sizeof
		*		/		%
		+		(
		<<	 	>>
		<		<=	>		>=
		==		!=
		&
		^
		|
		&&
		| |
		?
		=		+ =	(=		* =	/ =
		,
 
 
 
5.7.	Pré-processador e diretivas
O pré-processador é um programa que age antes do compilador da linguagem C, aumentando sua capacidade e auxiliando a portabilidade. Ele é comandado por diretivas (que iniciam sempre pelo sinal #). As diretivas só valem no arquivo onde estão definidas ou arquivos incluídos abaixo destas diretivas 
5.8 	# define
Serve para definir uma constante simbólica. Por exemplo:
#define TRUE 1
#define FALSE 0
#define MENS_ERRO "Erro. Divisão por zero.\n"
#define MAX_TAM 100
As constantes assim definidas podem ser usadas para atribuir valores a variáveis, passadas como parâmetros e para comparações dentro do programa. Ex.:
int erro;
. . .
erro = FALSE;
if (a == 0) 
    flag = TRUE;
if (erro)
    printf (MENS_ERRO);
	
Outra finalidade do #define é criar macro funções. Por exemplo:
# define MIN(a, b) ((a) < (b) ? (a) : (b))		então	(	se: a = MIN(x, 3);	(	a = ((x) < (3) ? (x) : (3));
#define streq	(x, y) (strcmp((x), (y)) == 0)		/* iguais */	
#define strlt	(x, y) (strcmp((x), (y)) < 0)		/* x < y */
#define strgt	(x, y) (strcmp((x), (y)) > 0)		/* x > y */
Para que se possa reutilizar uma constante devemos torná-la antes indefinida, usando a diretiva #undef a seguir redefini-la novamente usando outro #define. Por exemplo:
a) 	# define NOME "teste"
 			. . .
 	 # undef NOME
 	# define NOME "teste"
b) #define TAM 100
 	#define COMP 100
 			char array [ TAM ][ COMP ]
 	#undef COMP
 	#define COMP 200
 		char arrayb [TAM][COMP]
5.9 	# include
Permite incluir o conteúdo de um arquivo no programa. 
Exemplos:	#include <stdio.h>				//	Procura stdio.h no diretório de arquivos header
#include "stdio.h"				//	Procura stdio.h no diretório corrente
#include "b:auxiliar.h"			//	Procura auxiliar.h no drive b
Esta última forma deve ser evitada, pois gera dependência do sistema operacional.
O comando #include <iostream> é usada para incluir o acesso a biblioteca padrão de entrada e saída de dados do C++. 
A <iostream> é uma biblioteca usada para entrada e saída de dados. Ela fornece o objeto std::cout, que serve para enviar uma mensagem para a tela e utiliza o operador <<, que indica: envie estes caracteres para saída (cout = C out). 
A <iostream> fornece também o objeto std::cin, que é usado para entrada de dados. Observe o uso do operador >> que indica: armazene a entrada do usuário neste objeto.
5.10	namespace 
O que é um namespace ? Como o próprio nome diz, signifca espaço para nomes. 
Quando se monta programas utilizando bibliotecas externas, podem ocorrer duplicações de nomes, isto é, um objeto defnido em uma bibliotecas tem o mesmo nome de um objeto defnido por você. 
Por exemplo: você criou as funções min ( ) e max ( ), que retornam o menor e maior valor de um vetor. Mas a STL – biblioteca padrão para tratamento de vetores em C++ já tem estas funções e , por isso, o compilador não “saberá” que função min( ) e max ( ) você quer chamar. 
Solucionar o problema da duplicação de nomes pode ser complexo, pois se estes nomes pertencerem a bibliotecas externas, você precisaria contatar os desenvolvedores delas para resolver os confitos, ou renomear seus objetos e funções. O namespace veio para resolver este problema. 
Para usar os objetos standart de C++ é preciso incluir a palavra std e a seguir o operador de resolução de escopo, isto é: std::nomeObjeto; 
std::cout << “ Entre com x : “; 			//	cout 	=	saída de dados
std::cin >> x ; 								//	cin 	=	entrada de dados
Obs.:os comandos cin e cout devem ser utilizados somente em programação ambientadas em C++
5.11 using namespace std
Mas é possível utilizr os objetos standarts de C++ diretamente, isto é, sem o uso de std::. Para tal basta colocar a declaração using namespace std no início do programa. 
// Exemplo: Declara que vai usar os objetos standart de C++ 
	 …
using namespace std; 
int x = 3 ; 
cout	 < < “ Entre com x : “; 
cin	> > x ;
 
 
 6.	Entrada e Saída de Dados Pela Console – Funções printf e scanf 
Ao contrário de outras linguagens, no C as operações de leitura e impressão, tanto na tela quanto em arquivos, é totalmente feita por funções. Os protótipos destas funções se encontram no arquivo stdio.h, o qual deve sempre ser incluído quando forem usadas funções de IO (entrada e saída).
6.1.	printf
Principal funçãode impressão no vídeo e retorna o número de caracteres impressos.
Formato: int printf (formato, argumentos);
Obs1.: Em C, o valor de retorno de uma função pode ser ignorado.
Obs2.: Em C, as funções podem ter um número variável de parâmetros.
Ex.: printf (" \n FIM \n" ) ;
Principais formatos de impressão:	
SYMBOL 183 \f "Symbol" \s 10 \h		%d 		(			inteiro
SYMBOL 183 \f "Symbol" \s 10 \h		%c 		(			caracter
SYMBOL 183 \f "Symbol" \s 10 \h		%f 		(			float
SYMBOL 183 \f "Symbol" \s 10 \h		%ld 		( 			long int
SYMBOL 183 \f "Symbol" \s 10 \h		%lf 		( 			double
SYMBOL 183 \f "Symbol" \s 10 \h		%s 		( 			string
SYMBOL 183 \f "Symbol" \s 10 \h		%e 		( 			notação científica
// A saída pode ser formatada através do tamanho do campo:
SYMBOL 183 \f "Symbol" \s 10 \h	%3d 		( 		inteiro com 3 dígitos.
SYMBOL 183 \f "Symbol" \s 10 \h	%7.2f 	( 		float com dois dígitos após o ponto decimal.
6.2.	scanf
Principal função de leitura do teclado.
Formato: int scanf (formato, parâmetros);
Retorna o número de variáveis lidas corretamente ou EOF em caso de erro grave.
Principais formatos:		
		%d 	– 	inteiro
		%c 	– 	caracter
		%f 	– 	float
		%ld 	– 	long int
		%lf 	– 	double
		%s 	– 	string
Para a função scanf, o branco é considerado delimitador. Por exemplo, scanf ("%d %d", &a, &b); mostrará 1 3 ou 1 3 (depende dos espaços entre os %d). Já scanf ("%d , %d", &a, &b); mostrará 1 , 3 (um, vírgula e três).
// Ex.: Ler dois números e imprimir a soma.
# include <stdio.h>
void 	main ( )
{
    		int a, b, c;
    		printf("Entre 2 numeros: ");
    		scanf("%d %d", &a, &b);
    		c = a + b;
    		printf("soma = %d\n", c);
    		/* ou poderia ser printf("soma = %d\n", a + b); */
}
7.	Instuções de controle
7.1.	if { } ; if { … } else { … } ; if { … } else { if { … }} ; etc …
// Exemplo 1
if ( teste ) < um só comando; >
// Exemplo 2
if ( teste )
{
		< bloco de comandos; >
}
else
{
		bloco de comandos;
}
// Exemplo 4: ler 2 números e indicar o maior
#include <stdio.h>
void 	main ( )
{
    		int a, b;
    		printf ("Entre 2 numeros: ");
    		scanf ("%d %d", &a, &b);
    		if (a == b)										/* todo teste de igualdade utiliza == */
        				printf ("Sao iguais\n");
    		else 	if (a > b)
        						printf ("O primeiro é maior\n");
    				else
        						printf ("O segundo é maior\n");
}
// Exemplo 5: ler uma série de números reais e indicar o maior e o menor.
#include <stdio.h>
void main ( )
{
    		float min, max, x;
    		printf ("Entre os numeros:\n");
    		scanf ("%f", &x);
    		min = max = x;		/* atribuição múltipla */
    		while (scanf("%f", &x) == 1)
        			if 	(min > x)		min = x;
        			else 				if (max < x)		max = x;
 		printf (" \n O maior é: %f\n", max);
    		printf (" \n O menor é: %f\n", min);
}
7.2.	O operador ? (substitui o if)
É uma outra forma de utilização do comando if (útil para pequenos comandos do tipo if).
if (a == 10)	 
{
 		b = 20; 		
}										(			b = (a == 10)	?	20	:	30;
else	
{										
		b = 30;
}	 
 
 
7.3.	O comando switch – substitui grandes if's.
switch (exp)			// A expressão exp deve fornecer um resultado inteiro.
{	
case cte 1: 	bloco1;			// cte = constante (	 valor ou caractere (entre aspas simples) 
    							break;
case cte 2:	bloco2;
    							break;
case cte 3:	bloco3;
    							break;
 				. . .
					. . .
case cte n:	bloco n;
    							break;
default		:	bloco default;
    							break;		/* não é necessário break aqui */
}
Exercícios de Fixação
Implemente um programa que receba 3 (três) números inteiros, através do teclado, e visualize qual o maior e qual o menor deles.
Implemente um programa que receba 4 (quatro) números inteiros, através do teclado, e que, após, os visualize em ordem decrescente.
Implemente um programa que receba um número inteiro, através do teclado, pertencente ao intervalo [1000,1010.000[, e que, após, determine e visualize: (i) seus dígitos individualmente; (ii) denomine por extenso o valor de cada dígito; e (iii) a soma dos dígitos pares do número informado. 
Implemente um programa que receba 3 (três) números inteiros, através do teclado, e verifique se eles podem formar um triângulo eqüilátero, um triângulo retângulo, ou se não permitem a formação de um triângulo. 
Obs.:	Relação Triangular: cada lado de um triângulo tem de ser menor que a soma dos outros dois lados ;
 
 
 
 
 
7.4.	for ( . . . ) { . . . }
Formato:	for (inicialização; condição; incremento)	// Todos os campos do for são opcionais
				{
< bloco de comandos; >
				}
// Exemplos: Imprimir os números de 1 a 10
#include <stdio.h>
void 	main ( )
{		int i;
    		for (i = 1; i <= 10; i++)	printf ("%d\n", i);
}	
#include <stdio.h>
void 	main( )
{		int i = 1;
    		for ( ; i <= 10; )	printf("%d\n", i++);
}
7.5.	while
Formato: 		while (condição)
					{
							< bloco de comandos ; >
					}
//	Executa o bloco enquanto a condição for verdadeira (em C, verdadeiro é o que não for zero).
//Exemplo: Seja fazer um programa que imprima a soma dos números de 1 a 5 com um laço while.
// Solução 1:
#include <stdio.h>
void	main( )
{		int i = 1, soma = 0;
    		while (i <= 5)	soma += i++;
    		printf ("\nSoma = %d\n", soma);
}
// Solução 2:
#include <stdio.h>
void main ( )	{		int i = 1, soma = 0;
    							while (i <= 5)	soma += i++;
    							printf ("\nSoma = %d\n", soma);
}
 	Obs.:	i ++;	(	 ++ i;
se a = 1:		para b = ++ a;		(		b = 2 e a = 2
					para b = a ++;		(		b = 1 e a = 2
var = var op exp;			(		var op = exp;
			x = x + 5;					x + = 5;
			x = x / (a + b);				x / = a + b;
 
 
7.6.	do while
Formato:	do		{
			 					< bloco de comandos; >:
						}
while (condição);
Repete o bloco de comandos enquanto a condição for verdadeira.
// Exemplo: Imprimir os números de 1 a 10
#include <stdio.h>
void	main ( )
{		
int i = 1;
    		do		printf ("%d\n", i++ );	while (i <= 10);
}
// Exemplo: Calcular o fatorial de um número lido usando for.
// Solução 1:
#include <stdio.h>
void 	main ( )
{		
int n, i, fator = 1;
    		printf ("Entre o numero: ");	scanf ("%d", &n);
    		for (i = 1; i <= n; i++) fator *= i;
    		printf (" \n Fatorial de %d = %d \n", n, fator ) ;
}
 
// Solução 2:
#include <stdio.h>
void	main ( )
{		
int n, i, fat;
    		printf ("Entre o numero: ");	scanf ("%d", &n);
    		i = n;
    		for (fat = 1; n > 1; n– –) fat *= n;
    		printf( " \n Fatorial de %d = %d \n", i, fat ) ;
}
continue
Continua com o próximo incremento no for ignorando as instruções restantes dentro do bloco do for.
. . .
for (i = 0; i < 10; i++)
{			
if (i == 0)
    			continue;		/* evita divisão por zero */
    			printf("%f\n", (float) 10 / i);
}
 
 
 
 
7.8.	break
Interrompe a execução de um for, while, do ... while ou switch. O fluxo de execução do programa é desviado para primeira instrução fora do bloco que possui o break.
Ex.: 	while (1) 						/* loop infinito */
    		{		scanf("%d" , &a);
    				if (a != 0)	processa ( );
    				else			break;
    		}
goto label
Desvia o fluxo de execução do programa para um label em outro ponto do programa.
			goto Label_1;
			processa ( );
			Label_1:
				. . .
		// 	Para label sem instruções deve-se usar um “;” no final: Erro_Fatal: ;
// Exemplo: Fazer um programa que simule uma calculadora, com as quatro operações, teste // a divisão por zero e sinal inválido.
 # define FALSE 0	/* definição de constantes */
# define TRUE 1
# include <stdio.h>
voidmain ( )
{		
float v1, v2, res;
    		char op;
    		 int erro = FALSE;	/* usa int como variável lógica */
    		 
 
printf ("Entre sua expressão:\n");
    		scanf ("%f %c %f", &v1, &op, &v2);	/* le a expressão */
    		switch ( op )	
{		
case '+' :	res = v1 + v2;	break;
    								case '(' :	res = v1 ( v2:	break;
    								case '*' :	res = v1 * v2;	break;
    								case '/' :	if (v2 == 0.0)	
{		printf (" \n Erro: Divisão por zero\n");
            												erro = TRUE;
            									}
        											else	res = v1 / v2;	break;
    								default:	erro = TRUE;
        										printf (" \n Sinal inválido \n " ) ;
        										break;
        					}
    		if (!erro)				// 	Não precisa fazer erro == TRUE 
        		printf ("\nO resultado é: %10.4f\n", res);
}
 
 // Exemplo: Fazer um programa que leia um valor n e leia e imprima o quadrado de n números.
#include <stdio.h>
void 	main ( )
{		 
float x;
    		int n;
    		
printf ("\n Número de valores a serem lidos: ");
    		scanf ("%d", &n);
    		
while (n ––);
{		
printf(" \nValor: ");
        			scanf (" %f ", &x);
        			printf (" \n Quadrado de %f = %f\n", x, x * x ) ;
        	}	
}
 /*	
 	Obs.: Outras funções de entrada e saída de dados
		int getchar ( void );	// Erro = EOF
		int putchar ( int );		// Erro = EOF; OK = caractere impresso. 
*/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Exercícios de Fixação
A seguir são apresentados vários exercícios. Quando algum deles necessitar utilizar comandos de repetição, resolva-os: (a) utilizando somente o comando do { ... } while ; (b) utilizando somente o comando while{ . . . }; e (c) utilizando somente o comando for { . . . }.
Implemente um programa que receba, através do teclado, um número natural, sem o zero, menor que 1001 (mil e um), e que, após, visualize a soma de todos os números ímpares naturais até o número digitado.
Implemente um programa que receba, através do teclado, um número natural, sem o zero, menor que 501 (quinhentos e um), e que, após, visualize todos os números pares múltiplos de 3 (três) entre 1 e o número digitado.
 
Implemente um programa que receba 3 (três) números inteiros, através do teclado, cujos significados são, respectivamente: o primeiro termo de uma Progressão Aritmética – P. A. ; a razão desta P.A.; e sua quantidade de termos. Após, o programa deverá determinar e visualizar a soma dos termos pares da P.A. supracitada.
Implemente um programa que calcule e visualize a soma dos 15 (quinze) primeiros termos da Progressão Geométrica 3, 9, 27, ... .
É sabido que a série de Fibonacci é: 1 1 2 3 5 8 13 . . . , que pode ser definida assim:
a1 = 1 ; a2 = 1 ; e
		an = (an – 1) + (an – 2) para n ( 3
2.1)	Implemente um programa que visualize um certo termo da série de Fibonacci cuja posição na série deve ser informada através do teclado e deve pertencer ao intervalo [ 0 , 20 ].
2.2)	Implemente um programa que visualize a soma dos N primeiros termos da série de Fibonacci, sendo N informado através do teclado e devendo pertencer ao intervalo [1, 25 ].
2.3)	Implemente um programa que exteriorize todos os quadrados perfeitos pertencentes aos 25 primeiros termos da série de Fibonacci. 
Implemente um programa que receba dois números inteiros, através do teclado, maiores que 0 (zero) e menores que 1000 (mil), e visualize todos os cubos perfeitos compreendidos entre eles, inclusive. 
 	
7) Implemente um programa que receba, através do teclado, um número inteiro maior que – 1 (menos um) e menor que 6(seis), e que, após, visualize seu fatorial.
 
 
 
 
 
8.	Arryas unidimensionais (vetores) numéricos
Definição de vetores unidimensionais:
			<tipo> <nome>[<tam>];
Ex.: int vet[5];	( define vet como um vetor inteiro de 5 posições
A posição do primeiro elemento é vet [ 0 ] e do último vet [ 4 ].
Exemplos de acesso:		int	vet [ 5 ];
									vet[ 0 ]	=	10;
									vet[ 1 ]	=	20;
									vet[ 2 ]	=	40;
for (i = 0 ; i < 5; i++ )		vet [ i ] = 0;		//	Zera o vetor vet
(	Iniciação na definição:
(	Para vetor local:
	static int vet[ ] = {1, 3, 5}; 		// assume que o vetor vet possui 3 elementos
	static float vet[10]; 				// assume vet com 10 elementos, que são iniciados com 0.
	static int vet[5] = {1, 2, 3};	 	// assume vet com 5 elementos; o 4º e o 5º são iniciados com 0.
(	Para vetor global:
	int vet[ ] = {10, 20, 40, 50};	//	assume vet tem 4 elementos
Quando um vetor extern ou static for iniciado sem dimensão, ela será igual ao número de valores da iniciação. Caso seja fornecida a dimensão e faltem elementos na iniciação, os elementos não iniciados valem zero.
 
// Exemplo: Fazer uma função que retorne o maior número de um vetor double.
# include <stdio.h>
double maxval	(double [ ], int);
void levet 		(double [ ], int);
void	main ( )
{		double vet [ 100 ];
    		int i, n;
    		printf (" Número de elementos do vetor: " ) ;		scanf (" %d ", &n);
    		levet (vet, n);
    		printf (" \n Maior valor = %lf ", maxval (vet, n) );
}
void	levet (double v[ ], int n )		/* “double v[ ];” não precisa dar a dimensão */
{		int i;		
double aux;
printf("Entre os elementos do vetor:");
    		for (i = 0; i < n; i++)	{	scanf (" %lf ", &aux );
        									v [ i ] = aux;
        								}
}
double	maxval (double v[ ], int n )
{			int i;		double maior ;	maior = v[ 0 ];			//	maior começa como sendo o primeiro
    			for (i = 1; i < n; i++)
        				if (v [ i ] > maior)	maior = v [ i ];
    		return (maior);
}
Exercícios de Fixação
1) Escreva um algoritmo que preencha um vetor, de dimensão 100 (cem), com valores inteiros maiores que 0 (zero) e menores que 101 (cento e um), informados através do teclado, e que, após, visualize somente os valores múltiplos de 5, sem utilizar o comando que forneça o resto de divisão automaticamente.
Escreva um algoritmo que preencha um vetor com valores inteiros, informados através do teclado, mas de tal modo que nunca sejam armazenados 2 (dois) valores iguais nele. Mais ainda; após terminar o preenchimento o algoritmo dever  visualizar todo conteúdo do vetor.
Escreva um algoritmo que preencha 2 (dois) vetores com valores inteiros maiores que 0 (zero) e menores que 101 (cento e um) , informados através do teclado, e que, após, processe a geração de um terceiro vetor que contenha todos os elementos dos dois primeiros vetores, porém sem que ocorra repetição de valores.
Escreva um algoritmo que preencha um vetor com valores inteiros maiores que 0 (zero) e menores que 101 (cento e um), informados através do teclado, e que, após, visualize todos os valores presentes no vetor que façam parte dos primeiros 10 (dez) termos da série de Fibonacci. 
Escreva um algoritmo que preencha um vetor com valores inteiros maiores que –10 (menos dez) e menores que 10 (dez), informados através do teclado, e que, após, visualize, sem repetições, todos os valores ímpares presentes no vetor que façam parte dos 15 (quinze) primeiros termos da série de Fibonacci.
Resolva os exercícios a seguir de 3 modos diferentes, ou seja: utilizando os comandos while { ... }; do { . . . }, while { . . .} e for { . . .}. Mais ainda: as visualizações deverão ocorrer: percorrendo o(s) vetor(es) em ordem crescente e, após, em uma outra versão do exercício, percorrendo o(s) vetor(es) ordem decrescente.
Escreva um programa que preencha, a partir do teclado, duas estruturas distintas do tipo vetor com os nomes e as notas (as notas têm de estar contidas no intervalo 0 ( nota ( 10) dos alunos, respectivamente, de uma turma de 100 alunos e, após, exteriorize somente os nomes dos alunos que obtiveram notas iguaisou maiores que 5 (cinco).
b)	Escreva um programa que preencha, a partir do teclado, duas estruturas distintas do tipo vetor com as idades de 100 pessoas. A primeira estrutura do tipo vetor deverá receber somente as idades das pessoas do sexo masculino, enquanto a segunda deverá armazenar as idades das pessoas do sexo feminino. Após, o programa deverá exteriorizar os nomes, o sexo e as idades das pessoas que possuem idade compreendida entre 20 (vinte) e 40 (quarenta) anos, inclusive. 
7)	Escreva um algoritmo que calcule e visualize a soma S conforme a representação abaixo. 
S ( ( a1 – an ) 2 ( ( a2 - an (1 ) 2 ( ( a3 - an (2 ) 2 ( ... ( ( an - a1 ) 2
	
Os valores de a1 a2 , ... , an deverão ser naturais consecutivos e o valor n deverá ser informado através do teclado, e estar compreendido no intervalo fechado [ 1 , 100 ] .
 
8.1.	“Arryas” unidimensionais (vetores) de caractreres – Strings
(	Considerações Gerais:
1.	São arrays de caracteres.
2.	Em C, toda string acaba com o caracter '\0'.
3.	Exemplo da definição de um vetor de caracteres: char str [ 7 ];
4.	A consideração 3 define str como vetor de 6 caracteres mais o caractere de final de string.
Exemplo:	char str [ 7 ];	
str[0] = 'C';
str[1] = 'a';
str[2] = 'r';
str[3] = 'l';
str[4] = 'o';
str[5] = 's';
str[6] = '\0';
	
	C
	0
	
	a
	1
	
	r
	2
	Na memória teríamos:
	l
	3
	
	o
	4
	
	s
	5
	
	\0
	6
Podemos iniciar uma string de duas formas:
1º)		Como um vetor: 	static char str [ ] = {'C', 'a', 'r', 'l', 'o', 's', '\0'}; 	// assume 6 caracteres mais '\0' = 7 
2º)		Deixar que o compilador inicie:			static char str[ ]="Carlos"; 	// assume 6 caracteres mais '\0' = 7 
Obs.:	Não é possível a atribuição direta: 	
char str[ 7 ];
		str = "Carlos";	/* Erro: não vale a atribuição */
// Exemplo: Fazer um programa para ler um nome e dar um bom dia para o dono do nome.
// Solução 1:
#include <stdio.h>
#define TAM 100
void main()
{
    		char linha [ TAM ];
    		int c, i;
    		printf ( " \n Qual é o seu nome ? " ) ;
     		for (i = 0; (c = getchar ( ) ) != '\n'; i++) 	linha [ i ] = c;
   		linha [ i ] = '\0';
    		printf (" \n Tenha um bom dia " ) ;
    		for (i = 0; linha [ i ] != '\0'; i++) putchar ( linha [ i ] );
    		putchar('\n');
}
A função getchar retorna um caractere do teclado e a função putchar coloca um caractere no vídeo. Estas funções, bem como as outras de IO podem ser redirecionadas. Em caso de erro, a função getchar retorna EOF.
// Solução 2:
#include <stdio.h>
#define TAM 100
void	main()
{		
char linha [ TAM ];
    		printf	(" \n Qual é o seu nome ? " );
    		
gets 	( linha );
    		
printf (" \n Tenha um bom dia !!!" );
    		puts 	(linha);
}
A função gets tem por finalidade ler uma string e a puts imprimir uma string. A função puts fornece automaticamente uma mudança de linha após a impressão.
Formatos: 		//	Ponteiros serão abordados com detalhes mais adiante)
						char *gets ( char *buf );
					
//	Retorna ponteiro para a string lida ou NULL em caso de erro.
						int puts ( char *buf );
					
//	Retorna '\n' se imprimiu bem ou EOF em caso de erro.
Para atribuição de strings, usa-se a função strcpy, que possui o formato:
					char *strcpy (char *destino, char *origem);
 Exemplo:	strcpy (str, "casa"); 		/* str passa a ter "casa" */
 
Para se saber o tamanho de uma função, usa-se a função strlen, que possui o formato:
					int strlen (char *st);
//	Exercício: construir a função strlen.
// 	Solução 1:
int 	strlen (char cadeia [ ] )
{		int len = 0, I = 0;
   		while (cadeia [ I ] != '\0')		{	++len ;	++ i;	}
    		return ( len );
}
//	Solução 2:
int strlen ( char cadeia [ ] )
{
    		int i;
    		for (i = 0; cadeia [ i ] != '\0'; i++)  ;		/* bloco nulo */
    		return ( i );
}
// Exercício: Construir uma função que copia uma string para um vetor de caracteres
// Solução 1:
void stringcpy (char[ ], char[ ]);
void stringcpy (char s1[ ], char s2[ ])
{
    		int i;
    		for (i = 0; s2 [ i ] != '\0'; i++)
        	s1[ i ] = s2 [ i ];
    		s1[ i ] = '\0';
}
// Solução 2:
void stringcpy(char s1[ ], char s2[ ])
{
    		int i = 0;
    		while ( (	s1[ i ] = s2 [ i ]) != '\0' ) 
      				i++;
}
9.	“Arrays” bidimensionais (matrizes bidimensionais)
Formato:	<tipo> <nome> [ <d1>][ <d2> ];
Onde:
d1 	( 	número de linhas (varia entre 0 e d1 ( 1)
d2 	( 	número de colunas (varia entre 0 e d2 - 1)
Exemplo:
	int b[3][5];	(	3 linhas e 5 colunas
 
Inicialização na declaração:
	static int b[ ][ 3 ] =	 (		static int b[ ][3] =
	{										{
	    		1, 1, 1,				|	    			{1, 1, 1},
	    		2, 2, 2,				|	    			{2, 2, 2},
	    		3, 3, 3					|	    			{3, 3, 3}
};									    	};
 
A iniciação também pode ser feita de forma esparsa. Por exemplo:
	static int b[ 3 ][ 3 ] = 
   	{
	    			{1, 1},
	    			{1}
	};
A matriz gerada pela inicialização acima será:			1 1 0
																	1 0 0
																	0 0 0
Obs.: (1) Para este tipo de iniciação é necessário que se forneça o número de linhas e de colunas; (2) o armazenamento em C é feito por linhas; e (3) ao se passar uma matriz bidimensional, a única dimensão fixa é o número de colunas (ao contrário do Fortran que fixa o número de linhas).
// Exemplo 
		void	main ( )
	    {		
int mat[ 10 ][ 20 ];
	    					. . .
	    			f (mat, 10, 20);
		}
	
A função f ( ) poderia receber a matriz de duas formas:
	
void f (int mat [10][20], int lin, int col)	 		ou		
void f	 (int mat [ ][20], int lin, int col)
{
		   comandos;
 } 
//	Exemplo de como zerar uma matriz:
void zera (float mat[ ][ 20 ], int, int);	/* protótipo */
void 	main ( )
{		
float mat [ 10 ][ 20 ];
    		zera (mat, 10, 20);
}
void 	zera (float mat[ ][ 20 ], int lin, int col)
{		
register int i, j;
    		for (i = 0; i < lin; i++)
    		for (j = 0; j < col; j++) mat[ i ][ j ] = 0.0;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Exercícios de Fixação
 
Escreva um algoritmo que preencha uma certa matriz quadrada de ordem 4 (quatro) com números inteiros, informados através do teclado, e que, após:
Visualize todos números pertencentes a Diagonal Principal – DP ;
Visualize todos números pertencentes a Diagonal Secundário – DS ;
Visualize todos números que estejam acima da Diagonal Principal ; e
Visualize a soma de todos os números que estejam abaixo da Diagonal Secundária.
Escreva um algoritmo que preencha automaticamente uma certa matriz quadrada de ordem 8 (oito) conforme a representação gráfica abaixo: 
 colunas
 					 1	 2	 3 4 	5 6 7 8
	
	1
	A
	A
	A
	A
	A
	A
	A
	A
	
	2
	A
	B
	B
	B
	B
	B
	B
	A
	
	3
	A
	B
	C
	C
	C
	C
	B
	A
	linhas
	4
	A
	B
	C
	D
	D
	C
	B
	A
	
	5
	A
	B
	C
	D
	D
	C
	B
	A
	
	6
	A
	B
	C
	C
	C
	C
	B
	A
	
	7
	A
	B
	B
	B
	B
	B
	B
	A
	
	8
	A
	A
	A
	A
	A
	A
	A
	A
 
Escreva um algoritmo que preencha duas matrizes quadradas de ordem 3 com valores inteiros maiores que 0 (zero) e menores que 101 (cento e um), informados através do teclado, sem permitir que sejam armazenados valores repetidos em cada matriz. 
Após, o algoritmo deverá visualizar todos os valores ímpares e múltiplos de 11 sem, no entanto, utilizar o comando mod. 
Mais: após, o algoritmo deverá executar a geração automática de uma terceira matriz que represente a soma das outras duas matrizes, também sem permitir a ocorrência de repetição de valores.Quando ocorrer repetição o valor repetido deverá ser substituído por 0 (Zero) na matriz soma. Finalmente, o algoritmo deverá visualizar os valores presentes na terceira matriz – matriz soma – que façam parte dos 10 (dez) primeiros termos da série de Fibonacci.
Escreva um algoritmo que preencha duas matrizes de dimensões 5x3 e 3x2, respectivamente, e que, após, calcule e visualize a matriz produto delas. 
 
 
 
 
 
 
 
 
 
 
 
 
 
10.		Funções
Formato:	< tipo > < nome da função > ( < parâmetros > )
	    			{
	    						declaração de variáveis locais;
	    						corpo da função;
	    			}
SYMBOL 183 \f "Symbol" \s 10 \h	< tipo > é o tipo do valor a ser retornado pela função;
SYMBOL 183 \f "Symbol" \s 10 \h	se uma função não retorna valor, o seu tipo é void;
SYMBOL 183 \f "Symbol" \s 10 \h	os parâmetros são sempre passados por valor, isto é, uma cópia do valor da variável é passado para a função;
SYMBOL 183 \f "Symbol" \s 10 \h	para arrays (vetores e matrizes) é passado como valor o endereço da primeira posição;
SYMBOL 183 \f "Symbol" \s 10 \h	deve-se sempre usar o protótipo da função;
SYMBOL 183 \f "Symbol" \s 10 \h	variáveis 'char' são transformadas em 'int' e variáveis 'float' são transformadas em 'double'.
O formato da função varia entre o padrão K & R e o ANSI. O padrão K & R pode ser usado no ANSI.
formato K & R				|		formato ANSI
int soma (a, b)				|		int soma (int a, int b)
int a, b;						|		{
{								|	    			return ( a + b );
				return (a+b);		|		}
}								|
O valor retornado por uma função pode ou não ser utilizado (e.g.: a função printf ( ) ). 
Mais: pode-se retornar de qualquer ponto da função, bastando usar a instrução return ( ).
// Exemplo: Fazer um programa para ler um número e imprimir o seu fatorial utilizando uma
// 				 função para ler o número, uma para cálculo do fatorial e uma para mostrá-lo. 
# include <stdio.h>
long factorial 	(long);
long leval 		(void);
void printfat 	(long);
void main ( )
{
    		long fat, val;
    		val = leval ( );
    		fat = factorial (val);
    		printfat (fat);
}
long leval ( )
{ 	
long x;
    		printf (" \nEntre o valor a ser calculado: ");
    		scanf("%ld", &x);
    		return ( x );
}
void printfat (long y)
{
    		printf (" \nFatorial = %ld\n", y);
}
long fatorial (long a)
{
    		long fator = 1;
    		long i;
    		for (i = 1; i <= a; i++)	fator *= i;
    		return ( fator );
}
 
 
11.		O Tipo “Pointer” (Ponteiro) 
11.1.	Definição
Um ponteiro é uma variável que contem como valor um endereço. 
Para definirmos uma variável como ponteiro, devemos fornecer o tipo da variável para qual apontará e um nome.
Embora os endereços de variáveis de um tipo (e.g.: int), sejam semelhantes aos de outros tipos como float, char ou double, é importante não misturá-los. Para a declaração de um ponteiro tem-se que indicar o tipo de variável para o qual ele irá apontar, pois ao serem feitas operações aritméticas com os ponteiros, eles irão variar em função de seu tipo.
 
 Principais vantagens do uso:
SYMBOL 183 \f "Symbol" \s 10 \h	superar as restrições de passagem de argumento, por valor, para funções;
SYMBOL 183 \f "Symbol" \s 10 \h	acessar elementos de arrays de modo alternativo ao uso de índices;
SYMBOL 183 \f "Symbol" \s 10 \h	permitir a criar estruturas dinâmicas (árvores e listas encadeadas) bem como suas manipulações.
Forma de definição:
	<tipo> *<nome>;
Exemplos:			int *p;		( 	p é um ponteiro para inteiro
						float *pf;	( 	pf é um ponteiro para float
						int i, *pt;	( 	pt é um ponteiro para inteiro
						pt 	= &i;		( 	pt	recebe oendereço de i 
*pt 				( 	5	(conteúdo do endereço dado por pt)
void 	*pvoid;	( 	ponteiro para qualquer tipo
Dado: float x, y, *p, *q;
Temos como operações possíveis:
	p = &x;		( 	p aponta para x
	
y = *p;		( 	y recebe o valor que está no endereço dado por p
	
q = p;		( 	q e p apontam para o mesmo endereço
Erros comuns:
int *p;
*p = 10;				// não apontou para nenhuma variável
float val;
int *p;
p = &val;			// tipos incompatíveis
11.2.	Iniciação de ponteiros na definição
		int i = 7, p = &i;	 /* a inicialização é de p e não de *p */
		
11.3.	Passagem de parâmetros por endereço (referência)
Para que se possa passar uma variável por referência, devemos passar um ponteiro para esta variável ou, em outras palavras, o seu endereço.
 
/*
Exemplo: ler dois valores e trocá-los de ordem
*/
#include <stdio.h>
void swap	(int *, int *);	/* protótipo de swap */
void 	main( )
{
    		int a, b;
    		scanf (" %d %d", &a, &b);	/* le os dados */
    		
swap (&a, &b);					/* chama a função swap */
    		
printf ("%d : %d\n", a, b);	/* imprime resultado */
}
void swap(int *x, int *y)
{
    		int tmp;
    		tmp = *x;
    		*x = *y;
    		*y = tmp;
}
 // 	Exemplo: fazer uma função que tenha o seguinte protótipo:
void soma (int *r, int a, int b);
# include <stdio.h>
void soma( int *r, int a, int b);		// Os nomes dos parâmetros estão declarados por opção. 
void main ( )
{
    		int x, y, z;
    		printf ( " \n Entre dois números: \n");
    		scanf ("%d %d", &x, &y);
    		soma (&z, x, y);
    		printf (" \n A soma é: %d\n", z);
}
void soma (int *r, int a, int b)
{ 
*r = a + b; 
}
 
12.		A relação entre ponteiros e Arrays
	Um nome de array é um endereço ou ponteiro, que é fixo.
//	Exemplo:
	
int k, a[100], *p;
	p = a;				// 	p possui o endereço do primeiro elemento de a
// 	ou
	p = &a[ 0 ];	//	p possui o endereço do primeiro elemento de a
	Para que p aponte para o elemento seguinte, basta incrementar o endereço de 1.
	p = a + 1;		// 	p = &a [ 1 ];
	p++;				//	p aponta para o próximo elemento.
	k = *p++;		//	k ( valor do elemento apontado por p e p aponta para o próximo elemento
//	Exemplos para zerar um vetor:
	for (i = 0; i < 100; i++)				// com índice 
	    a[ i ] = 0;
ou
	for (i = 0, p = a; i < 100; i++)		// com ponteiro 
	    *p++ = 0;
 
// 	Exemplo: Criar uma função que retorne o tamanho em bytes de uma cadeia de caracteres
// 	usando ponteiro.
// Solução 1:
# include <stdio.h>
int strlen (char* str);
void main ( )
{
    		static char str [ ] = "Esta string tem 30 caracteres.";
    		printf (" \nTamanho da string: %d caracteres.\n", strlen (str) );
}
 
 
int 	strlen (register char *s)	{		register int n;
    												for (n = 0; *s != '\0'; s++) ++n;
return ( n );
}
 
// Solução 2:
# include <stdio.h>
int strlen (char *str);
void 	main ( )			{		static char str[ ] = "Esta string tem 30 caracteres.";
    									printf ("\nTamanho da string : %d caracteres.\n", strlen (str) );
}
int		strlen(register char *s)
{		register int n=0;
    		while (*s++)	++n;
    		return(n);
}
// Solução 3:
#include <stdio.h>
int 	strlen (char *str);
void 	main ( )
{		static char str[ ] = "Esta string tem 30 caracteres.";
    		printf (" \n Tamanho da string : %d caracteres.\n", strlen (str) );
}
int 	strlen (register char *s)
{		register char *ps;
    		ps = s;					// ps aponta para o inicio da string 
    		while (*ps)	ps++;
    		return(ps - s);
}
// 	Exemplo: Criar a função strcpy, que copie o conteúdo de uma string em outra.
# include <stdio.h>
char *strcpy (char *d, char *o);
void 	main ( )
{		static char orig[ ] = "teste", dest [ 20 ];
    		strcpy (dest, orig);
    		printf("origem = %s ; destino = %s\n", dest, orig);
}
char 	*strcpy (char *dest, char *origem)
{		char *d = dest;
//	O while a seguir faz a copia e incrementa os ponteirosde cada string, até aparecer um
// 																			caractere nulo significando fim de string.
// 	Alguns compiladores darão um aviso (warning), achando que se deseja fazer um teste ao
// 	Invés de atribuição com teste, que é o que se pretende fazer realmente.
    	while (*d++ = *origem++);	/* sem bloco */
    	return (dest );
}
 
// 	Exemplo: Criar a função strcmp que tem como finalidade comparar o conteúdo de uma 
// 	string com o de outra. A função tem o seguinte formato: int strcmp (char *s, char *t);
// 	Esta função retorna: (a) 0 se as strings forem iguais; (b) < 0	se s < t; e (c) > 0 se s > t
# include <stdio.h>
int strcmp (char *s, char *d);
void main ( )
{
    		char s1 [ 20 ], s2 [ 20 ];
    		printf	(" \nEntre a primeira string: ");
    		gets 	( s1 );
    		printf (" \nEntre a segunda string: ");
    		gets	( s2 );
    		if ( strcmp (s1, s2) )
        		printf (" \n Diferentes.\n");		/* <> de zero */
    		else
        		printf (" \n Iguais.\n");
}
int strcmp (char *s1, char *s2)
{
    		while (*s1 == *s2)
        			if (*s1++)
            			 s2++;
        			else
            			return(0);
    		return(*s1 - *s2);
    }
Para definição e iniciação de strings, também é possível o seguinte tipo de instrução:
    							char *mens = "Divisão por zero";
A definição acima define mens como sendo um ponteiro para a string "Divisão por zero".
 
13.		Ponteiros e arrays bidimensionais
	Como para vetores unidimensionais, o nome de um array é um ponteiro fixo. Assim, as seguintes instruções são equivalentes e geram o mesmo código:
b[ i ][ j ]		*(*(b + i) + j)		*(b + i * ncolun + j)
	O esquema abaixo representa o acesso à vetores bidimensionais.
	
 
 
Como para vetores unidimensionais, existem formas de se acessar matrizes de uma forma mais eficiente, como veremos a seguir.
Definição de ponteiros para matrizes.
	int mat[10][20], (*plin)[20];
	plin = mat;
	Nas instruções acima, definimos plin como sendo um ponteiro para uma linha de um array com 20 colunas e mandamos que ele aponte para o primeiro elemento.
	Forma de armazenamento na memória:
�
Para acessar um elemento da matriz via ponteiro:
	(*plin)[j]	ou	*(*(plin) + j) 
 
 
Para se passar para a próxima linha:
		plin++;
	plin		plin + 1		plin + 9
	
Nota: 	( * plim) [ 20 ] define um ponteiro para linha de um vetor com 20 colunas, enquanto que *plin[20] define um vetor de 20 elementos do tipo ponteiro.
//	Exemplo: Calcular a média dos elementos de uma coluna de uma matriz de 3 colunas.
//	Solução:
# include <stdio.h>
double test_avg (int [ ][ 3 ], int, int);
void	main ( )
{		double res;
    		static int board [ ][ 3 ] =	{		1,		2,		3,
         											4,		5,		6,
         											7,		8,		9,
        											10,		11,		12
        									};
    			res = test_avg ( board, 4, 2 );
    			printf (" %lf\n", res);
}
double 	test_avg (int tab[ ][3], int maxlin, int col)
{			long sum = 0;
    			int i, (*ptr)[3] = tab;
    			for (i = 0; i < maxlin; i++)
        				sum += (*ptr++) [col ];
 		return ( (double) sum / maxlin );
}
// Exemplo: calcular a média dos elementos de uma linha de uma matriz de 3 colunas.
// Solução:
# include <stdio.h>
double test2_avg ( int[ ][ 3 ], int);
void main ( )
{
    		static int board[ ][3] = 
        	{
         			1,  		2,  		3,
         			4,  		5,  		6,
         			7,  		8,  		9,
        			10, 	11, 	12
      	};
    		double res;
    		res = test2_avg (board, 1);		/* calcular para linha 1. */
    		printf (" %lf\n", res);
}
double test2_avg(int tab[][3], int linha)
{
    		long soma = 0;
    		int i;
    		int *p = &tab[linha][0];
    		for (i = 0; i < 3; i++)
    				soma += *p++;
    		
return ( (double) soma / 3 );
}
Notas:	&tab[n][0] 	=	endereço do elemento (n, 0) em tab
		tab[n] 		= 	linha “n “de tab
O nome de um array bidimensional quando usado com um único índice é um ponteiro para o primeiro elemento de uma determinada linha.
13.1	(	Arrays tridimensionais:
	Seguem as mesmas regras do bidimensional. Exemplo:
						int v [ 3 ][ 4 ][ 5 ]
	define um array v com dimensões 3 x 4 x 5.
	
Definição de um vetor 3D em funções:
						int vet[ ][ 4 ][ 5 ] 		ou 	int (*vet)[ 4 ][ 5 ]
 
 
 
 
 
 
 
13.2	(	Arrays de ponteiros (ragged arrays)
São arrays com linhas de tamanho variável. Um array deste tipo é composto por ponteiros para outras variáveis e o seu uso mais comum é para acessar tabelas de strings.
Exemplo: definir um vetor de ponteiros para uma tabela de dias da semana.
static char *dias[ ] = 
{
    		"segunda", "terça", "quarta",
    		"quinta", "sexta", "sábado", "domingo"
};
Para esta definição, dias é um array de 7 ponteiros para caracteres.
O esquema a seguir apresenta a organização interna da tabela de dias da semana.
	�
Os elementos de 'dias' podem ser acessados de duas maneira:
1.	dias [ i ]
	printf ("%s\n", dias[2]);						// 	será impresso "quarta"
2.	dias [i ][ j ]
	printf ("%c\n", dias[ 1 ][ 2 ]); 				// será impresso ' r '
	//	dias [ 1 ] 	( 	"terça" 		e 		dias [ 1 ][ 2 ] 	( 	r 	(de "terça")
// 	Exemplo: Fazer uma função para imprimir 'dias'.
#i nclude <stdio.h>
void printab (char *[ ], int);
void printab (char *tab[ ], int n)
{
    		int i;
    		for (i = 0; i <= n; i++)
    				printf(" %s\n ",tab [ i ]);
}
Nota: Um elemento em um array de pointers pode ser usado como se ele fosse um pointer para o primeiro elemento de uma linha de um array bidimensional (tab [ i ]). 
 
 
 
 14. Alocação Dinâmica de Memória
	A linguagem C possui uma série de funções que permitem alocar e liberar áreas de memória, fazendo com que se possa usar a memória gasta por variáveis, vetores, matrizes, listas, pilhas, etc. de uma forma mais eficiente.
	Quando necessário, o usuário pede uma área e a utiliza e, quando esta área não for mais necessária, ela é devolvida ao sistema operacional, de forma a poder ser utilizada em outra etapa do programa.
	O esquema abaixo apresenta o mapa da memória de um programa em C.
	Área de Código
	Área de Variáveis Estáticas e Globais
	Stack
	Heap
	A área disponível para alocação dinâmica se encontra na Heap.
	As principais funções para manipulação de memória estão definidas no header stdlib.h e são:
SYMBOL 183 \f "Symbol" \s 10 \h	malloc
SYMBOL 183 \f "Symbol" \s 10 \h	calloc
SYMBOL 183 \f "Symbol" \s 10 \h	realloc
SYMBOL 183 \f "Symbol" \s 10 \h	free
void *malloc(unsigned int);
		ptr = malloc(tam);
Aloca uma área de tam bytes. Se alocou corretamente, retorna um pointer para o primeiro byte da área alocada e em caso de erro retorna NULL.
// 	Exemplo 1:
int *ptr;
. . .
ptr = malloc(sizeof(int));
if (ptr == NULL)		{		printf(" \nErro de alocação");		
exit ( 1 );
}
*ptr = 10;
. . .
// 	Exemplo 2:
int *ptr, *ptraux, i;
. . .
ptr = malloc(sizeof(int) * 100);
if (ptr == NULL)
{		printf("Erro de alocação");
		exit(1);
}
ptraux = ptr;
for (i = 0; i < 100; i++) *ptr++ = i;
ptr = ptraux;
 ...
 
(	Vetores gerados dinamicamente
//	Obtém área para um vetor do tipo float. O número de elementos é pedido pelo programa.
//	Após a obtenção da área necessária são pedidos dados para o seu preenchimento.
# include <stdio.h>
# include <stdlib.h>
void prtvet (float*, int);
void main ( )
{		int num, i;
    		float *pvet, *pinic;
    		printf ("\nEntre com número de elementos:\n");
    		scanf ("%d", &num);
    		pvet = (float*) malloc(num * sizeof(float));
    		if (!pvet)
        	{	printf (" \nErro. Falta de memória.\n");exit ( 1 );
        	}
   		pinic = pvet;
    		for (i = 0; i < num; i++)
        	{		printf (" \n%d -> ", i + 1);
        			scanf ("%f", pvet++);						//	Não funciona no Turbo C
        	}
    		pvet = pinic;
    		prtvet(pvet, num);									//	Imprime o vetor
    		free(pvet);
}
void prtvet (float *p, int n)
{
    		int i;
    		for (i = 0; i < n; i++)
        			printf("\n\%d -> %f", i + 1, *pv++);
}
void *calloc (unsigned int, unsigned int);
		ptr = calloc(num, size);
Aloca uma área de 'tam' * 'num' bytes. Se alocou corretamente, retorna um pointer para o primeiro byte da área alocada e em caso de erro retorna NULL. A área alocada é automaticamente zerada.
 
// 	Exemplo 1:
int *ptr;
. . .
ptr = calloc(1, sizeof(int));
if (ptr == NULL)
{		printf ("Erro de alocação");
		exit (1);
}
*ptr = 10;
 		. . .
//	Exemplo 2:
int *ptr, *ptraux, i;
 . . .
ptr = calloc(100, sizeof(int));
if (ptr == NULL)
{		printf (" \nErro de alocação");
		exit ( 1 );
}
ptraux = ptr;
for (i = 0; i < 100; i++) 	*ptr++ = i;
ptr = ptraux;
 . . .
void 	free ( void *);
free (ptr);
void *realloc (void *, unsigned int)
		nptr = realloc(old, tam);
A função realloc altera o tamanho da área alocada por malloc ou calloc. O novo tamanho pode ser maior ou menor do que o tamanho original. Quando chamada, retorna um pointer para a nova área alocada, sendo old um pointer para a área antiga e tam' o novo tamanho em bytes. Em caso de erro, a função retorna NULL e o programa deve ser interrompido, já que a área original poderá estar comprometida.
 
Exemplo:
#include <stdio.h>
#include <stdlib.h>
void prtvet(float*, int);
void 	main ( )
{		int num, i;
   		char *p;
    		p = (char*) malloc(23);
    		strcpy (p, "AQUI TEM 22 CARACTERES");
    		printf ("\n%s\n", p);
    		p = realloc (p, 24);
    		strcat(p, ".");
    		printf(" \n%s\n", p);
    		free ( p );
}
 
(	Libera a área alocada por malloc, calloc ou realloc.
// 	Exemplo:
int *ptr, *ptraux, i;
 ...
ptr = malloc(sizeof(int) * 100);
if (ptr == NULL)
{		printf (" \nErro de alocação");
		exit ( 1 );
}
ptraux = ptr;
for (i = 0; i < 100; i++) *ptr++ = i;
ptr = ptraux;
 . . .	
free (ptr);
 . . .
15.		Definição de novos tipos
Para definição de novos tipos, é utilizada a instrução typedef.
Formato:
		typedef <tipo existente> <novo tipo>;
//	Exemplos:
//	Para se definir o tipo 'contador':
	typedef 		int 	contador;
	contador	 	i, j;					// É o mesmo que int i, j
 
Para se definir o tipo string:
	typedef char string [ 81 ];
	string text;							// É o mesmo que char text[81]
Para se definir o tipo 'boolean':
	typedef int boolean;
	# define FALSE 0
	# define TRUE 1
			. . .
	boolean ok = TRUE;
		if (ok) . . .
Para se definir o tipo ptrchar (pointer para caractere):
	typedef char *ptrchar;
	ptrchar pchar;						// É o mesmo que char *pchar
 
16.		Estruturas	(struct (
Uma etrutura – struct – é usada quando há necessidade de se combinar dados de um mesmo tipo ou de tipos diferentes em um único objeto ou registro.
Forma de definição:
struct <nome>		{			<tipo 1> < campo 1 , campo 2 , . . . , campo n>;
    									<tipo 2> < campo 1 , campo 2 , . . . , campo n>;
																:
    									<tipo N> < campo 1 , campo 2 , . . . , campo n>;
};
 
 
Exemplos:
struct s1								// 	Define estrutura chamada s1 contendo os seguintes campos
{
    		int a;							//	Define um campo do tipo inteiro denominado a
    		char nome [ 81 ];			//	Define um array de caracteres denominado nome 
    		char ender [ 100 ]; 			// 	Define um array de caracteres denominado endereço
};										//	Aqui, a struct s1 passa a ser um tipo
// Agora é possível utilizar a struct s1 para definir duas variáveis estruturadas: info1 e info2 
struct s1 info1, info2;
 
(	Uma outra forma de definirmos este tipo de variáveis é: 
struct	{	int x, 	y;	}	v1, v2;
// 	No exemplo acima, não foi criado um tipo, e sim duas variáveis (v1 e v2) do tipo struct 
// 	Também é possível o uso do typedef em conjunto com as estruturas:
typedef struct s1 t_s1;
	t_s1 info1, info2;			// Foram criadas duas variáveis info1 e info2 do tipo struct t_s1
Acesso aos membros de uma estrutura:
		<variável>.<campo>;
 
 Exemplos:
	info1.a = 10;
	strcpy(info1.nome, "teste");
	struct s2
	{		
int a;
	   		char *nome;					/* nome é um ponteiro */
	};
	struct s2 info3;
	
info3.a = 10;
	info3.nome = "José da Silva";		/* nome é um ponteiro */
Operações possíveis entre estruturas:
A partir da definição: struct s1 v1, v2; temos:
1) atribuição:
	v1 = v2;
2) comparação (somente igualdade e desigualdade)
	if (v1 == v2) 
	{
	     . . .
	}
É possível perguntarmos se duas estruturas são iguais ou diferentes, mas não se uma é maior ou menor do que a outra. No entanto, os campos (membros) de uma estrutura podem ser comparados com os de outra.
Apesar de na versão ANSI podermos passar estruturas por valor para as funções, isto deve ser evitado, já que torna a chamada da função mais lenta e aumenta a área ocupada no stack. 
A forma mais indicada para se passar estruturas é utilizar pointers, como será visto mais adiante.
 
 
 
 
16.1	Iniciação de estruturas
Para alguns compiladores, é necessário que as variáveis locais sejam estáticas.
struct s_carta
{		int carta;
    		char naipe;				/* Ouro, Copas, Paus e Espadas */
};
struct s_carta c = 
{		12,
    		'O'							/* inicializa como dama de ouros */
};
16.2	Campos de bits
Os campos de bits ou bitfields tem como principal finalidade a economia de memória, porém em alguns casos o código gerado para a sua manipulação pode ser grande, gastando mais memória do que economizando.
Forma de definição:
	struct <nome>
{		<tipo 1> <nome 1> : <tamanho em bits>;
	   		<tipo 2> <nome2> : <tamnaho em bits>;
	    						. . .
	    		<tipo N> <nome n> : <tamanho em bits>;
	   };
	//	Obs.: <tipo> pode ser: int, unsigned int e signed int.
 
 // Exemplo:
struct baralho
{		unsigned carta : 4;		/* 	0 a 15 */
    		unsigned nipe : 2;		/* 	0, 			1, 			2, 				3 		*/
    										/* 	ouros,		copas,	espadas, 	paus 	*/
};
struct baralho x;
x.carta = 9;
x.nipe = 2;							/* 9 de espadas */
Ao contrário de estruturas normais, os bitfields não podem ser usados com pointers.
16.3	Uniões
Permitem armazenar em uma mesma região valores de tipos diferentes.
Forma de definição:
	union <nome>
	    {
	    			<tipo1> <campo1>;
	    			<tipo2> <campo2>;
	    					. . .
	    			<tipon> <campon>;
	    };
 
 //	Exemplo:
union mixed
{
    			char c;
    			float f;
    			int i;
};
 
union mixed x;
x.c = 'A';
 . . .
x.f = 10.0;
 . . .
x.i = 1;
A área reservada para uma variável deste tipo é calculada pelo tamanho do maior campo. No exemplo acima, a área reservada teria o tamanho de um float.
Devemos notar que uma variável deste tipo guarda apenas um valor de cada vez, isto é, ao armazenar o dado de um novo tipo apaga o do tipo anterior.
A seguir é apresentado um exemplo no qual se monta em array de estruturas que guarda elementos de "tipos" diferentes.
/*	Exemplo do uso combinado de estrutura e união:
 	Cria um array denominado tabela e dimensão TAMANHO.
Cada elemento do array contem uma estrutura que consiste de um ponteiro para caractere (nome), um inteiro (tipo) e um membro do tipo union chamado "dados".
Cada membro dados do array pode conter int, float ou char.		*/
# include <stdio.h>
# define INTEGER 0
# defineFLOATING 1
# define CHAR 2
# define TAMANHO 6
 
void main ( )
{
    		Struct	S1
        {
        			char *nome;
        			int tipo;
        			union
            		{
            				int i;
            				float f;
            				char c;
            		} dados;
        } 	tabela [TAMANHO];	// Cria uma um vetor de estruturas denominado tabela
    			int j;
 	// 	Inicia os elementos da estrutura 
    		tabela[ 0 ].nome 		= 	"Cesar";
   		tabela[ 0 ].tipo 			= 	CHARACTER;
    		tabela[ 0 ].dados.c		= 	'A';
    		tabela[ 1 ].nome 		= 	"do Vale ";
    		tabela[ 1 ].tipo 			= 	CHARACTER;
    		tabela[ 1 ].dados.c		= 	'A';
    		tabela[ 2 ].nome 		= 	"Ferrari ";
    		tabela[ 2 ].tipo 			= 	CHARACTER;
    		tabela[ 2 ].dados.c 	= 	'A';
    		tabela[ 3 ].nome 		=	"Idade ";
    		tabela[ 3 ].tipo 			= 	INTEGER;
    		tabela[ 3 ].dados.i 	= 	42;
    		tabela[ 4 ].nome 		= 	"Salário ";
    		tabela[ 4 ].tipo 			= 	FLOATING;
    		tabela[ 4 ].dados.f 	= 	7200.56;
    		tabela[ 5 ].nome 		= 	"Imposto ";
    		tabela[ 5 ].tipo	 		= 	FLOATING;
    		tabela[ 5 ].dados.f 	= 	2785.89;
    		for (j = 0; j < TAMANHO; j++)
   		{
        			printf (" %s ", tabela[ j ].nome);
        			switch (tabela[ j ].tipo)
         			{
        					case 	INTEGER:
printf (" %d\n", tabela[ j ].dados.i);
            						break;
 
        					case 	FLOATING:
printf (" %.2f\n", tabela[ j ].dados.f);
            						break;
        					case 	CHARACTER:		
printf ("%c\n", tabela[ j ].dados.c);
            						break;
        					default:				
printf ("Tipo desconhecido %d - elemento %d.\n", tabela[ j ].tipo, j);
            						break;
       			}
    		}
} 
 
16.4	Pointers para Estruturas
Como vimos anteriormente, devemos passar as estruturas através de pointers e não por valor. Isto deve ser feito mesmo que não alteremos nenhum dos campos da estrutura.
/* Exemplo - Pointer para estruturas */
#include <stdio.h>
struct s_data
{		
int dia, mes, ano;
};
typedef struct s_data sdata;
void prtdata (sdata *);
void 	main ( )
{		sdata data;
    		data.dia 		= 15;
    		data.mes 	= 3;
    		data.ano 	= 1988;
    		prtdata ( &data);		/* passa o endereço da estrutura data */
}
void prtdata(sdata *data)
{
    		printf("	%d/% d/ %d \n", (*data).dia, (*data).mes, (*data). ano);
}
	Existem duas formas de se acessar os valores de uma estrutura através de pointers:
	(* < pointer >).< componente >	ou 	< pointer > (( < componente >;
Exemplo:
	sdata data, *pdata;
	pdata = &data;
	(*pdata).dia 	= 31;				// ou	pdata((dia = 31;
	(*pdata).mes 	= 12;				// ou	pdata((mes = 12;
	(*pdata).ano 	= 1989;			// ou	pdata((ano = 1989;
 
 
16.5.	Ponteiro para percorrer array de ponteiros.
Como para os outros arrays, o nome de um array de ponteiros é um ponteiro para o primeiro elemento do array. Quando se passa um array de ponteiros como parâmetro, o que realmente se passa é um pointeiro para o primeiro elemento do array.
 
// Exemplo: Imprimir tabela 'dias'.
typedef char *CHARPTR;			/* define tipo pointer para char */
void	print_tab(CHARPTR *tab_ptr, int n)
{		CHARPTR *end_ptr = tab_ptr + (n - 1);
    		while (tab_ptr <= end_ptr)
        			printf (" %s\n", *tab_ptr++);
}
 
Esquema dos ponteiros:
	
17. 	Ponteiros para funções
Permitem passar funções como argumentos.
Forma de definição:
		< tipo > (* func_ptr ) ( < tipos dos argumentos > );
Nota: se não forem colocados os parênteses, estará sendo defininda uma função que retorna um pointer para <tipo>.
//	Exemplo:
int soma (int, int);
void 	main ( )
{		int (*ptr_soma) (int, int);
    			ptr_soma = soma;						// 	pointer para função soma
    			x = (*ptr_soma) (3,5);					//	 x 	(	soma (3, 5); 
}
// Exemplo: Fazer um programa que leia duas cadeias de caracteres numéricos ou alfanuméricos e as compare conforme o seu tipo.
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
int numcmp (char *, char *);
void check (char *, char *, int (*cmp) (char *, char *));
void	main ( )
{		char s1[ 80 ], s2[ 80 ];
    		gets (s1);					// obtém a primeira cadeia 
    		gets (s2);					// obtém a segunda cadeia
    		
if (isalpha (*s1) )		// isalpha devolve um valor ( de zero se no endereço apontado por s1
// 							houver um caractere alfabético ou zero em caso contrário
        			check (s1 ,s2, strcmp);		// computa como caracteres
    		else	check (s1, s2, numcmp);		// comp. como números 
}
void check (char *a, char *b, int (*cmp)(char *, char *))
{
    	if ( ! ( *cmp) (a, b) )
        		printf(" \n Iguais.\n");
    else
        		printf ("\n Diferentes.\n");
}
 
int numcmp(char *a, char *b)
{
    		if (atoi ( a ) == atoi ( b ) )
    			    	return ( 0 );
    		else
        			return ( 1 );
  }
Observações sobre o exemplo: 
SYMBOL 183 \f "Symbol" \s 10 \h	a função strcmp compara strings;
SYMBOL 183 \f "Symbol" \s 10 \h	a função isalpha retorna <> 0 para letra do alfabeto; e
SYMBOL 183 \f "Symbol" \s 10 \h	a função atoi transforma uma string em número inteiro
 
 18	.	Tipo enumerado
Faz com que uma variável possa ter somente um valor dentre um conjunto determinado de valores.
Forma de definição:
	enum <nome> {<conjunto de valores separados por vírgulas>};
Exemplo:
enum dia
   {segunda, terça, quarta, quinta, sexta, sábado, domingo};
     0        1       2        3        4        5        6
Este exemplo define o tipo dia. Uma variável deste tipo somente poderá receber um dos valores dados entre parênteses.
enum dia, dia1, dia2, todos[7];	/* define variáveis */
dia1 = segunda;
todos[6] = domingo;
Note que os valores entre parênteses não são strings.
Uma outra forma de definição possível é:
		enum {segunda, ..., domingo} dia1, dia2;
Se usarmos as definições acima, a cada valor do tipo enumerado será associado um valor inteiro, a partir de zero (0). Entretanto, podemos indicar os valores inteiros que desejamos associar:
		enum frutas {laranja = 7, lim,o = 6, jaca = 0};
		enum frutas {pera = 2, laranja, abacate, lim,o = 7};
Apesar das definições acima, os valores dos tipos enumerados não são inteiros.
Erros:
		dia1 = 1.0;
		dia2 = 2;
Para usarmos o valor inteiro associado, devemos usar um "cast" para inteiro:
		i = (int) dia1;
 
 
 
 
 
 
 
19. 	Arquivos
A linguagem C possui alguns arquivos pré-definidos e que são automaticamente abertos quando um programa começa a ser executado.
Eles são:
	
stdin			standard 	input 		(default = teclado)
	stdout			standard 	output 	(default = vídeo)
	stderr			standard 	error 		(default = vídeo)
	stdprn			standard 	printer 	(somente alguns compiladores)
Os arquivos pré-definidos stdin, stdout e stderr podem ser redirecionados pelo usuário.
O arquivo stdprn é dependente do compilador, podendo existir ou não.
Para estes arquivo pré-definidos, a leitura e impressão se passam como se estivéssemos utilizando um arquivo texto (leitura e gravação seqüenciais).
O conceito de arquivos em C é um pouco diferente do de outras linguagens. 
Na maioria das linguagens, o tipo de acesso (direto ou seqüencial) está diretamente ligado à forma de abertura do arquivo, o que não acontece em C.
Em C, o acesso a um arquivo pode ser direto ou seqüencial, sendo que esta escolha é feita conforme as necessidades do usuário.
	
O C possui funções que permitem o acesso tanto direto quanto seqüencial e permitem um acesso bastante eficiente à arquivos.
Forma de definição:
	
FILE *fp;
Para que esta definição esteja correta, é necessário que o arquivo

Continue navegando