Академический Документы
Профессиональный Документы
Культура Документы
Robson Ribeiro Linhares , Professor do Departamento Acadmico de Informtica(DAINF) da Universidade Tecnolgica Federal do Paran(UTFPR) Este documento est disponvel na HomePage:http://www.dainf.cefetpr.br/~robson/ Consideraes gerais Muitas linguagens foram desenvolvidas e por muitos anos utilizadas com diferentes objetivos e caractersticas, tais como: Fortran, Cobol, Basic, Algols, Pascal e etc. Mas o que C? C o nome de uma linguagem atualmente utilizada em diferentes reas e propsitos. Faz parte hoje de uma linguagem considerada avanada, desenvolvida nos laboratrios Bell nos anos 70. A definio formal da linguagem pode ser encontrada no livro The C Programming Language de Brian W. Kernighan e Dennis M. Ritchie (os pais da linguagem). Nos anos 80 iniciou-se um trabalho de criao de um padro chamado C ANSI (American National Standardization Institute). uma linguagem de nvel mdio, pois pode-se trabalhar em um nvel prximo ao da mquina ou como uma linguagem de alto nvel como outras existentes. Com o C podemos escrever programas concisos, organizados e de fcil entendimento, mas infelizmente a falta de disciplina pode gerar programas mal escritos, difceis de serem lidos e compreendidos. No se deve esquecer que C uma linguagem para programadores, pois impe poucas restries ao que pode ser feito. O C amigvel e estruturado para encorajar bons hbitos de programao; cabe ao programador exercitar esses hbitos. A necessidade de escrever programas, que faam uso de recursos da linguagem de mquina de uma forma mais simples e porttil, fez com que a principal utilizao do C fosse a reescrita do sistemas operacional UNIX. Sua indicao principalmente no desenvolvimento de programas, tais como: compiladores, interpretadores, editores de texto; banco de dados. Computao grfica, manipulao e processamento de imagens, controle de processos, Principais caractersticas da linguagem C a serem ponderadas: Portabilidade Gerao de cdigos executveis compactos e rpidos Interao com o sistema operacional Facilidade de uso Linguagem estruturada Confiabilidade Simplicidade
1. Elementos bsicos
1.1 Identificadores So utilizados para dar nomes a constantes, variveis, funes e vrios objetos definidos pelo usurio. As regras para formao desses nomes so: 1) Todo identificador deve iniciar por uma letra (a..z ou A..Z) ou um sublinhado 2) No pode conter smbolos especiais. Aps o primeiro caracter pode ser utilizado: letras, sublinhados e/ou dgitos. 3) Utiliza-se identificadores de, no mximo, 32 caracteres por estes serem significativos. 4) No pode ser palavra reservada e nem nome de funes de bibliotecas. Obs: letras maisculas e minsculas so tratadas de forma diferente. 1.2 Tipos de dados bsicos Tipo char int float double void 1.3 Modificadores Tipo unsigned char unsigned int Short int unsigned short int long int unsigned long int long double Nmero de bytes 1 21 2 2 4 4 10 Escala 0 a 255 0 a 655351 -32768 a 32767 0 a 65535 -2147483648 a 2147483647 0 a 4294967295 3.4E-4932 a 1.1E+4932 Nmero de bytes 1 21 4 8 0 Escala -128 a 127 -32768 a 327671 3.4E-38 a 3.4E+38 (+-) 1.7E-308 a 1.7E+308 (+-) sem valor
Observaes: 1) O modificador signed eventualmente pode ser utilizado, porm o seu uso equivale a
utilizar um tipo sem qualquer modificador. 2) A palavra int pode ser omitida. Ex: unsigned long int unsigned long
O tamanho do tipo int dependente da plataforma sobre a qual o programa compilado. Usualmente, um dado do tipo int ocupa dois bytes de tamanho.
1 1 1
1.4 Declarao de variveis A forma geral para declarao de uma varivel : tipo_da_varivel lista_de_variveis; onde tipo_da_varivel um tipo vlido em C (Sees 1.2 e 1.3) e lista_de_variveis pode ser um ou mais nomes de identificadores separados por virgula. Exemplos:
int f, i, k; float a, A, b; /* todas variveis do tipo int */2 /* todas variveis do tipo float */
1.5 Constantes Em C, constantes so valores fixos que no podem ser alterados por um programa.
1.5.1 Constantes em base decimal 1) Constantes numricas inteiras: podem ser atribudas a variveis dos tipos char e int,
modificados ou no, dependendo do valor da constante e da faixa de valores aceita pela varivel. Exemplos: 345 10 0 5000000
2) Constantes numricas no inteiras: podem ser atribudas a variveis dos tipos float e
double, modificados ou no, dependendo do valor da constante e da faixa de valores aceita pela varivel. Exemplos: -56.897 1.2E+5
0xAB (hexadecimal)
016 (octal)
/* e */ delimitam um comentrio textual, que no compilado mas que auxilia o programador na documentao do seu cdigo. Note-se que existe uma verso alternativa para delimitar um comentrio at o final da linha, usando //, porm esta verso padro C++ e no deve ser utilizada para compilao de cdigo ANSI C (C padro)
3
A tabela ASCII uma tabela padronizada que relaciona um conjunto de caracteres a valores numricos entre 0 e 255. Por exemplo, o caracter correspondente ao dgito 9 corresponde ao cdigo ASCII 57.
4
Para maiores informaes sobre nmeros octais e hexadecimais, consultar o texto sobre Bases Numricas
1.6 Instrues Uma instruo em linguagem C uma expresso seguida de um ponto e vrgula. Pode ser uma atribuio, uma chamada de funo, um teste de desvio ou um teste de lao. Exemplo de instruo de atribuio:
x = 12;
onde o sinal de igual (=) o operador de atribuio. Note-se que o operando do lado esquerdo do operador de atribuio sempre uma varivel, e que o operando do lado direito deve ser de um tipo de dado compatvel com o tipo da varivel. 1.7 Operadores
Observaes: 1) Todos os operadores so definidos para os tipos inteiros e no inteiros, exceto o operador resto (%) que no definido para variveis dos tipos no inteiros. 2) Para qualquer tipo inteiro, a adi o de um ao maior nmero da faixa daquele tipo produz o menor nmero da faixa. Os erros de estouro nem sempre so detectados, cabendo ao programador tomar cuidado ao dimensionar as variveis do programa para que eles no ocorram. Exemplo:
unsigned char x; x = 255; x = x + 1; /* x deveria assumir 256, no entanto estoura a faixa retorna para o menor valor que 0 */
1.7.2 Operadores relacionais Menor que Maior que Menor ou igual Maior ou igual Igualdade Desigualdade
Observaes: 1) Todas as operaes relacionais tem como resultado um inteiro representando um valor lgico (1 = true e 0 = false). 2) No confundir o operador de atribuio (= ) com o operador de igualdade ( = = ).
Os operadores lgicos podem receber qualquer valor de operando, porm os valores diferentes de zero so sempre interpretados como true (verdadeiro) e os iguais a zero so interpretados como false (falso). O resultado de uma operao lgica sempre um valor lgico. Tabela da verdade p 0 0 1 1 Q 0 1 0 1 p && q 0 0 0 1 p || q 0 1 1 1 !p 1 1 0 0
Exemplos:
a a a a += -= *= /= b; b; b; b; /* /* /* /* a a a a = = = = a a a a + * / b; b; b; b; */ */ */ */
Observaes: 1) Todos os operadores de atribuio atribuem o resultado de uma expresso a uma varivel Se o tipo do lado esquerdo no for o mesmo do lado direito, o tipo do lado direito ser convertido para o tipo do lado esquerdo. Isto pode causar a perda de preciso em alguns tipos de dados e deve ser levado a srio pelo programador.
Significado incrementa a varivel antes de usar o seu valor incrementa a varivel depois de usar o seu valor decrementa a varivel antes de usar o seu valor decrementa a varivel depois de usar o seu valor
a, b, c; 6; ++a; /* a recebe 7 e depois b tambm recebe 7*/ a++; /* c recebe 7 e depois a recebe 8 */
1.7.6 Operadores em nvel de bit Deslocamento esquerda (shift left) Deslocamento direita (shift right) e (and) ou (or) ou exclusivo (xor) no (not) << >> & | ^ ~
Para uma discusso mais aprofundada sobre o uso de bits e nmeros binrios, consultar o texto sobre Bases Numricas
/* fornece o tamanho do tipo int (2 bytes) */ /* fornece o tamanho da varivel y (4 bytes) */ /* fornece o tamanho da varivel c (1 byte) */
1.8 Expresses Operadores, constantes, variveis e funes constituem expresses. As principais regras algbricas so consideradas nas expresses. Alguns aspectos das expresses so especficos da linguagem C e so explicados a seguir.
/* res recebe 1, j que op1 e op2 so ambos nmeros do tipo int e o resultado da sua diviso tambm int */ res = (float)op1 / op2; /* res recebe 1.5, j que o type cast forou o operando op1 a ser um float nesta operao. O resultado da diviso, por consequncia, tambm float */
2. Estrutura de um programa em C
Uma particularidade interessante no programa C seu aspecto modular e funcional, em que o prprio programa principal uma funo. Esta forma de apresentao da linguagem facilita o desenvolvimento de programas, pois permite o emprego de formas estruturadas e modulares encontradas em outras linguagens. A estrutura de um programa em C possui os seguintes elementos, sendo que aqueles delimitados por colchetes so opcionais: [ [ [ [ [ main ( ) { /* definies de variveis */ /* corpo da funo principal, com declaraes de suas variveis, seus comandos e funes */ } Definies de pr-processamento so comandos interpretados pelo compilador, em tempo de compilao, que dizem respeito a operaes realizadas pelo compilador para gerao de cdigo. Geralmente iniciam com uma cerquilha (#) e no so comandos da linguagem C, por isso no sero tratados aqui com maiores detalhes. definies de pr-processamento definies de tipo declaraes de variveis globais prottipos de funes funes ] ] ] ] ]
Ex:
#include <stdio.h> /* comando de pr-processador, utilizado para indicar ao compilador que ele deve colar as definies do arquivo stdio.h neste arquivo antes de compil-lo */
Definies de tipos so definies de estruturas ou tipos de dados especiais, introduzidos pelo usurio para facilitar a manipulao de dados pelo programa. Tambm no sero tratados aqui em maiores detalhes. Declaraes de variveis globais so feitas quando necessrio utilizar variveis globais no programa. O conceito de varivel global e as vantagens e desvantagens do seu uso dizem respeito modularizao de um programa em C (consultar o material sobre modularizao e funes). Prottipos de funes e funes tambm dizem respeito a questes de modularizao. main() a funo principal de um programa em C, contendo o cdigo que ser inicialmente executado quando o programa em si for executado. Todo programa em C deve conter a funo main(), do contrrio ser gerado um erro durante o processo de gerao do programa (mais especificamente, na etapa de ligao).
caracteres simples (tipo char) inteiro (tipo int ) notao cientfica ponto flutuante (tipo float) %e ou %f (mais curto) octal string inteiro sem sinal hexadecimal tipo double inteiro no sinalizado (tipo unsigned int) tipo long int
2)
char carac = A; float num = 3.16; printf(A letra eh %c e o numero eh %f, carac, num); /* exibe A letra eh A e o numero eh 3.16. Neste caso, o especificador %c (primeiro da string) substitudo pelo valor da varivel carac e o especificador %f substitudo pelo valor da varivel num. Note-se que os tipos dos especificadores e das variveis so compatveis */
3.2 Funo scanf() (biblioteca stdio.h) A funo scanf utilizada para receber dados de uma entrada de dados padro. Consideraremos, para fins de simplificao, que essa entrada padro sempre o teclado. O prottipo de scanf o seguinte: scanf (string de formato, &var1, &var2, , &varN); onde a string de formato contm os especificadores de formato na sequncia e relativos a cada um dos dados que se pretende receber. Para uma lista dos especificadores de formato mais utilizados, ver seo 3.1. var1 a varN identificam as variveis nas quais sero armazenados os valores recebidos por scanf, na mesma ordem determinada pelos especificadores de formato. O nmero N deve ser igual ao nmero de especificadores de formato fornecidos.
IMPORTANTE: o operador de endereo (&) DEVE obrigatoriamente ser utilizado diante dos identificadores das variveis, do contrrio ocorre um erro. Para maiores detalhes, consultar a teoria sobre ponteiros. Exemplos: 1)
int t; printf(Digite um inteiro: ); scanf(%d, &t); /* aguarda a digitao de um nmero do tipo int. O nmero digitado armazenado na varivel t quando o usurio digita ENTER */
2)
char carac1; int i; printf(Digite um caracter e um int, separados por vrgula: ); scanf(%c, %d, &carac1, &i); /* neste caso, os especificadores de formato %c e %d esto separados por vrgula, o que significa que o usurio deve digitar os valores tambm separados por vrgula e na ordem correta */
3.3 Funo getch() (biblioteca conio.h) A funo getch utilizada, basicamente, para esperar o pressionamento de uma tecla pelo usurio. A tecla pressionada pode ser capturada atravs do valor de retorno da funo (para maiores detalhes sobre valor de retorno, consultar a teoria sobre funes). Pelo fato de interromper a execuo at o pressionamento de uma tecla, a funo getch pode ser utilizada no final de um programa de console para permitir que o usurio visualize o resultado do programa antes que a sua janela se feche. Exemplo:
printf(Estou mostrando uma frase\n); printf(Digite qualquer tecla para sair do programa); getch(); /* aguarda aqui at uma tecla ser pressionada */ /* fim do programa */
Observao: a funo getche funciona de forma semelhante, porm exibe na tela o caracter digitado (o nome significa get char with echo).
4. Estruturas de controle
Comando simples Uma linha de comando em C sempre termina com um ponto e vrgula (;) Exemplos:
x = 443.7; a = b + c; printf(Exemplo);
4.2 Bloco de comandos Utiliza-se chaves ( { } ) para delimitar blocos de comando em um programa em C. Estes so mais utilizados no agrupamento de instrues para execuo pelas clusulas das estruturas condicionais e de repetio. 4.3 Estruturas condicionais
Exemplos: 1)
int num; printf(Digite um numero: ); scanf(%d, &num); if (num < 0) /*testa se num menor que zero */ { /* bloco de comandos executado se a condio verdadeira. Neste caso, como printf um nico comando as chaves poderiam ser omitidas */ } else { printf(\nO nmero menor que zero);
/* bloco de comandos executado se a condio falsa. Neste caso, como printf um nico comando as chaves poderiam ser omitidas */ } printf(\nO nmero maior que zero);
2)
if ((a == 2) && (b == 5)) /* condio com operao lgica */ printf(\nCondio satisfeita); /* bloco de comandos */ getch(); /* esta instruo no faz parte da estrutura condicional, logo sempre executada */
3)
if (m == 3) { if ((a >=1) && (a <= 31)) /* este if faz parte do bloco de comandos do if anterior */ { printf(Data OK); } else /* este else do if mais proximo (que faz parte do bloco de comandos) */ { printf(Data invlida); } }
printf(Tera); break; case 4: printf(Quarta); break; case 5: printf(Quinta); break; case 6: printf(Sexta); break; case 7: printf(Sbado); break; default: printf(Este dia no existe); /* s entra aqui se o usurio no digitar um dia entre 1 e 7 */ break;
Estamos considerando programas executados linearmente, ou seja, sem a ocorrncia de eventos assncronos (p. ex., interrupes).
Exemplo:
int x = 0; /* imprime os valores de x de 0 at 9 o valor 10 no impresso porque, ao testar a condio para x igual a 10, o valor lgico falso e a execuo do while interrompida */ while (x < 10) { printf(\nx = %d, x); x++; /* faz a condio tornar-se falsa em algum momento */ }
2)
/* neste caso a sequncia de comandos nula, e o lao utilizado somente para gastar tempo contando de 0 a 999 */ for (x = 0; x< 1000; x++);
3)
/* no h incremento, e o lao executado at que o valor digitado pelo usurio seja 10 */ for (x = 0; x != 10;) scanf(%d, &x);
4)
/* duas variveis so inicializadas, testadas e incrementadas */ for (x = 0, y = 0; x + y < 100; x++, y++) printf(%d, x + y);
int num, x; for (x = 0; x<10; x++) { printf(Tente acertar o nmero (entre 0 e 32767).); printf(Vc tem %d tentativas., 10 x); scanf(%d, &num); if (num == sorteio) /* se acertou o nmero */ { break; /* interrompe o lao (no so necessrias mais tentativas) */ } } /* se x igual a 10, o usurio esgotou suas tentativas sem obter sucesso */
} else { } } printf(Lamentvel!);
5. Modularizao em C
Funes Em C no existe uma distino entre funes e subrotinas. Ou seja, todas as subrotinas, do ponto de vista de algoritmos, podem ser tratadas como funes que no retornam nenhum valor. Formato de declarao de funes :
Tipo de retorno identificador_da_funo param2,..., tipoN paramN) { /* corpo da funo */ return valor de retorno; } /* fim da funo */ (tipo1 param1, tipo2
Tipo de retorno especifica o tipo do valor que ser retornado para quem chamou a funo. Quando o tipo de retorno for void isto significa que se trata de uma funo que se comporta como uma subrotina; ou seja, a funo no necessita retornar nenhum valor, apenas ser chamada.
O comando return utilizado para realizar o retorno da funo; este pode ser utilizado em qualquer ponto da funo que se deseje finalizar a sua execuo e retornar o valor (se a funo retornar algum valor) para quem a chamou. Valor de retorno o valor a ser efetivamente retornado e pode ser tanto uma varivel como uma constante; nos casos em que a funo no retorna nenhum valor o comando return deve ser utilizado sozinho ou pode-se simplesmente omit-lo, o que far com que a funo retorne automaticamente ao seu final. Exemplos de uso de return:
return 0; /* retorna o valor constante 0 */ return var; /* retorna o valor da varivel var */ return; /* no retorna valor. usado para funes com retorno do tipo void */
Os parmetros param1 a paramN identificam os parmetros que se deseja passar para a funo. Cada um destes parmetros passa a ser uma varivel local da funo de tipo tipo1 a tipoN e inicializado com o valor que foi passado para si no momento da chamada da funo. Funes que no recebem nenhum valor como parmetro devem ser declaradas com a palavra void entre os parnteses. Exemplos de declaraes de parmetros no cabealho das funes:
/* dois parmetros, um int e um char. O ... se refere a um tipo de retorno qualquer */ ... Func1(int var, char var2) { } ... Func2 (void) /* no recebe nenhum parmetro */ { }
void main (void) /* programa principal */ { char c1; float f; int resultado; int inteiro; /*esta varivel inteiro existe no escopo da funo main, logo no tem nada a ver com a varivel inteiro que criada na funo func1 no momento da passagem dos parmetros */ /* l um nmero inteiro, um caracter e um float */ scanf(%d, %c, %f, &inteiro, &c1, &f); /* chama a funo func1 com os parmetros na ordem correta */ resultado = func1(c1, inteiro, f); printf(%d, resultado); /* imprime resultado da funo */ }
Observaes: main () tambm uma funo, porm especial j que ela representa o ponto de partida para qualquer programa em C; O resultado da funo func1, no exemplo acima, no precisa necessariamente ser atribudo a uma varivel (no caso, resultado); se isto no acontecer o valor de retorno da funo simplesmente ser perdido. Porm, como a funo foi feita para retornar um valor inteiro isto deve ser evitado, porque constitui-se em uma m estruturao e uso da funo; Todas as variveis declaradas dentro do corpo de uma funo so locais a ela, ou seja, s existem enquanto a funo est sendo executada.
Todas as funes devem ser conhecidas no local onde forem utilizadas, ou seja, a sua declarao deve vir antes do uso. Caso no se deseje implementar a funo antes do local onde ela vai ser utilizada pode-se escrever um prottipo da seguinte forma:
Tipo de retorno identificador_da_funo param2,..., tipoN paramN); (tipo1 param1, tipo2
O prottipo deve ser colocado antes da chamada da funo, sinalizando ento ao compilador que aquela funo existe e vai ser implementada adiante. No nosso exemplo, se quisssemos escrever a funo func1 depois da funo main deveramos incluir um prottipo de func1 antes dela. CUIDADO!! O prottipo no exatamente igual ao cabealho da funo, ele possui um pontoe-vrgula a mais no final! Variveis globais Em C considera-se como varivel global todas aquelas variveis declaradas fora do escopo de qualquer funo (inclusive da funo main). Qualquer varivel s conhecida aps a sua declarao, logo costuma-se declarar todas as variveis globais no incio do programa, antes da implementao das funes que a utilizam.
Passagem de parmetros por valor Na passagem por valor, uma cpia do valor do argumento armazenado no parmetro da funo chamada. Qualquer alterao deste parmetro no se reflete no valor original do argumento. Uma alternativa para a passagem de parmetro de valor, que a passagem de parmetros por referncia utilizando ponteiros, permitiria que a funo alterasse o valor do parmetro de forma que esta alterao se refletisse no valor original do argumento. Este tipo de passagem de parmetros ser melhor estudado no captulo sobre Ponteiros.
Funes com lista varivel de parmetros Em C possvel declarar funes cuja quantidade de parmetros no definida. Cabe ento funo, por meio do uso de funes especficas de biblioteca de C, obter cada um dos parmetros recebidos e convert-lo para o tipo desejado. A biblioteca cstdarg prov alguns tipos de dados e funes utilizadas para a obteno dos parmetros de uma lista: va_list tipo de lista de parmetros variveis, utilizado para declarar uma estrutura (ver o captulo sobre Estruturas de dados) que contm os parmetros variveis recebidos. void va_start(va_list lista, ultimo) macro utilizada para inicializar a lista de parmetros do tipo va_list. Ultimo o identificador do ltimo parmetro direita que no pertence lista varivel de parmetros. tipo va_arg(va_list lista, tipo) permite, a partir da lista do tipo va_list, obter o valor de tipo tipo do prximo argumento da lista. void va_end(va_list lista) finaliza a obteno dos parmetros da lista. Para declarar uma funo com lista varivel de parmetros:
Tipo de retorno identificador_da_funo (tipo1 param1, tipo2 param2, ...);
Onde a elipse (. . .) denota o incio da lista varivel de parmetros. Um exemplo: funo que recebe n valores e retorna a sua mdia:
/* n a quantidade de valores, que vm em seguida na lista de parmetros */ float media (int n, ...) { float soma = 0; int i; va_list valores; /* lista de parmetros */ va_start(valores, n); /* n o ltimo parmetro fixo antes da lista de parmetros variveis */ for (i = 0; i < n; i++) { /* aqui o valor do prximo parmetro, de tipo float adicionado a soma*/ soma += va_arg(valores, float); } va_end(valores); /* finaliza a obteno dos parmetros */ return soma/n; }
6. Vetores e matrizes
Definio de vetor Vetor em C uma varivel composta por um conjunto de dados com um mesmo nome (identificador) e individualizadas por um ndice. Declarao de vetor em C O vetor declarado da seguinte maneira:
tipo nome [tamanho];
Onde tipo o tipo de cada um dos elementos do vetor e tamanho o nmero de elementos do vetor. Para acessar um elemento do vetor a sintaxe :
nome [ndice];
IMPORTANTE! O ndice do primeiro elemento de um vetor SEMPRE ZERO! Assim, ndice pode variar entre 0 e o valor de tamanho 1. Por exemplo, para a declarao de um vetor chamado teste cujo tipo dos dados char e que tenha 4 posies declara-se:
char teste [4];
O ndice do ltimo elemento indexvel do vetor 3, pois em C a primeira posio utilizada a posio 0. Neste caso as posies disponveis no vetor so as seguintes: teste[0] teste[1] teste[2] teste[3] Passagem de vetor como parmetro para funo Existem trs maneiras possveis:
tipo_retorno nome (tipo v[tam], ...); tipo_retorno nome (tipo v[], ...); tipo_retorno nome (tipo * v, ...);
Em todos os casos a funo recebe uma referncia (endereo). Note que na ltima maneira utilizado um ponteiro, que ser explicado mais adiante.
Por ser passada uma referncia, as alteraes feitas nos elementos do vetor dentro da funo sero refletidos nos valores originais do vetor (j que se utilizar sua posio real na memria). Por exemplo:
void troca (int v[]) { int aux; v[0] = v[1]; v[1] = aux; } void main(void) { int nums[2]; nums[0] = 3; nums[1] = 5; troca (nums); /* O argumento o nome do vetor */ /* imprime 5, 3, j que os valores do vetor trocados dentro da funo troca */ printf(%d, %d, nums[0], nums[1]); }
nums
foram
Onde dim1 e dim2 so as duas dimenses da matriz (no caso de uma matriz bi-dimensional). Para se acessar um elemento da matriz a sintaxe :
nome[ind1][ind2];
Onde ind1 e ind2 seguem as mesmas regras dos ndices de vetores unidimensionais (ou seja, podem assumir valores entre 0 e a dimenso 1), sendo ind1 o ndice da linha e ind2 o ndice da coluna. As representao grfica de uma matriz M 3x2 se d da seguinte maneira: M[0][0] M[1][0] M[2][0] M[0][1] M[1][1] M[2][1]
Na memria ela pode ser vista da seguinte forma (obs: os valores da esquerda representam endereos arbitrrios de memria, considerando uma matriz de elementos char de um byte):
No primeiro caso, dim2 deve ser fornecido para que o compilador possa calcular o deslocamento em bytes em relao ao endereo do primeiro elemento para uma determinada posio. No segundo caso, m s pode ser utilizado atravs da aritmtica de ponteiros (explicada adiante). Exemplo:
void inverte_linha(int m[][2]) { int aux1, aux2; aux1 = m[0][0]; aux2 = m[0][1]; m[0][0] = m[1][0]; m[0][1] = m[1][1]; m[1][0] = aux1; m[1][1] = aux2; } void main(void) { int m[2][2]; . . . inverte_linha(m); . . . }
6.6 Inicializao de vetores e matrizes Para vetores: valores entre chaves, separados por vrgulas. Por exemplo:
int primos [7] = {2, 3, 5, 7, 11, 13, 17};
Caso o nmero de valores de inicializao seja menor que o tamanho do vetor, as posies restantes sero preenchidas com zeros. Por exemplo:
int teste[5] = {1, 2, 3}; /* teste[3] e teste[4] recebem 0 */
Para matrizes cada linha preenchida entre chaves, com valores separados por vrgulas. Todas as linhas ficam entre chaves. Ex:
int m[5][3] = {{1, 2, 3,}, {3, 2, 1}, {3, 3, 2}, {1, 2, 1} {3, 2, 0}};
Caso algum elemento no seja explicitado, ele ser preenchido com zero.
Ex:
int m2[3][4] = {{3, 2, 5}, {4, 6}, {1, 2, 3, 4}};
3 2 5 0 4 6 0 0 1 2 3 4
7 Ponteiros
Ponteiro em C uma varivel que, ao invs de armazenar um dado de um determinado tipo, armazena o endereo de um dado de um determinado tipo: Ponteiros so usados freqentemente para: Acesso a E/S mapeada em memria Uso de alocao dinmica de memria. Alternativa para passagem de parmetros por referncia (em C++) 7.1 Declarao de ponteiros em C Os ponteiros so declarados da seguinte maneira:
tipo *nome;
Onde nome o identificador do ponteiro e tipo o tipo de dado para o qual ele pode apontar. Ex:
int *d; short int *ptr; float *ptr2;
7.2 Operadores de ponteiro Operador &: Operador de referenciao. Retorna o endereo de uma varivel. Pode ser utilizado para inicializar um ponteiro. Operador *: Operador de derreferenciao. Retorna o contedo do endereo apontado por um ponteiro. Ex:
int int x = ptr . . . a = x,a; *ptr; 30; = &x;
/*
*/
*ptr;
Um modo didtico para o entendimento de ponteiros ler o significado de * e & como contedo do endereo apontado por e endereo de, respectivamente. Por exemplo no seguinte cdigo:
int *ptr; int x; x = 10; *ptr = 3; /* O CONTEDO DO ENDEREO APONTADO POR ptr recebe 3 */ ptr = &x; /* ptr recebe o ENDEREO DE x */
7.3 Problemas no uso de ponteiros - Ponteiros sempre devem apontar para endereos correspondentes a variveis que tenham sido declaradas ou a regies de memria nas quais no existam dados ou cdigo de outros programas. Por exemplo, o seguinte cdigo armazena o contedo da varivel x em um endereo qualquer, que pode ser um endereo invlido.
int *ptr; int x = 3; *ptr = x; /* ERRO! Para onde o ptr aponta???
*/
- Ponteiros devem apontar para dados do mesmo tipo de sua declarao, do contrrio podem ocorrer interpretaes erradas na operao de derrenferenciao. Por exemplo, o seguinte cdigo no armazena o valor 56 na varivel f, j que o ponteiro para float tentar ler o tamanho de um dado float a partir do endereo de memria da varivel x e no o tamanho de um int, que o tipo declarado da varivel x.
int x = 56; float *ptr; float f; ptr = &x; /* Ponteiro para float aponta para int */ . . . f = *ptr; /* ERRO! Valor de F no 56 */
7.4 Aritmtica de ponteiros Valores numricos inteiros podem ser adicionados ou subtrados de um ponteiro. O resultado um endereo que segue as regras da aritmtica de ponteiro, ou seja: Para um ponteiro declarado da seguinte maneira:
tipo* ptr;
a operao ptr + N, onde N um nmero inteiro, resulta um endereo que igual a end1 mais N vezes o tamanho do tipo de dado apontado (ou seja, o tamanho em bytes de tipo).
Outro exemplo:
float ptr = . . . *(ptr = 112 *ptr; (float*)100; /* ponteiro forado para o end. 100 */
7.5 Relao ponteiro-vetor Quando um vetor declarado, o identificador deste vetor marca o endereo de incio da rea de memria alocada por ele. Assim, o nome do vetor pode ser usado como referncia de endereo com os mesmos operadores utilizandos para ponteiros. Portanto:
int vetor[10], b; . . . b = vetor[3]; /* vetor alocado no end. 100 (p. ex.) */
*/
Equivale a:
int vetor[10], b; /* vetor alocado no end. 100 (p. ex.) */
/* Na memria isso ser guardado na posio 106 -> 100 + 3 x Tamanho do tipo de dado apontado (int = 2 bytes) */ b = *(vetor + 3);
7.6 Uso de ponteiro para passagem de parmetros Em muitos casos interessante que uma funo fornea mais do que um valor de sada como seu resultado. Porm a sintaxe de linguagem C permite somente um valor de retorno direto (atravs do comando return). O uso de ponteiros cria uma alternativa para que uma funo fornea mais do que um valor de sada, baseado no fato de que o conceito de endereo em um programa independente de escopo. Ou seja, se uma funo chamadora fornecer para a funo chamada os endereos de suas variveis, a funo chamada poder receb-los em ponteiros e preencher valores nestes endereos, que por sua vez estaro disponveis para acesso direto pela funo chamadora.
Exemplo:
/* funo recebe dois endereos de int como parmetros */ void troca (int *a, int *b) { int aux; aux = *a; /* contedo do endereo recebido como parmetro */ *a = *b *b = aux; } void main(void) { int n1 = 8, n2 = 5; /* endereos de n1 e n2 so passados para a funo troca() */ troca (&n1, &n2); printf(%d, %d, n1, n2); }
8 Strings
8.1 Definio de string Strings so seqncias de caracteres diversos. So conhecidos por literais na teoria de algoritmos estruturados, sendo representados entre aspas. Alguns exemplos de strings: Fulano da Silva, ? Interrogao? , 1,234, 0. Em C, strings so representadas atravs de vetores de caracteres, terminados com o caractere de fim de string cujo valor na tabela ASCII zero (0 ou \0). 8.2 Declarao de string Um vetor em C que pretenda armazenar uma string n caracteres deve ser alocado com n+1 posies do tipo char para conter o terminador de string. A inicializao de uma string pode ser efetuada com o uso de uma sequncia de caracteres entre aspas. Exemplos de declaraes de string:
char frase[] = Primeira string; /*Inicializao sem a dimenso */ char frase[16] = Primeira string; char frase[6] = {T, e, s, t, e, 0); /* inicializado como um vetor de caracteres comum, forando o caracter terminador */
P r i m e i r a
f r a s e 0
8.3 Operaes sobre string String no um tipo primitivo da linguagem C, por isso as seguintes operaes NO so vlidas:
char str1[10]; char str2[] = Palavra 2; str1 = str2 /* ERRO! No copia str2 em str1 */ if (str1 == str2) /* ERRO! No compara str1 com str2 */ { . . . }
Para operar sobre strings so utilizadas funes da biblioteca string.h. Esta biblioteca possui algumas dezenas de funes com diversas variaes e por questes de simplificao apenas algumas das principais sero explicadas neste material. Para maiores detalhes sobre as demais funes, consultar documentao sobre a biblioteca (geralmente disponvel nos arquivos de ajuda dos ambientes de desenvolvimento). 8.3.1 strlen Prottipo:
int strlen (char *string)
Descrio: Retorna o nmero de caracteres de uma string (exceto o caractere de fim de string). Exemplo:
char nome[] = Fulano; printf (O nome possui %d letras, strlen (nome));
Descrio: Compara os contedos de string1 e string2 caracter a caracter e retorna 0 se string1 = string2 <0 se string1 < string2 >0 se string1 > string2
Exemplo:
char nome1[] = Fulano char nome2[] = Beltrano; if (strcmp (nome1, nome2) == 0) { printf (Nomes so iguais); } else { printf (Nomes so diferentes); }
Descrio: Recebe uma string via teclado e armazena em string1. Os caracteres so armazenados at que o enter seja pressionado. Exemplo:
char nome[10]; gets (nome);
Observaes:
a funo gets() permite que o usurio fornea mais caracteres do que os que podem ser armazenados no vetor, o que pode causar um erro. Para evitar este problema, pode-se utilizar a funo fgets:
char nome[10]; fgets(nome, 10, stdin); /* stdin um arquivo aberto por padro, relacionado aos dados digitados via teclado */
No exemplo mostrado, fgets receberia 9 caracteres (ou at que o usurio teclasse enter) e armazenaria os dados digitados na string nome, adicionando o caracter terminador de string. importante observar que, caso o usurio digitasse enter antes de 9 caracteres, o caracter de nova linha (\n) tambm seria armazenado no vetor. gets() termina quando o usurio digita um espao, impedindo a digitao de frases com mais de uma palavra. Para contornar este problema pode-se utilizar opes de recebimento de dados do scanf:
scanf (%s, str); /* Recebe uma string at que o primeiro espao seja inserido */ scanf (%[\n]s, str) /* Recebe uma string at que seja enviado o caractere ASCII \n, que corresponde a enter */
8.4 Entrada controlada de dados possvel fazer uma entrada de dados controlada (ou seja, os caracteres so checados assim que so recebidos) recebendo os mesmos um a um. No exemplo a seguir implementaremos uma entrada de senha que mostra os caracteres * na tela ao invs das letras correspondentes utilizando a funo getch (que no ecoa o caracter digitado para o monitor). Note que s sero aceitos letras e no nmeros e smbolos.
int i = 0; char str[9]; printf (Digite uma senha de oito letras); while (i < 8) { str[i] = getch(); if (((str[i] >= a) && (str[i] <= z)) || ((str[i] >= A) && (str[i] <= Z))) { printf (*); i++; } }
Exemplo:
int *v; int n; printf (Quantos elementos no vetor?); scanf (%d, &n); v = (int*) malloc(n * sizeof(int)); /* Alocar n vezes o tamanho de um int */ if (v == 0) { printf (Erro); } else { /* aqui poderia vir o cdigo para manipulao do vetor . . . */ free (v); }
A funo free() chamada ao final da utilizao do espao de memria dinamicamente alocado para liberar este espao, permitindo que seja utilizado por outras operaes de alocao dinmica. O prottipo de free o seguinte:
void free(void* ptr)