Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
! Definição
ALOCAÇÃO DINÂMICA é o processo através do qual um programa pode criar novas variáveis (áreas de memória) em tempo de execução.
Variáveis alocadas dinâmicamente são criadas em uma área de memória livre chamada de HEAP e são acessadas através de PONTEIROS.
[img[img/cap1.fig1_2.png]]
! Funções de Alocação Dinâmica em C
!! Padrão ANSI
* {{{#include <stdlib.h>}}}
** {{{void * calloc(size_t num, size_t size);}}}
*** Aloca uma quantidade de memória igual a {{{num}}}*{{{size}}}. Isto é, aloca memória suficiente para um ARRANJO de {{{num}}} VARIÁVEIS de tamanho {{{size}}}.
*** Devolve o endereço para o primeiro byte da região alocada. Se não houver memória suficiente para satisfazer a solicitação, é devolvido {{{NULL}}} (endereço nulo).
** {{{void * malloc(size_t size);}}}
*** Aloca uma quantidade de memória igual a {{{size}}}. Isto é, aloca memória suficiente para uma VARIÁVEL de tamanho {{{size}}}.
*** Devolve o endereço para o primeiro byte da região alocada. Se não houver memória suficiente para satisfazer a solicitação, é devolvido {{{NULL}}} (endereço nulo).
** {{{void * realloc(void * ptr, size_t size);}}}
*** Modifica o tamanho da memória previamente alocada apontada por {{{ptr}}} para um novo tamanho especificado por {{{size}}}. O valor {{{size}}} pode ser maior ou menor que o original.
*** Retorna o endereço para o primeiro byte da região de memória redimensionada. Se não houver memória suficiente no HEAP para satisfazer a solicitação, é devolvido NULL (endereço nulo) e o endereço originalmente em {{{ptr}}} é deixado inalterado.
** {{{void free(void * ptr);}}}
*** Devolve ao HEAP a memória apontada por {{{ptr}}}, tornando a memória disponível para alocação futura.
*** Deve ser chamada somente com um PONTEIRO {{{ptr}}} cujo endereço de memória foi previamente alocado por meio de uma das funções do sistema de alocação dinâmica ({{{calloc(), malloc(), realloc()}}}).
!! Outras
* {{{#include <string.h>}}}
** {{{char * strdup(const char * pstr);}}}
*** Duplica a STRING apontada por {{{pstr}}}. Ou seja, aloca no HEAP {{{strlen(pstr)+1}}} bytes e copia a STRING começando em {{{pstr}}} para o endereço alocado.
*** Retorna o endereço alocado contendo uma cópia da STRING apontada por {{{pstr}}} ou {{{NULL}}} caso não haja memória suficiente no HEAP.
Ex.: O trecho de código abaixo:
{{{
char str[] = "Teste";
char * pstr = strdup(str);
}}}
É equivalente a:
{{{
char str[] = "Teste";
char * pstr = calloc(strlen(str) + 1, sizeof char);
strcpy(pstr,str);
}}}
! Atividade 1
Utilizando as funções de alocação dinâmica em C, iremos agora implementar uma segunda versão do programa //lista de strings// estudado na aula [[Ponteiros]].
!! list.h
{{{
/* list.h, Rev. 1.2
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements a list of strings.
**/
#ifndef LIST_H
#define LIST_H
unsigned short list_size(void);
void list_add(const char * str, unsigned short pos);
char * list_rem(unsigned short pos);
void list_set(const char * str, unsigned short pos);
char * list_get(unsigned short pos);
void list_print(void);
#endif
}}}
!! list.c
{{{
/* list.c, Rev. 1.3
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements a list of strings.
**/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "list.h"
#include "xcpt.h"
/** private data */
static char ** list;
static unsigned short size = 0;
static char xcpt_cmsg[XCPT_CMSG_MAX_SIZE+1];
/** public functions */
unsigned short list_size(void) {
return size;
}
/*
Add a new element str in the list at a given position pos.
From pos to the end of the list, all existing elements are
shifted right.
Throws:
INDEX_OUT_OF_BOUNDS_XCPT when pos is invalid ( > size +1 )
NULL_POINTER_XCPT when there is no memory available
to add a new element to the list.
**/
void list_add(const char * str, unsigned short pos) {
char * line = strdup(str);
sprintf(xcpt_cmsg,"%s, %d: list_ins (\"%s\",%d);",__FILE__,__LINE__,str,pos);
if ( line == NULL ) {
THROW(NULL_POINTER_XCPT,xcpt_cmsg);
return ;
}
if ( pos > size + 1 ) {
THROW(INDEX_OUT_OF_BOUNDS_XCPT,xcpt_cmsg);
return ;
}
if ( size % 10 == 0 ) {
char ** aux = (char **) realloc(list,(size + 10)*(sizeof (char**)));
if ( aux == NULL ) {
THROW(NULL_POINTER_XCPT,xcpt_cmsg);
return ;
}
list = aux;
}
if ( pos == 0 ) {
list[size] = line;
} else {
int i;
for ( i = size ; i >= pos; i-- )
list[i] = list[i-1];
list[i] = line;
}
size++;
}
char * list_rem(unsigned short pos) {
THROW(FUNCTION_NOT_IMPLEMENTED_XCPT,"list_rem();");
}
void list_set(const char * str, unsigned short pos) {
THROW(FUNCTION_NOT_IMPLEMENTED_XCPT,"list_set();");
}
char * list_get(unsigned short pos) {
THROW(FUNCTION_NOT_IMPLEMENTED_XCPT,"list_get();");
}
void list_print(void) {
int i;
for ( i=0; i < size; i++ )
printf("%2d: %s\n",i+1,list[i]);
}
}}}
! Exercícios
# Conclua a Atividade 1 implementando as funções:
** {{{char * list_rem(unsigned short pos);}}}
** {{{void list_set(const char * str, unsigned short pos);}}}
** {{{char * list_get(unsigned short pos);}}}
# Teste a nova implementação de {{{list.h}}} e {{{list.c}}} com o mesmo arquivo {{{main.c}}} apresentado na aula [[Ponteiros]].
This tiddler shows some more complex effects that can be obtained with cunning use of CSS. Not all of these will work properly on all browsers because of differences in CSS implementation, but they should fail gracefully.
You can have special formatting for a specific, named tiddler like this:
{{{
#tiddlerHelloThere .title {
background-color: #99aaee;
}
}}}
Or for the first displayed tiddler:
{{{
div.tiddler:first-child .title {
font-size: 28pt;
}
}}}
Or just for the first line of every tiddler:
{{{
.viewer:first-line {
background-color: #999999;
}
}}}
Or just for the first letter of every tiddler:
{{{
.viewer:first-letter {
float: left;
font-size: 28pt;
font-weight: bold;
}
}}}
Or just for tiddlers tagged with a particular tag (note that this won't work for tags that contain spaces):
{{{
div[tags~="welcome"].tiddler .viewer {
background-color: #ffccaa;
}
div[tags~="features"].tiddler .viewer {
background-color: #88aaff;
}
}}}
! Ementa
Conceitos Gerais. Tipos de linguagens. Linguagem de programação estruturada. Variáveis e tipos de dados. Estruturas de controle de fluxo de execução. Modularização. Tipos complexos de dados. Operações com arquivos. Aplicações.
! Objetivos
Apresentação de uma linguagem de programação que será usada no aprendizado de técnicas de programação e na modelagem de problemas.
! Programa
1 Introdução às linguagens de programação
2 Visão Geral de C
<<<
2.1 Padronizações
2.2 Características
2.3 Estrutura geral de um programa em linguagem C
<<<
3 Tipos de dados e tipos de variáveis
<<<
3.1 Variáveis inteiras, caracter, e ponto flutuante
3.2 Definição de variáveis globais, externas, locais e estáticas
<<<
4 Operadores e expressões
<<<
4.1 Operadores aritméticos, relacionais, lógicos, bit a bit
4.2 Operador de atribuição condicional e operador de moldagem
4.3 Expressões em C
<<<
5 Controle de fluxo de execução
<<<
5.1 Desvios incondicionais
5.2 Desvios condicionais
5.3 Comandos de malha
<<<
6 Funções
<<<
6.1 Tipos de funções
6.2 Passagem de parâmetros por valor e por endereço
6.3 Construção de funções e funções padronizadas
<<<
7 Vetores e ponteiros
<<<
7.1 Alocação estática e dinâmica
7.2 Definição e inicialização de vetores
7.3 Ponteiros em C
7.4 Aplicações de ponteiros
<<<
8 Estruturas, uniões e tipos definidos pelo usuário
<<<
8.1 Definição de estruturas
8.2 Vetor de estruturas
8.3 Passagem de estruturas como parâmetros
8.4 Definição de Uniões
8.5 Tipos definidos pelo usuário
<<<
9 Entrada e saída em arquivos
<<<
9.1 Conceitos de arquivos
9.2 Arquivos no MSDOS e UNIX
9.3 Arquivos textos e binários
9.4 Operações de leitura e escrita em arquivos
9.5 Funções da biblioteca C para manipulação de arquivos
<<<
10 Pre - Processador C
<<<
10.1 Diretivas de Compilação
<<<
! Procedimentos de Ensino/Aprendizagem
!! Recursos Didáticos
Uso de computadores, ambiente desenvolvimento em C, quadro-branco, marcador, notas de aulas.
!! Metodologia
** Aulas teórico - práticas em laboratório,
** desenvolvimento e discussão de programas,
** trabalhos de programação pelos alunos.
! Sistema de Avaliação
Três Avaliações (A1, A2 e A3), seguidas de uma Reposição (R) (para aqueles cuja média (A1+A2+A3)/3 < 7,0) e uma Final (F) (para aqueles cuja média corrigida pela Reposição seja >= 4,0 e < 7,0).
Seguindo as normas da UFMA, será APROVADO o aluno que:
* tiver média ao fim da última avaliação maior ou igual a SETE
** media = (A1+A2+A3)/3 >= 7,0
OU
* tiver média após a reposição maior ou igual a SETE
** mediaRep = (A1+A2+A3 - min{A1,A2,A3} + R)/3 >= 7,0
OU
* tiver média após a reposição MAIS nota da Final maior ou igual a 12
** mediaRep + Final >= 12,0
!! Avaliações
!!! A1 e A2
Feitas a partir de:
* PROVAS ESCRITAS INDIVIDUAL (P1 e P2)
* LISTAS de EXERCÍCIOS INDIVIDUAIS (L1 e L2)
Calculo:
* Avaliação A1 = ( 2*P1 + L1 ) / 3
* Avaliação A2 = ( 2*P2 + L2 ) / 3
!!! A3
Feita a partir de:
* PROVA ESCRITA INDIVIDUAL (P3)
* PROJETO de PROGRAMAÇÃO em GRUPO (T3)
Calculo:
* Avaliação A3 = (2*T3 + P3) / 3
!! Reposição
Consistirá em uma PROVA ESCRITA INDIVIDUAL. A nota da Reposição irá substituir a menor nota dentre A1, A2 e A3. O assunto da Reposição será o conteúdo correspondente ao conteúdo da menor nota sendo substituída.
!! Final
Consiste em uma PROVA ESCRITA INDIVIDUAL. O assunto da Final será todo o conteúdo ministrado durante o curso.
! [[Bibliografia]]
! Básica
* [CCT] Schildt, H. (1996) __C, completo e total: 3a Ed.__. São Paulo, Makron.
! Complementar
* [K&R] KERNIGHAN, B. e RITCHIE, D. (1990) __C, a linguagem de programação: padrão ANSI__. Rio de Janeiro: Campus.
* DEITEL, H. M. (1999) __Como programar em C__. Rio de Janeiro: LTC.
* Módulo Consultoria e Informática (1989) __Linguagem C: programação e aplicações__. Rio de Janeiro: LTC.
Em Inglês:
* Jones, Derek M. (2008) "[[The New C Standard: An Economic and Cultural Commentary|http://www.knosof.co.uk/cbook/cbook.html]]."
* Parlante, N. (2003) "[[Essential C | http://cslibrary.stanford.edu/101/]]." Stanford CS Education Library.
* Oualline, Steve (????) "[[C - Elements of Style|http://www.computer-books.us/c_3.php]]."
* Franek, Frantisek (2003) "[[Memory as a Programming Concept in C and C++ | http://www.amazon.com/gp/product/0521520436/ref=pd_luc_0000115932706580521520436 ]]." Cambridge University Press.
* van der Linden, Peter (1994) "[[Expert C Programming | http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298/ref=sr_1_44?ie=UTF8&s=books&qid=1205152819&sr=1-44]]." Prentice Hall PT.
! [[Links]]
PageTemplate
|>|>|SiteTitle - SiteSubtitle|
|MainMenu|DefaultTiddlers<<br>><<br>><<br>><<br>>ViewTemplate<<br>><<br>>EditTemplate|SideBarOptions|
|~|~|OptionsPanel|
|~|~|AdvancedOptions|
|~|~|<<tiddler Configuration.SideBarTabs>>|
''StyleSheet:'' StyleSheetColors - StyleSheetLayout - StyleSheetPrint
SiteUrl
! Objetivos
Nesta aula, iremos iniciar o estudo dos comandos e construção em C para o @@CONTROLE do FLUXO de EXECUÇÃO@@ de um programa. Especificamente, abordaremos os comandos para realização de @@DESVIOS CONDICIONAIS@@:
* {{{if ... else ...}}}
* {{{switch ... case ...}}}
também conhecidos como @@COMANDOS DE SELEÇÃO@@.
! Controle de Fluxo
Em C, bem como em toda linguagem moldada sob os princípios da @@PROGRAMAÇÃO ESTRUTURADA@@, o fluxo de execução de um programa é controlado de acordo com algumas idéas simples e fundamentais:
* SEQÜÊNCIA e BLOCOS de comandos
* DESVIOS
** CONDICIONAIS
** INCONDICIONAIS
* ITERAÇÕES (LAÇOS)
! Seqüência e Blocos de Comandos
Uma @@SEQÜÊNCIA de COMANDOS@@ é uma lista de COMANDOS delimitados por {{{ ; }}} .
Um @@BLOCO de COMANDOS@@ é qualquer SEQÜÊNCIA de COMANDOS delimitada por chaves {{{ {} }}}.
Em um @@BLOCO de COMANDOS@@, podem-se distinguir três tipos básicos de @@COMANDOS@@:
# DECLARAÇÃO de VARIÁVEIS LOCAIS
** sempre no início do BLOCO
** variáveis declaradas dentro de um BLOCO podem ter o mesmo nome de uma outra variável situada em um BLOCO mais externo; neste caso, a variável dentro do BLOCO mais interno se sobrepõe a variável do BLOCO mais externo.
# COMANDOS de EXPRESSÃO formados por uma expressão C válida
** ATRIBUIÇÕES
** CHAMADAS de FUNÇÃO
# COMANDOS de CONTROLE de FLUXO atuando sobre COMANDOS individuais ou então outros BLOCOS de COMANDOS.
** DESVIOS CONDICIONAIS
** DESVIOS INCONDICIONAIS
** ITERAÇÕES
Por exemplo:
{{{
int f() { /* início de BLOCO */
int a,b; /* DECLARAÇÕES LOCAIS */
a = 10; /* comando de EXPRESSÃO */
b = a % 3 ; /* comando de EXPRESSÃO */
if ( a > 2 ) /* comando de CONTROLE de FLUXO */
{ /* início de BLOCO */
int x,y; /* DECLARAÇÕES LOCAIS */
x = 2*a; /* comando de EXPRESSÃO */
for ( y =1; y < 10; y++ ) /* comando de CONTROLE de FLUXO */
x += y; /* comando de EXPRESSÃO */
...
} /* fim de BLOCO */
else
printf("a é menor que 2\n"); /* comando de EXPRESSÃO */
} /* fim de BLOCO */
}}}
! Desvios Condicionais ( Comandos de SELEÇÃO )
Em C, há dois comandos para DESVIOS CONDICIONAIS:
* {{{ if ... else }}}
* {{{ switch ... case ... break ... default }}}
!! O comando {{{ if ... else ... }}}
''Forma Geral''
{{{
if ( condição )
ação_se_não_zero
else
ação_se_zero
}}}
onde:
* tanto {{{ação_se_não_zero}}} quanto {{{ação_se_zero}}} podem ser:
** um único comando de EXPRESSÃO ou
** um outro comando de CONTROLE de FLUXO ou
** um BLOCO de COMANDOS
* a parte {{{else ação_se_zero}}} é opcional
* a {{{condição}}} deve ser uma EXPRESSÃO ESCALAR (ou seja, uma EXPRESSÃO que quando avaliada produza um inteiro, um caracter ou ponto flutuante.)
''Observação'':
* em {{{if ... else ... }}} aninhados cada {{{else}}} se refere ao {{{if}}} mais próximo dentro do mesmo bloco.
!! O comando {{{ switch ... case ... break ... default }}}
[img[img/cap3.switch.png]]
''Observações'':
* O comando {{{switch}}} só pode testar igualdade; já o comando {{{if}}} pode avaliar uma expressão lógica ou relacional;
* Duas constantes {{{case}}} no mesmo {{{switch}}} não podem ter valores idênticos;
* Constantes caracter são automaticamente convertidas para seus valores inteiros;
* Os comandos {{{break}}} dentro do {{{switch}}} são opcionais. Eles terminam a seqüência de comandos associados com cada constante. Se o comando {{{break}}} é omitido, a execução continua pelos próximos comandos {{{case}}} até que um {{{break}}}, ou o fim do {{{switch}}}, seja encontrado.
! Atividade 1
Escreva um programa calculadora que leia dois números {{{double}}} e em seguida realize uma dentre um conjunto de operações disponíveis. As operações disponíveis são:
* adição ({{{+}}})
* subtração ({{{-}}})
* multiplicação ({{{*}}})
* divisão ({{{/}}})
* divisão inteira ({{{div}}})
* resto divisão inteira ({{{mod}}})
* exponenciação inteira ({{{^}}})
{{{
...
}}}
! Leitura Recomendada
* CCT capítulo 3
* K&R capítulos 3
! Exercícios
# Complete as atividade 1 acima;
# Extenda a atividade 1 para lidar com as operações ''fat'' (fatorial), ''sen'' (seno), ''cos'' (coseno) e ''rq'' (raiz quadrada). Nestes casos, apenas um número deve ser lido.
! Laços
Em C, há três comandos de ITERAÇÃO ou LAÇOS:
* {{{ for }}}
* {{{ while }}}
* {{{ do ... while}}}
Estes permitem que um conjunto de instruções seja executado até que ocorra uma certa condição. Esta condição pode ser pré-definida (como no laço {{{for}}}) ou com o final em aberto (como nos laços {{{while}}} e {{{do ... while}}}).
! Laço {{{for}}}
''FORMA GERAL''
{{{
for( INICIALIZAÇÃO ; CONDIÇÃO ; INCREMENTO ) COMANDO;
}}}
* {{{INICIALIZAÇÃO}}} - geralmente um comando de atribuição para colocar um valor na variável de controle do laço;
* {{{CONDIÇÃO }}} - é uma expressão relacional que determina quando o laço acaba;
* {{{INCREMENTO}}} - define como a variável de controle do laço varia cada vez que o laço é repetido;
* {{{COMANDO}}} - um único comando ou um bloco de comandos executados enquato a {{{CONDIÇÃO}}} é verdadeira.
''VARIAÇÕES''
''1. Operador Vígula'' - uma das variações mais comuns é o uso do operador vírgula para permitir que duas ou mais variáveis controlem o laço:
{{{
for( x = 0 , y = 100 ; x < y ; x ++ , y -= x )
printf("x = %i, y = %i\n",x,y);
}}}
''2. Laço infinito'' - Nenhuma das três expressões que formam um laço {{{for}}} é obrigatória. Assim, você pode criar um laço infinito assim:
{{{
for ( ; ; )
printf(" Laço infinito \n");
}}}
''3. Laço sem corpo'' - Um comando pode ser vazio. Isso significa que o corpo do laço {{{for}}} (ou qualquer outro laço) também pode ser vazio.
{{{
int pausa ( unsigned long int p) {
for ( t = 0 ; t < p ; t++ )
;
}
}}}
! Laço {{{while}}}
''FORMA GERAL''
{{{
while( CONDIÇÃO )
COMANDO;
}}}
{{{COMANDO}}} é executado enquanto a {{{CONDIÇÃO}}} for verdadeira ( diferente de zero ); quando for falsa, o controle passa para a linha após {{{COMANDO}}}.
''VARIAÇÕES''
''1. Laço infinito'' :
{{{
while ( 1 )
printf(" Laço infinito \n");
}}}
''2. Laço sem corpo''.
{{{
int pausa ( unsigned long int p) {
while ( p-- )
;
}
}}}
! Laço {{{do ... while}}}
Ao contrário dos laços {{{for}}} e {{{while}}}, que testam a condição do laço no começo, o laço {{{do ... while}}} verifica a condição ao final do laço. Isso significa que um laço {{{do ... while}}} SEMPRE SERÁ EXECUTADO AO MENOS UMA VEZ.
''FORMA GERAL''
{{{
do {
COMANDO;
} while( CONDIÇÃO );
}}}
Embora as chaves não sejam necessárias quando apenas um comando está presente, elas são geralmente usadas para evitar confusão (para você, não para o compilador) com o {{{while}}}.
O laço {{{do ... while}}} repete até que a {{{CONDIÇÃO}}} se torne falsa.
''VARIAÇÕES''
''1. Laço infinito'' :
{{{
do{
printf(" Laço infinito \n");
} while ( 1 )
}}}
''2. Laço sem corpo''.
{{{
int pausa ( unsigned long int p) {
do {} while ( p-- );
}
}}}
! Desvios Incondicionais
* {{{return}}}
* {{{goto}}}
* {{{break}}}
* {{{continue}}}
!! O comando {{{return}}}
Este comando é usado para retornar de uma função. Ele é um comando de desvio porque faz com que a execução retorne (salte de volta) ao ponto em que a chamada à função foi feita.
Se {{{return}}} tem um valor associado a ele, esse valor é o valor de retorno da função. Se nenhum valor de retorno é especificado, assume-se que apenas lixo é retornado (alguns compiladores irão automaticamente retornar 0 se nenhum valor for especificado, mas não conte com isso).
FORMA GERAL
{{{
return EXPRESSÃO;
}}}
!! O comando {{{goto}}}
Na programação estruturada, não há nenhuma situação que necessite do {{{goto}}}. No entanto, o {{{goto}}} é uma conveniência que, se usada com prudência, pode ser uma vantagem em certas situações.
FORMA GERAL
{{{
goto RÓTULO;
...
RÓTULO:
}}}
O comando {{{goto}}} requer um RÓTULO - um identificador válido seguido por dois-pontos).
O RÓTULO tem de estar na mesma função do {{{goto}}} que o usa -- não é permitido desvios entre funções.
O RÓTULO pode vir antes, e não apenas depois, do comando {{{goto}}}.
''laço infinito''
{{{
LOOP:
printf("laço infinito\n");
goto LOOP;
}}}
!! O comando {{{break}}}
O comando {{{break}}} tem dois usos. Você pode usá-lo para terminar um {{{case}}} em um comando {{{switch}}} (vide aula [[Controle de Fluxo: Comandos de Seleção]]). Você pode também utilizá-lo para forçar uma terminação imediata de um laço, evitando o teste condicional normal do laço.
Quando o comando {{{break}}} é encontrado dentro de um laço, o laço é imediatamente terminado e o controle do programa retorna ao comando seguinte ao laço.
!! O comando {{{continue}}}
O comando {{{continue}}} trabalha de uma forma pouco parecida com a do comando {{{break}}}. Porém, em vez de forçar a terminação, {{{continue}}} força que ocorra a próxima iteração do laço, pulando qualquer código intermediário.
Para o laço {{{for}}}, o comando {{{continue}}} faz com que o incremento e o teste condicional sejam executados.
Para os laços {{{while}}} e {{{do ... while}}}, o controle do programa passa para o teste condicional.
{{{
int conta_espacos(const char * str) {
int i = 0, nesp = 0;
while ( str[i] ) {
if ( str[i] != ' ' )
continue;
nesp ++;
}
return nesp;
}
}}}
! Leitura Recomendada
* CCT capítulo 3
* K&R capítulos 3
|!Data |!Assunto |
| 18/03 |[[Introdução; visão geral de C]] |
| @@color(red):20/03@@ |@@color(green):PONTO FACULTATIVO@@ |
| 25/03 |[[Declarações: Identificadores e Tipos de Dados Básicos]] |
| 27/03 |[[Declarações: Variáveis e Classe de Memória]] |
| 01/04 |[[Declarações: Tipo de Acesso, Inicialização e Constantes]] |
| 03/04 |[[Operadores e Expressões: atribuições, aritmética e lógica]] |
| 08/04 |[[Operadores e Expressões: atribuições, aritmética e lógica]] |
| 10/04 |[[Operadores e Expressões: bit-a-bit e especiais]] |
| 15/04 |[[Operadores e Expressões: bit-a-bit e especiais]] |
| 17/04 |''1a Prova Escrita'' |
| 22/04 |[[Controle de Fluxo: Comandos de Seleção]] |
| 24/04 |[[Controle de Fluxo: Laços e Desvios Incondicionais]] |
| 29/04 |[[Exemplo: Calculadora RPN]]|
| @@color(red):01/05@@ |@@color(green):FERIADO@@ |
| 06/05 |[[Exemplo: Pilha de float]] |
| 08/05 |[[Vetores, matrizes e strings]] |
| @@color(red):13/05@@ |@@color(green): Sem aula, estarei no [[AOSE@AAMAS'08|http://grasia.fdi.ucm.es/aose08/]]@@ |
| @@color(red):15/05@@ |@@color(green): Sem aula, estarei no [[AOSE@AAMAS'08|http://grasia.fdi.ucm.es/aose08/]]@@ |
| 20/05 |[[Ponteiros]] |
| @@color(red):22/05@@ |@@color(green):FERIADO@@ |
| 27/05 |[[Exemplo: Lista de Strings]] |
| 29/05 |[[Vetores para Ponteiros, Ponteiros para Vetores e Ponteiros para Ponteiros]] |
| 03/06 |[[Funções: definição, declaração e chamada]] |
| @@color(red):05/06@@ |@@color(green):GREVE de ONIBUS@@|
| 10/06 |''2a Prova Escrita '' |
| 12/06 |[[Funções: main() e recursão]] |
| 17/06 |[[Funções: main() e recursão]] |
|@@color(red):19/06@@ |@@color(green):JIM@@ |
| 24/06 |[[Alocação Dinâmica]] |
| 26/06 |[[Estruturas]] |
| 01/07 |[[typedef, ponteiros para funções e union]] |
| 03/07 |[[Entrada/Saída: console]] |
| 08/07 |[[Entrada/Saída: arquivos]] |
| 10/07 |[[Enumerações e Campos de Bits]] |
| 15/07 |[[Pré-processador C]] |
| 17/07 |''3a Prova Escrita'' |
| 24/07 |''Reposição'' |
| 31/07 |''Final'' |
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};
//--
//-- Crypto functions and associated conversion routines
//--
// Crypto "namespace"
function Crypto() {}
// Convert a string to an array of big-endian 32-bit words
Crypto.strToBe32s = function(str)
{
var be = Array();
var len = Math.floor(str.length/4);
var i, j;
for(i=0, j=0; i<len; i++, j+=4) {
be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
}
while (j<str.length) {
be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
j++;
}
return be;
};
// Convert an array of big-endian 32-bit words to a string
Crypto.be32sToStr = function(be)
{
var str = "";
for(var i=0;i<be.length*32;i+=8)
str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
return str;
};
// Convert an array of big-endian 32-bit words to a hex string
Crypto.be32sToHex = function(be)
{
var hex = "0123456789ABCDEF";
var str = "";
for(var i=0;i<be.length*4;i++)
str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
return str;
};
// Return, in hex, the SHA-1 hash of a string
Crypto.hexSha1Str = function(str)
{
return Crypto.be32sToHex(Crypto.sha1Str(str));
};
// Return the SHA-1 hash of a string
Crypto.sha1Str = function(str)
{
return Crypto.sha1(Crypto.strToBe32s(str),str.length);
};
// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
Crypto.sha1 = function(x,blen)
{
// Add 32-bit integers, wrapping at 32 bits
add32 = function(a,b)
{
var lsw = (a&0xFFFF)+(b&0xFFFF);
var msw = (a>>16)+(b>>16)+(lsw>>16);
return (msw<<16)|(lsw&0xFFFF);
};
// Add five 32-bit integers, wrapping at 32 bits
add32x5 = function(a,b,c,d,e)
{
var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
return (msw<<16)|(lsw&0xFFFF);
};
// Bitwise rotate left a 32-bit integer by 1 bit
rol32 = function(n)
{
return (n>>>31)|(n<<1);
};
var len = blen*8;
// Append padding so length in bits is 448 mod 512
x[len>>5] |= 0x80 << (24-len%32);
// Append length
x[((len+64>>9)<<4)+15] = len;
var w = Array(80);
var k1 = 0x5A827999;
var k2 = 0x6ED9EBA1;
var k3 = 0x8F1BBCDC;
var k4 = 0xCA62C1D6;
var h0 = 0x67452301;
var h1 = 0xEFCDAB89;
var h2 = 0x98BADCFE;
var h3 = 0x10325476;
var h4 = 0xC3D2E1F0;
for(var i=0;i<x.length;i+=16) {
var j,t;
var a = h0;
var b = h1;
var c = h2;
var d = h3;
var e = h4;
for(j = 0;j<16;j++) {
w[j] = x[i+j];
t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
for(j=16;j<20;j++) {
w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
for(j=20;j<40;j++) {
w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
for(j=40;j<60;j++) {
w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
for(j=60;j<80;j++) {
w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
h0 = add32(h0,a);
h1 = add32(h1,b);
h2 = add32(h2,c);
h3 = add32(h3,d);
h4 = add32(h4,e);
}
return Array(h0,h1,h2,h3,h4);
};
}
//}}}
Starting with this revision, you can skin TiddlyWiki with a special StyleSheet tiddler containing your own CSS style sheet declarations. Unlike hacking the HTML directly, the StyleSheet tiddler withstands upgrading to a new version of the TiddlyWiki code (see HowToUpgrade). You can also use the NestedStyleSheets feature to structure your CSS declarations.
The ExampleStyleSheet shows some of the basic options you can control (see AnotherExampleStyleSheet for more complex examples). SaveChanges and then click refresh in your browser to see StyleSheet changes. Any errors in your CSS syntax will be caught and displayed, but they shouldn't stop TiddlyWiki from working.
You can customise the appearance and behaviour of TiddlyWiki to almost any degree you want:
* Use the ColorPalette to change the basic colour scheme
* Create a CustomStyleSheet for finer grained control over the appearance
* Customise the PageTemplate, ViewTemplate or EditTemplate to change the composition of the page and the layout of individual tiddlers
* Use off-the-shelf themes from [[TiddlyThemes|http://tiddlythemes.com/]]
* Visit the [[Configuration]] summary to see all the special configuration tiddlers
* Install [[Plugins]] to extend the core functionality (find them at [[TiddlyVault|http://tiddlyvault.tiddlyspot.com/]] or you can try [[writing or adapting your own|http://gimcrackd.com/etc/src/codex/]])
* Use TiddlyBookmarklets for low level hacking of TiddlyWiki documents
There are also a bunch of TiddlyWikiTools that you can use to enhance TiddlyWiki.
! Objetivos
Na primeira aula, vimos que um programa em C pode ser visto como uma seqüência de @@DECLARAÇÕES@@. De maneira geral, uma DECLARAÇÃO introduz um novo nome - um @@IDENTIFICADOR@@ - e associa a este uma interpretação. Tome como exemplo o seguinte trecho de código:
{{{
00: #include <stdio.h>
01: double x;
02:
03: void p(float b, int e) {
04: short int i;
05:
06: x = b;
07: ...
08: }
09:
10: int main() {
11: p(3.1415, 5);
12: printf("%f",x);
13: return 0;
14: }
}}}
Na linha 1, vemos uma DECLARAÇÃO de @@VARIÁVEL GLOBAL@@. Nas linhas 3 a 8, temos uma DECLARAÇÃO de @@FUNÇÃO@@ que, por sua vez, é formada por uma DECLARAÇÃO de @@PARÂMETROS@@ (linha 3), uma DECLARAÇÃO de @@VARIÁVEL LOCAL@@ (linha 4) e uma seqûência de comandos (linhas 5-7).
Em cada uma dessas DECLARAÇÕES um novo IDENTIFICADOR é introduzido com uma interpretação particular! Na declaração da linha 1, o IDENTIFICADOR introduzido é {{{x}}} e sua interpretação é VARIÁVEL GLOBAL do TIPO BÁSICO {{{double}}}. Na declaração das linhas 3 a 8, o IDENTIFICADOR é {{{p}}} e sua interpretação é FUNÇÃO que recebe como PARÂMETROS um valor do TIPO BÁSICO {{{float}}} e um valor do TIPO BÁSICO {{{int}}}; tem uma VARIÁVEL LOCAL do TIPO BÁSICO {{{short int}}}, executa os comandos das linhas 6-7 e ao final nada retorna ( TIPO BÁSICO {{{void}}}).
Note que, nesses exemplos, a interpretação dada a um IDENTIFICADOR está ligada de maneira íntima com um @@TIPO de DADOS BÁSICO@@.
Nesta aula, nosso objetivo é mostrar através de exemplos o que é um IDENTIFICADOR válido e quais são os TIPOS de DADOS BÁSICOS - os dois ingredientes fundamentais de toda DECLARAÇÃO em um programa C.
! IDENTIFICADORES
Em C, um IDENTIFICADOR é uma seqüência de LETRAS ou DÍGITOS onde:
* O primeiro caracter deve ser uma LETRA ( {{{'a',...,'z','A',...,'Z','_'}}} )
** O caracter {{{'_'}}} é contado como uma LETRA
* LETRAS maiúsculas (e.g., {{{'A'}}}) são consideradas diferentes de letras minúsculas (e.g., {{{'a'}}})
** isto implica que o IDENTIFICADOR {{{aux}}} é diferente de {{{Aux}}} que é diferente de {{{AUX}}}
* PALAVRAS RESERVADAS tais como {{{if}}}, {{{else}}}, {{{char}}}, {{{int}}}, ... não podem ser usadas como IDENTIFICADORES.
Pelo padrão C ANSI, um IDENTIFICADOR pode ter qualquer tamanho.
''Observações''
* Para //IDENTIFICADORES INTERNOS// (i.e., nomes restritos a uma única //UNIDADE de COMPILAÇÃO//), pelo menos os primeiros 31 caracteres são significativos; algumas implementações podem utilizar um conjunto maior de caracteres significativos.
* Já os //IDENTIFICADORES EXTERNOS// (i.e., nomes de de VARIÁVEIS GLOBAIS e FUNÇÕES compartilhados entre várias //UNIDADES de COMPILAÇÃO//) são mais restritos: as implementações podem considerar em casos extremos apenas 6 caracteres como significativos, e podem ignorar as distinções entre letras maiúsculas e minúsculas.
! Atividade 1: Validando Indentificadores
Vamos escrever um programa em C ({{{id.c}}}) que dado uma palavra (cadeia de caracteres) imprima na tela {{{é um identificador!}}} ou {{{não é um identificador!}}} caso a palavra obedeça ou não a definição de identificador dada acima.
DICA - começe o programa assim:
{{{
#include <stdio.h>
char str[80]; /* armazena uma cadeia de até 79 caracteres */
int main() {
printf("Digite uma palavra: ");
scanf("%s", str); /* le do usário uma cadeia de caracteres */
...
}
}}}
! TIPOS de DADOS BÁSICOS
Há cinco tipos de dados básicos em C:
* {{{char}}} : um único byte, capaz de conter um caracter no conjunto de caracteres local;
* {{{int}}} : um inteiro, normalmente refletindo o tamanho natural dos inteiros da máquina hospedeira;
* {{{float}}} : ponto flutuante em precisão simples;
* {{{double}}} : ponto flutuante em dupla precisão;
* {{{void}}} : conjunto vazio de valores.
Todos os outros tipos de dados em C são baseados em um desses tipos básicos.
!! Modificadores
Exceto {{{void}}}, os tipos de dados básicos podem ter vários MODIFICADORES precedendo-os. Um MODIFICADOR é usado para alterar o significado de um tipo básico para adaptá-lo à necessidade de diversas situações.
São MODIFICADORES de tipos:
<<<
{{{long}}}
{{{short}}}
{{{signed}}}
{{{unsigned}}}
<<<
[img[img/cap2.tipos.mod2.png]]
* {{{short}}} ou {{{long}}} - referem-se a diferentes tipos de inteiros:
** A palavra {{{int}}} pode ser omitida e normalmente o é!
*** {{{short}}} = {{{short int}}}
*** {{{long}}} = {{{long int}}}
** Obs.:
*** Alguns compiladores permitem {{{long long int}}} ! (Fora do Padrão ANSI)
** {{{long}}} pode também ser aplicado a {{{double}}} de tal modo que:
*** {{{float}}} ≤ {{{double}}} ≤ {{{long double}}}
* {{{signed}}} ou {{{unsigned}}} - podem ser aplicados a {{{char}}}, ou a {{{short}}} ou {{{long}}} ( {{{int}}} ).
** Equivalencias
*** {{{char}}} = {{{signed char}}} ou {{{char}}} = {{{unsigned char}}}, a depender da máquina hospedeira;
*** {{{signed int}}} = {{{int}}} = {{{signed}}}
*** {{{signed long}}} = {{{long}}}
*** {{{signed short}}} = {{{short}}}
*** {{{unsigned int}}} = {{{unsigned}}}
** Obs.:
*** Alguns compiladores podem permitir {{{unsigned double}}} ! (Fora do Padrão ANSI)
!! Tamanho e Faixa de Valores
O tamanho e faixa de valores dos tipos básicos de dados variam de acordo com:
* tipo do processador
* implementação do compilador
No entanto, o padrão ANSI C estipula valores mínimos:
[img[img/cap2.tab2_1.png]]
! Atividade 2: Explorando {{{<limits.h>}}}
Nos arquivos de cabeçalho {{{<limits.h>}}} e {{{<float.h>}}} encontram-se definidas constantes simbólicas para a faixa de valores e tamanho em bytes dos tipos de dados básicos e modificados da linguagem C, conforme foram implementados em um dado compilador/máquina.
Nesta atividade, o seu objetivo é escrever um programa {{{tipos.c}}} que inclua os arquivos de cabeçalho {{{<limits.h>}}} e {{{<float.h>}}} e imprima - para os tipos mostrados na tabela 2.1 - as seguintes informações :
{{{
TIPO VALOR_MIN VALOR_MAX TAMANHO em BYTES
char -128 127 1
unsigned char 0 255 1
signed char -128 127 1
...
}}}
Como ponto de partida, você pode iniciar o seu programa assim:
{{{
#include <limits.h>
#include <float.h>
char c;
unsigned char uc;
signed char sc;
int i;
...
int main(void) {
printf("TIPO\t\t\tVALOR_MIN\t\tVALOR_MAX\tTAMANHO em BYTES\n");
printf("char\t\t\t%i\t\t\t%i\t\t%i\n", CHAR_MIN, CHAR_MAX, sizeof c);
printf("unsigned char\t\t%i\t\t\t%i\t\t%i\n", 0, UCHAR_MAX, sizeof uc);
printf("signed char\t\t%i\t\t\t%i\t\t%i\n", SCHAR_MIN, SCHAR_MAX, sizeof sc);
...
}
}}}
! Leitura Recomendada
* CCT capítulo 2
* K&R capítulos 2
* Seebach, "Everything You Ever Wanted to Know about C Types"
** [[What's in a type?|http://www-128.ibm.com/developerworks/power/library/pa-ctypes1/index.html]]
** [[Floating point and derived types| http://www-128.ibm.com/developerworks/power/library/pa-ctypes2/index.html]]
** [[Implementation details|http://www-128.ibm.com/developerworks/power/library/pa-ctypes3/index.html]]
** [[Portability and pitfalls|http://www-128.ibm.com/developerworks/power/library/pa-ctypes4/index.html]]
* http://pt.wikipedia.org/wiki/Tipo_de_dado
Para detalhes sobre representacao de caracteres:
* http://www.ime.usp.br/~pf/algoritmos/aulas/char.html
Para detalhes sobre representação de números:
* inteiros ({{{int}}})
** http://www.ime.usp.br/~pf/algoritmos/aulas/int.html
* ponto flutuante ({{{float}}}, {{{double}}})
** http://en.wikipedia.org/wiki/Floating_point
** http://en.wikipedia.org/wiki/Double_precision
** http://en.wikipedia.org/wiki/IEEE_754
Para detalhes sobre o padrão ANSI C:
* Jones, Derek M. (2008) "[[The New C Standard: An Economic and Cultural Commentary|http://www.knosof.co.uk/cbook/cbook.html]]."
! Exercícios
# Faça por completo a atividade 1
# Faça por completo a atividade 2
# Utilizando os TIPOS inteiros em C, escreva programas para:
## Dado um número inteiro positivo n, calcular a soma dos n primeiros números naturais.
## Dado um número inteiro positivo n, imprimir os n primeiros naturais ímpares.
*** Exemplo: Para n=4 a saída deverá ser 1,3,5,7.
## Dados n e dois números inteiros positivos i e j diferentes de 0, imprimir em ordem crescente os n primeiros naturais que são múltiplos de i ou de j e ou de ambos.
*** Exemplo: Para n = 6 , i = 2 e j = 3 a saída deverá ser : 0,2,3,4,6,8.
## Dizemos que um número natural é triangular se ele é produto de três números naturais consecutivos. Exemplo: 120 é triangular, pois 4.5.6 = 120. Dado um inteiro não-negativo n, verificar se n é triangular.
## Dado um inteiro positivo p, verificar se p é primo.
## Dados três números naturais, verificar se eles formam os lados de um triângulo retângulo.
# Utilizando os TIPOS ponto flutuante em C, faça programas para os seguintes enunciados:
## Um programa que leia uma temperatura em graus celsius e a converta para fahrenheit.
## Uma pessoa aplicou um capital de x complexos (1) a juros mensais de z durante 1 ano. Deseja-se um programa que determine o montante de cada mês durante este período.
##Dados números reais a, b e c, calcular as raízes de uma equação do 2o grau da forma ax^2 + b^x + c = 0.
# Utilizando o TIPO {{{char}}}, re-escreva os programas anteriores para ao final perguntar ao usário: {{{deseja processar outro valor? [s/n]}}}. Se o usuário digitar {{{'s'}}} ou {{{'S'}}} o programa deve continuar processando uma nova entrada; caso contrário deve terminar.
! Objetivo
Nas últimas aulas, estudamos a forma geral de uma @@DECLARAÇÃO de VARIÁVEIS@@ ( global ou local ):
{{{
ESPEC-DECLARAÇÃO
DECLARADOR-1 = INICIALIZADOR-1,
...,
DECLARADOR-n = INCIALIZADOR-n;
}}}
Recapitulando,
* o {{{ESPEC-DECLARAÇÃO}}} é uma seqüência composta de:
<<<
* @@OBRIGATORIAMENTE@@, um ESPECIFICADOR de TIPO de DADO ( acompanhado ou não de MODIFICADORES )
** {{{char}}}
*** {{{signed}}} e {{{unsigned}}}
** {{{int}}}
*** {{{signed}}} e {{{unsigned}}}
*** {{{long}}} e {{{short}}}
** {{{float}}}, {{{double}}} e {{{long double}}}
* @@OPCIONALMENTE@@, um ESPECIFICADOR da CLASSE de MEMÓRIA
** {{{auto}}}
** {{{register}}}
** {{{static}}}
** {{{extern}}}
<<<
* cada {{{DECLARADOR-i}}} (em sua forma mais simples) consiste em um IDENTIFICADOR
* cada {{{ = INICIALIZADOR-i }}} é @@OPCIONAL@@ e (em sua forma mais simples) consiste em uma CONSTANTE
Na aula de HOJE, nosso objetivo é tornar este quadro mais completo apresentando um terceiro e último tipo de ESPECIFICADOR que pode ser utilizado em declarações:
* @@ESPECIFICADOR de TIPO de ACESSO@@
** {{{const}}} e {{{volatile}}}
Além disso, discutiremos as regras gerais do processo de @@INICIALIZAÇÃO de VARIÁVEIS@@ e ao final apresentaremos a forma das @@CONSTANTES@@ associadas aos tipos básicos de dados em C.
! ESPECIFICADOR de TIPO de ACESSO
Em uma declaração de variáveis (globais ou locais), um ESPECIFICADOR de TIPO de ACESSO pode ser utilizado para estabelecer a maneira como as variáveis podem ser acessadas ou modificadas. Em C, há duas PALAVRAS RESERVADAS que funcionam como ESPECIFICADORES de TIPO de ACESSO durante uma declaração de variáveis:
* {{{const}}}
* {{{volatile}}}
''const''
* variáveis declaradas {{{const}}} podem ser inicializadas mas não modificadas
* usar {{{const}}} é útil quando vc. quer ter certeza que (parte do) seu código não irá alterar valores de certas variáveis; uma situação típica é na declaração de CONSTANTES SIMBÓLICAS, como em:
{{{
const double PI = 3.1415927;
}}}
* Uma outra situação é quando vc. passa um argumento a uma função através de um parâmetro e deseja que o valor do argumento não seja em hipótese alguma modificado pelo código da função ... @@Mais detalhes somente em aulas futuras ...@@
''volatile''
* este ESPECIFICADOR indica que a variável pode sofrer modificações de maneira não especificada pelo programa. Em outras palavras, uma variável {{{volatile}}} pode ter seu conteúdo alterado (@@via apontadores e endereços@@) por comandos que fazem parte de outros programas.
* Na prática, {{{volatile}}} indica ao compilador para não realizar otimização de EXPRESSÕES contendo tais variáveis.
''Observação''
* Os ESPECIFICADORES {{{const}}} e {{{volatile}}} podem ser utilizados juntos!
* Exemplo:
{{{
const volatile unsigned short int port = 80;
}}}
** Neste exemplo, a variável {{{port}}} não pode ser modificado pelo programa sendo escrito mas pode ter seu valor modificado por comandos externos ao programa!
! Atividade 1: Variáveis {{{const}}}
Teste o código abaixo e observe o Erro de Compilação !
{{{
const int x = 100;
int main() {
x = x + 1; /* Isto irá gerar um erro de compilação */
}
}}}
! Inicialização de Variáveis
Inicializar uma variável significa dar à variável um valor, no mesmo momento em que ela é declarada.
De maneira geral, o valor inicial de uma variável pode ser o resultado de uma EXPRESSÃO envolvendo dentre outros CONSTANTES, OPERADORES e outras VARIÁVEIS.
''Regras de Inicialização''
* Variáveis GLOBAIS e variáveis LOCAIS {{{static}}} declaradas COM {{{=INICIALIZADOR}}} são inicializadas com o valor de {{{INICIALIZADOR}}} apenas uma vez no começo do programa
* Variáveis GLOBAIS e variáveis LOCAIS {{{static}}} declaradas SEM {{{=INICIALIZADOR}}} são inicializadas com ZERO apenas uma vez no começo do programa
* Variáveis LOCAIS {{{auto}}} e {{{register}}} declaradas COM {{{=INICIALIZADOR}}} são inicializadas com o valor de {{{INICIALIZADOR}}} toda vez que o BLOCO no qual foram declaradas for ativado
* Variáveis LOCAIS {{{auto}}} e {{{register}}} declaradas SEM {{{=INICIALIZADOR}}} têm valor DESCONHECIDO antes de ser efetuada uma primeira atribuição a elas
* Apenas DECLARAÇÕES que são DEFINIÇÕES podem conter {{{=INICIALIZADOR}}}. Assim, variáveis declaradas {{{extern}}} não podem ser inicializadas no momento de suas declarações!
! Atividade 2 : Inicialização de Variáveis
Compile, execute e compare a saída do programa abaixo com o que foi dito acima sobre inicialização de variáveis:
{{{
#include <stdio.h>
int Gi = 3, G_; /* variáveis GLOBAIS */
void f(); /* DEClARAÇAO de f() */
void g() { /*DECLARACAO/DEFINICAO de g() */
char ga_;
printf("\n. g():\n");
printf(" ga_ = %i\n", ga_);
printf("\n > para terminar digite 't' < ");
scanf(" %c",&ga_);
if (ga_ != 't' )
f(); /* ativa função f() */
printf("\n# g():\n");
}
void f() { /* DEFINICAO de f() */
static int fsi = 3, fs_;
int fai = 3, fa_;
printf("\n. f():\n");
printf(" fsi = %i\n", fsi);
printf(" fs_ = %i\n", fs_);
printf(" fai = %i\n", fai);
printf(" fa_ = %i\n", fa_);
fsi ++;
fs_ ++;
fai ++;
fa_ ++;
printf("\n Após incremento:\n\n");
printf(" fsi = %i\n", fsi);
printf(" fs_ = %i\n", fs_);
printf(" fai = %i\n", fai);
printf(" fa_ = %i\n", fa_);
g(); /* ativa função g() */
printf("\n# f():\n");
}
int main () {
int m_;
printf("\n. main()\n");
printf(" Gi = %i\n",Gi);
printf(" G_ = %i\n",G_);
printf(" m_ = %i\n",m_);
f(); /* Ativa função f() */
printf("\n# main()\n");
}
}}}
! Constantes
Um dos elementos principais na INICIALIZAÇÃO de VARIÁVEIS (e de EXPRESSÕES em geral) são as constantes.
Constantes são VALORES ESPECÍFICOS de qualquer um dos TIPOS de DADOS básicos.
[img[img/jgrasp-const-int.png]]
[img[img/jgrasp-const-fcs.png]]
''Observações''
* Nas constantes caracter e string, além dos caracteres comuns, caracteres de controle (não imprimíveis) são escritos através de um 'código de barra invertida' (veja tabela abaixo)
* Não confunda constantes caracter com string! Uma constante de um único caracter é colocada entre aspas simples; constantes string são colocadas entre aspas duplas. Ou seja,
** {{{'a'}}} (constante {{{char}}}) é diferente de {{{"a"}}} (constante //string//)
[img[img/cap2.tab2_2.png]]
! Leitura Recomendada
* CCT capítulo 2
* K&R capítulos 2 e 4
! Exercícios
# Considere o programa da atividade 2. Descreva passo a passo como o ambiente de execução (área estática de dados + pilha de execução) evolui durante a execução do programa. Na sua descrição localize onde são alocadas as variáveis do programa.
# Explique qual a diferença entre '0', '\0', "0" .
# A matemática e a física é repleta de exemplos de constantes fundamentais. Utilizando variáveis decladas com o ESPECIFICADOR {{{const}}}, mostre como você representaria as seguintes constantes abaixo:
** razão áurea (φ);
** número de Euler (e);
** velocidade da luz no vácuo (c);
** massa do elétron em repouso (me);
** número de Avogadro (L);
# Escreva um programa que converta números de decimais para hexadecimal e octal. Dica: uma maneira simples de fazer o programa é ler os números em decimal e os imprimir na tela como constantes inteiras escritas em hexadecimal e octal. Para saber como usar a função {{{printf}}} para imprimir inteiros em hexadecimal e octal cosulte os livros ou a internet. Veja por exemplo, a página abaixo:
** http://www.dca.fee.unicamp.br/cursos/EA876/apostila/HTML/node131.html
# O programa abaixo, quando compilado, gera uma mensagem de erro.
## Que mensagem de erro é essa?
## Como o programa pode ser corrigido para eliminar a mensagem de erro?
## Após o programa ter sido corrigido e compilado com sucesso, que valores serão impressos na tela ?
[img[img/jgrasp-exerc4_1.png]]
! Objetivo
Na última aula, vimos que uma @@DECLARAÇÃO@@ introduz um novo @@IDENTIFICADOR@@ e associa a este uma interpretação. Dentre as interpretações possíveis, um IDENTIFICADOR pode ser declarado para ser o nome símbólico de uma VARIÁVEL. Neste caso, temos um dos mais importantes tipos de DECLARAÇÃO - a @@DECLARAÇÃO de VARIÁVEIS@@.
Nesta aula, nosso objetivo é estudar:
* a forma geral de DECLARAÇÕES de VARIÁVEIS em C
* a noção de CLASSE de MEMÓRIA associada a uma VARIÁVEL
! Variáveis
VARIÁVEIS são abstrações de locais de armazenamento de dados. Os dados armazenados em uma VARIÁVEL podem mudar ao longo da execução de um programa. Daí o nome VARIÁVEL.
Uma VARIÁVEL possui dois atributos principais:
* um @@TIPO de DADO@@ : determina o significado dos valores achados em uma VARIÁVEL.
* uma @@CLASSE de MEMÓRIA@@ (ou @@CLASSE de ARMAZENAMENTO@@) : determina o tempo de vida e a área de memória na qual a VARIÁVEL é alocada.
Variáveis também podem ter:
* um @@TIPO de ACESSO@@ : determinam a maneira como as variáveis podem ser acessadas ou modificadas.
Variáveis podem ser declaradas tanto fora quando dentro de funções. No primiro caso as variáveis são ditas @@GLOBAIS@@; no segundo caso, @@LOCAIS@@.
! Declaração de Variáveis
Em C, uma @@DECLARAÇÃO de VARIÁVEL@@ assume a seguinte forma geral:
{{{
ESPEC-DECLARAÇÃO
DECLARADOR-1 = INICIALIZADOR-1,
...,
DECLARADOR-n = INCIALIZADOR-n;
}}}
Onde:
* @@ESPEC-DECLARAÇÃO@@ e cada @@DECLARADOR-i@@ são obrigatórios;
* cada @@ = INICIALIZADOR-i@@ é opcional.
@@ESPEC-DECLARAÇÃO@@ é uma sequência composta de pelo menos um dentre três categorias de ESPECIFICADOR:
* ESPECIFICADOR do TIPO de DADO;
** {{{int}}}, {{{char}}}, {{{float}}}, {{{double}}} e seus MODIFICADORES {{{long}}}, {{{short}}}, {{{signed}}} e {{{unsigned}}}
* ESPECIFICADOR da CLASSE de MEMÓRIA;
** {{{auto}}}, {{{register}}}, {{{static}}} e {{{extern}}}
* ESPECIFICADOR do TIPO de ACESSO;
** {{{const}}} e {{{volatile}}}
A forma mais simples de um {{{DECLARADOR}}} é um IDENTIFICADOR. Nesta aula, iremos considerar como {{{DECLARADOR}}} apenas IDENTIFICADORES.
Um {{{INICIALIZADOR}}}, de maneira geral, consiste em uma EXPRESSÃO.
! Ambiente de Execução C
Em C, há quatro locais onde uma variável pode ser alocada:
* na @@ÁREA de DADOS ESTÁTICA@@
* na @@PILHA de EXECUÇÃO@@
* em @@REGISTRADORES@@
* no @@HEAP@@
[img[img/cap1.mmc1.png]]
[img[img/cap1.fig1_2.png]]
! Especificadores da Classe de MEMÓRIA
Em C, há quatro PALAVRAS RESERVADAS que funcionam como ESPECIFICADORES da CLASSE de MEMÓRIA durante a DECLARAÇÃO de uma VARIÁVEL:
* {{{auto}}} - define variáveis automáticas na PILHA de EXECUÇÃO
** são sempre variáveis locais a um BLOCO e que são descartados na saída do BLOCO;
* {{{register}}} - define variáveis automáticas em REGISTRADORES
** são sempre variáveis locais a um BLOCO e que são descartados na saída do BLOCO;
* {{{static}}}
** podem ser variáveis locais a um BLOCO ou externas a todos os BLOCOS
** retêm seus valores durante toda execução do programa pois são alocadas na ÁREA de DADOS ESTÁTICA
** quando em DECLARAÇÕES LOCAIS, @@DEFINE@@ variáveis estáticas (escopo de BLOCO)
** quando em DECLARAÇÕES GLOBAIS, @@DEFINE@@ variáveis estáticas com //ligação interna// (escopo de UNIDADE DE COMPILAÇÃO)
* {{{extern}}}
** podem ser variáveis locais a um BLOCO ou externas a todos os BLOCOS
** quando em DECLARAÇÕES LOCAIS, @@DECLARA@@ variáveis estáticas que foram definidas fora do BLOCO das declarações
** quando em DECLARAÇÕES GLOBAIS, @@DECLARA@@ variáveis estáticas com //ligação externa//, i.e, que foram definidas fora da @@UNIDADE DE COMPILAÇÃO@@ das declarações
''Observação''
* um @@BLOCO@@ é qualquer parte de um programa delimitada por @@{ }@@; um BLOCO pode ser o corpo de função bem como o corpo de um comando composto como {{{if, while}}}, etc.
A seguir ilustram-se a utilização de Variáveis {{{auto}}}, {{{register}}} e {{{static}}} LOCAIS. Variáveis {{{static}}} GLOBAIS e variáveis {{{extern}}} serão discutidas em aulas futuras.
! Atividade 1: Variáveis {{{auto}}} e {{{register}}}
Para ilustrar o uso de {{{auto}}} e {{{register}}}, compile e execute o programa abaixo.
{{{
/* teste_fat.c ( rev 1.1 )
**/
/* função fat:
calcula fatorial de x
**/
unsigned long fat(unsigned short x) {
register int i; /* acesso o mais rápido possível; se não possível em pilha */
unsigned long ret; /* alocada na pilha; se possível acesso o mais rápido possível */
ret = 1;
for ( i = 1; i <= x; i++ )
ret = ret * i;
return ret;
}
/* função main:
testa a função fat acima
**/
int main() {
auto int i; /* alocada na pilha */
for( i = 0; i < 20; i++ )
printf("fat(%i) = %lu \n",i,fat(i));
}
}}}
''A Fazer -'' No programa acima:
* declare uma VARIÁVEL GLOBAL especificando {{{auto}}} como CLASSE de ARMAZENAMENTO, compile e observe as mensagens geradas pelo compilador;
* declare uma VARIÁVEL GLOBAL especificando {{{register}}} como CLASSE de ARMAZENAMENTO, compile e observe as mensagens geradas pelo compilador;
Que conclusões podemos tirar sobre o uso de {{{auto}}} e {{{register}}} em DECLARAÇÕES GLOBAIS?
! Atividade 2: Variáveis {{{static}}} em DECLARAÇÕES LOCAIS
Para ilustrar o uso dos ESPECIFICADORES {{{static}}} em DECLARAÇÕES LOCAIS podemos refatorar o programa anterior da seguinte maneira:
* para n > 12, fat(n) estoura a representação {{{unsigned long int}}}
* assim, uma primeira medida deve ser barrar o cálculo de fat(n) para n>12
* dado que o número de valores possíveis é pequeno, uma segunda idéia é armazenar os valores já calcular para evitar repetir cálculos em chamadas futuras.
{{{
/* teste_fat.c (rev 1.2)
**/
/* função fat:
para x <=12, calcula fatorial de x
para x > 12, retorna 0
**/
unsigned long fat(unsigned short x) {
register int i;
static unsigned long ret[13];
if ( x > 12 )
return 0;
if ( ret[x] != 0 )
return ret[x];
ret[x] = 1;
for ( i = 1; i <= x; i++ )
ret[x] = ret[x] * i;
return ret[x];
}
/* função main:
testa a função fat acima
**/
int main() {
int i;
for( i = 0; i < 20; i++ )
printf("fat(%i) = %lu \n",i,fat(i));
}
}}}
Em DECLARAÇÕES LOCAIS, o especificador {{{static}}} é usado para indicar uma variável que é DECLARADA ~LOCALmente mas que irá residir na área de VARIÁVEIS GLOBAIS. Há duas conseqüências:
* por se tratar de uma declaração local, a variável só é visível no BLOCO onde foi declarada
** por exemplo, a variável {{{static unsigned long ret[12]}}} só é visível dentro da função {{{fat}}}
* por residir na área de variáveis globais, a variável reterá seu valor entre ativações sucessivas do BLOCO onde foi declarada
** por exemplo, a variável {{{static unsigned long ret[12]}}} retém seus valores mesmo quando a função {{{fat}}} não está executando. Assim, na primeira vez que se chama {{{fat(5)}}}, o valor correspondente é calculado e armazenado em {{{ret[5]}}}. Em uma segunda chamada {{{fat(5)}}}, ao invés de se realizar o mesmo cálculo novamente, o valor é recuperado de {{{ret[5]}}}. Em outras palavras, a função passa a "lembrar" cálculos anteriores!
''A Fazer '' - No programa acima:
* na DECLARAÇÃO da variável {{{ret}}}, elimine o ESPECIFICADOR {{{static}}}, compile, execute o programa e verifique o funcionamento do programa. Explique a saída gerada!
! Leitura Recomendada
* CCT capítulo 2
* K&R capítulos 2 e 4
* Franek, Frantisek (2003) "Memory as a Programming Concept in C and C++ ." Cambridge University Press.
! Exercícios
* Conside o seguinte programa
{{{
int i;
void g() {
static int j;
j = i;
i = i * 2;
printf("g(){ i = %d j = %d }\n",i,j);
}
void f() {
i = 2;
g();
printf("f() { i = %d }\n",i);
}
int main() {
int i;
i = 3;
f();
g();
printf("main() { i = %d }\n",i);
return 0;
}
}}}
** Qual a saída gerada na tela quando o programa é executado?
** Descreva passo a passo como o ambiente de execução (área estática de dados + pilha de execução) evolui durante a execução do programa.
* Utilizando variáveis {{{auto}}} e {{{register}}}, escreva programas para calcular:
** exponenciação inteira, i.e, a ^ b, onde b é um número inteiro.
** raiz quadrada de x, utilizando o método de newton ( onde r(x) representa a raiz de x)
*** [img[img/exer.raiz.png]]
** cosseno, utilizando a série
*** [img[http://www.ime.usp.br/~macmulti/figuras/Image26.gif]]
*** utilize a função {{{fat()}}} desenvolvida na atividade 2
*** veja como exemplo o [[Programa seno]] discutido em sala de aula
[[Freqüência]]
[[Cronograma]]
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};
//--
//-- Deprecated code
//--
// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};
// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = function(w)
{
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var text = lookaheadMatch[1];
if(config.browser.isIE)
text = text.replace(/\n/g,"\r");
createTiddlyElement(w.output,"pre",null,null,text);
w.nextMatch = lookaheadRegExp.lastIndex;
}
};
// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
createTiddlyElement(place,"br");
};
// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
var i = this.indexOf(item);
return i == -1 ? null : i;
};
// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
return store.getLoader().internalizeTiddler(store,this,title,divRef);
};
// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
return store.getSaver().externalizeTiddler(store,this);
};
// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
return store.allTiddlersAsHtml();
}
// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
refreshPageTemplate(title);
}
// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
story.displayTiddlers(srcElement,titles,template,animate);
}
// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
story.displayTiddler(srcElement,title,template,animate);
}
// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;
// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");
}
//}}}
[img[img/cap9.tab9_1.png]]
! {{{fopen(), fclose()}}}
* {{{#include <stdio.h>}}}
** {{{FILE * fopen(const char * nomearq, const char * modo);}}}
** {{{int fclose(FILE * fp);}}}
[img[img/cap9.tab9_2.png]]
! {{{putc(), fputc(), getc(), fgetc()}}}
* {{{#include <stdio.h>}}}
** {{{int putc(int char, FILE * fp);}}}
** {{{int fputc(int char, FILE * fp);}}}
** {{{int getc(FILE * fp);}}}
** {{{int fgetc(FILE * fp);}}}
! Exemplo 1
{{{
/** ktod.c */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
FILE * fp;
char ch;
if ( argc != 2 ) {
printf("sintaxe:\n");
printf(" %s NOME_ARQ\n",argv[0]);
exit (1);
}
fp = fopen(argv[1],"w");
if ( fp == NULL ) {
printf("O arquivo %s não pode ser aberto.\n",argv[1]);
exit(1);
}
do {
ch = getchar();
putc(ch, fp);
} while ( ch != '$' );
fclose(fp);
}
}}}
! Exemplo 2
{{{
/** dtos.c */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
FILE * fp;
char ch;
if ( argc != 2 ) {
printf("sintaxe:\n");
printf(" %s NOME_ARQ\n",argv[0]);
exit (1);
}
fp = fopen(argv[1],"r");
if ( fp == NULL ) {
printf("O arquivo %s não pode ser aberto.\n",argv[1]);
exit(1);
}
ch = getc(fp);
while ( ch != EOF ) {
putchar(ch);
ch = getc(fp);
}
fclose(fp);
}
}}}
! {{{fputs() , fgets()}}}
* {{{#include <stdio.h>}}}
** {{{int fputs(const char * str, FILE * fp);}}}
** {{{char * fgets(char *str, int length, FILE * fp);}}}
! {{{fread() , fwrite()}}}
* {{{#include <stdio.h>}}}
** {{{size_t fread(void * buffer, size_t num_bytes, size_t count, FILE * fp);}}}
** {{{size_t fwrite(const void * buffer, size_t num_bytes, size_t count, FILE * fp);}}}
! Leitura Recomendada
** CCT Cap 9
** http://www.dee.feis.unesp.br/graduacao/disciplinas/langc/modulo_linguagemc/modulo8.htm
! Exercícios
''1.'' Refaça os programas dos exemplos 3 e 4 utilizando {{{fputs()}}} e {{{fgets()}}}.
''2.'' Escreva um programa que abra um arquivo texto e conte o número de caracteres presentes nele. Imprima o número de caracteres na tela.
''3.'' Considere um arquivo de dados do tipo texto com o seguinte conteúdo:
<<<
{{{
3
ZE SA
8.5
10.0
ANTONIO SANTOS
7.5
8.5
SEBASTIAO OLIVEIRA
5.0
6.0
}}}
<<<
** O arquivo acima é apenas um exemplo. Nestes arquivos de alunos a primeira linha contém o número de alunos no arquivo. As linhas seguintes contém os seguintes dados:
*** nome do aluno com no máximo 50 caracteres;
*** nota da primeira prova;
*** nota da segunda prova.
** Escreva um programa que imprima os nomes de todos os alunos que têm a média das duas notas menor que 7.0
''4.'' Escreva um programa que grave os dados lidos no exercício anterior em um arquivo do tipo binário de acesso aleatório. O número que indica quantos alunos devem ser lidos (primeira linha do arquivo) não deve ser gravado no arquivo binário. Nesta questão os dados devem estar obrigatoriamente armazenados em um vetor de estruturas do seguinte tipo:
{{{
typedef struc _aluno
{
char nome[81];
float n1, n2;
} ALUNO;
}}}
''5.'' Escreva um programa que leia de um arquivo, cujo nome sera fornecido pelo usuario, um conjunto de numeros reais e armazena em um vetor. O tamanho máximo do vetor e dado pela constante TAM_MAX. A quantidade de numeros no arquivo varia entre 0 e TAM_MAX. O programa ao final calcula a media dos numeros lidos.
''6.'' Faça um programa que leia 10 caracteres e armazene em um arquivo 10 cópias de cada um. Exiba o conteúdo do arquivo.
''7.'' Crie uma função que receba duas strings como parâmetros, uma com um endereço de arquivo e outra com um texto qualquer, e adicione o texto no fim do arquivo.
''8.'' Utilizando a função do exercício anterior faça um programa que gere 10 arquivos com o nome "Teste" e extensões "01", ..., "10". Cada um contendo o texto "Texto do arquivo [NÚMERO DO ARQUIVO]".
''9.'' Escreva um programa para armazenar o telefone de 5 amigos atravez da estrutura
{{{
struct pessoa{
char nome[50];
int idade;
float altura;
char telefone[10];
} amigos[5];
}}}
a ser preenchida pelo usuário antes do armazenamento de cada registro.
''10.'' Faça um programa que leia os dados do arquivo gerado no exercício anterior e salve-os num novo arquivo utilizando uma saída formatada.
{{{
FORMATO:
--------
[nome] tem [idade] anos e [altura] de altura.
Tel.: [telefone].
--------
}}}
''11.'' Escreva um programa que leia um arquivo texto contendo linhas de dados. Em cada linha do arquivo há o nome de um aluno e duas notas. Estes dados estão separados por ponto e vírgula. Existe um ponto e vírgula ao final de cada linha. O formato dos dados e o seguinte:
{{{
ze sa; 10.0; 9.0;
antonio silva: 9.0; 7.0;
}}}
O programa deve ler estes dados e imprimir os valores lidos, a média das duas notas e se o aluno foi aprovado ou não (media >= 5). O formato de saida e:
{{{
ze sa 10.0 8.0 9.0 aprovado
antonio silva 9.0 7.0 8.0 aprovado
}}}
''12.'' Faça um programa que ao receber o nome de um arquivo, gere uma cópia deste.
''13.'' Escreva um programa que compare dois arquivos especificados pelo usuário e imprima sempre que os caracteres dos dois arquivos coincidirem. Por exemplo:
{{{
arquivo1.c
Olá, pessoal!
arquivo2.c
Oi, como vai?
}}}
Neste caso, os caracteres na primeira e décima primeira posição são iguais nos dois arquivos. A saída do seu programa deve ser algo como:
{{{
1 - O (79)
11 - a (97)
}}}
Os valores entre parenteses são os respectivos códigos ASCII dos caracteres.
! Lendo e Escrevendo Caracteres
* {{{#include <stdio.h>}}}
** {{{int getchar(void);}}}
** {{{int putchar(int c);}}}
* {{{#include <conio.h>}}}
** {{{int getch(void)}}}
** {{{int getche(void)}}}
! Lendo e Escrevendo Strings
* {{{#include <stdio.h>}}}
** {{{char * gets(char *str);}}}
** {{{int puts(const char *str);}}}
[img[img/cap8.tab8_1.png]]
! Exemplo 1
{{{
#include <stdio.h>
#include <ctype.h>
main()
{
char ch;
printf("Digite algum texto (termine com ponto para sair)\n");
do {
ch = getchar();
if ( islower(ch) )
ch = toupper(ch);
else
ch = tolower(ch);
putchar(ch);
} while ( ch != '.' );
}
}}}
! Atividade 1
Refaça o programa acima utilizando {{{getch()}}} e {{{getche()}}}.
! Entrada/Saída Formatada
* {{{#include <stdio.h>}}}
** {{{int printf(const char * string_de_controle, ...);}}}
** {{{int scanf(const char * string_de_controle, ...);}}}
!{{{printf()}}}: Formato Geral
[img[img/cap8.tab8_2.png]]
!{{{printf()}}}: Formato Detalhado
[img[img/es-printf-formato-detal.png]]
! Exemplo 2
{{{
printf ("\nResultado :%3.2f",num);
printf ("Frase : %s\nContador = %x",string,cont);
printf ("a : %-5d b : %-5d c : %-5d",a,b,c);
}}}
! Atividade 1
Teste o trecho de código acima em um programa.
! {{{scanf()}}}: Formato
[img[img/es-scanf-formato.png]]
[img[img/es-scanf-formato-detal.png]]
[img[img/es-scanf-formato-detal-2.png]]
! Leitura Recomendada
** CCT Cap 8.
** http://www.dee.feis.unesp.br/graduacao/disciplinas/langc/modulo_linguagemc/modulo4.htm
! Enumerações
Uma enumeração é uma extensão da linguagem C acrescentada pelo padrão ANSI. Uma //enumeração// é uma declaração de um novo tipo de dados que consiste em um conjunto de constantes inteiras que especficam todos os valores legais que uma variável desse tipo pode ter.
Enumerações são definidas de forma semelhante a estruturas; no entanto, utiliza-se a palavra-chave ''enum'' para assinalar o início de um tipo de enumeração.
FORMA GERAL:
{{{
enum identificador {
Simbolo_1,
Simbolo_2,
...
Simbolo_n
} var_1, var_2, ..., var_n;
}}}
Em uma enumaração cada {{{Simbolo_i}}} representa um valor inteiro. Cada símbolo recebe um valor maior em uma unidade do precedente. Por default, o valor do primeiro símbolo é 0. No entanto, você pode especificar o valor de um ou mais símbolos usando um inicializador. O símbolos que aparecem após os inicializadores recebem valores maiores que o da inicialização precedente.
!! Exemplos
{{{
enum dt_wday {
Sunday ,
Monday ,
Tuesday ,
Wednsday ,
Thursday ,
Friday ,
Saturday
};
enum dt_month{
January = 1 ,
February ,
Mars ,
April ,
May ,
June ,
July ,
August ,
September ,
October ,
November ,
December
};
}}}
! Campos de Bits
[img[img/cap7.bitfield.png]]
[img[img/cap7.bitfield2.png]]
!! Exemplo
{{{
struct {
unsigned mday : 5;
unsigned month: 4;
unsigned year :22;
unsigned isBCE: 1;
} bitf;
}}}
! Exemplo Completo
O programa abaixo ilustra todos os mecanismos de definição de novos tipos estruturados pelo usuário:
* estruturas {{{struct}}}
* definição de novos nomes para tipos {{{typedef}}}
* enumerações {{{enum}}}
* uniões {{{union}}}
* campos de bits {{{struct}}}
Além disso, o exemplo também aborda o uso de funções da biblioteca {{{<time.h>}}}.
Para o entedimento do exemplo que trata de datas do calendário gregoriano você pode consultar:
* http://en.wikipedia.org/wiki/Gregorian_calendar
Para implementação do algoritmo DOOMSDAY para o cálculo do dia da semana de uma data, consulte:
* http://en.wikipedia.org/wiki/Doomsday_algorithm
{{{
/** date.h
Author: Luciano R. Coutinho, 2007.
lrc@deinf.ufma.br
*/
#ifndef DATE_H
#define DATE_H
#include <limits.h>
/*
* A type for storing dates in the range:
* from Jan 1st , year 2^22 BCE
* to Dec 31th, year 2^22
*/
#if ( UINT_MAX < 0xffffffff )
typedef long date_t;
#else
typedef int date_t;
#endif
enum dt_wday {
Sunday ,
Monday ,
Tuesday ,
Wednsday ,
Thursday ,
Friday ,
Saturday
};
enum dt_month{
January = 1 ,
February ,
Mars ,
April ,
May ,
June ,
July ,
August ,
September ,
October ,
November ,
December
};
struct dt {
enum dt_wday wday; /* day of the week : 0 .. 6 */
unsigned mday; /* day of the month : 1 .. 31 */
unsigned yday; /* days since Jan. 1 : 1 .. 366 */
unsigned mweek; /* week of the month : 0 .. 5 */
unsigned yweek; /* week of the year : 0 .. 53 */
enum dt_month month; /* month : 1 .. 12 */
long year; /* year : -2^22 .. 2^22 */
unsigned isBCE; /* is Before Common Era ? */
long serial; /* number of days */
};
date_t date(date_t *); /* get current date */
date_t mkdate(struct dt *); /* code struct dt* in a date_t */
struct dt * gcdate(date_t); /* decode date_t in a struct dt */
struct dt * diffdate(date_t,date_t); /* interval between dates */
size_t strfdate(char*, size_t, const char*, const struct dt*);
int printf_date(const char *, const struct dt*);
int scanf_date (const char *, const struct dt*);
#endif
}}}
{{{
/** date.c
Author: Luciano R. Coutinho, 2007.
lrc@deinf.ufma.br
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "date.h"
union date_t {
date_t ival;
struct {
unsigned mday : 5;
unsigned month: 4;
unsigned year :22;
unsigned isBCE: 1;
} bitf;
};
/* Global Shared */
static struct dt dt_buf;
static int num_days[13] = {
0 , /* skiped */
31, /* January */
28, /* February */
31, /* Mars */
30,
31,
30,
31,
31,
30,
31,
30,
31 /* December */
};
/* Functions */
date_t date(date_t * d) {
time_t now = time(NULL);
struct tm *tm_now = localtime(&now);
union date_t ud;
ud.bitf.mday = tm_now->tm_mday;
ud.bitf.month= tm_now->tm_mon + 1;
ud.bitf.year = tm_now->tm_year + 1900;
ud.bitf.isBCE= 0;
if ( d )
*d = ud.ival;
return ud.ival;
}
/* Gregorian Calendar
The Gregorian calendar system adopts the following leap year rule:
* Every year that is exactly divisible by four is a leap year, except for years
that are exactly divisible by 100; the centurial years that are exactly
divisible by 400 are still leap years. For example, the year 1900 is not a leap
year; the year 2000 is a leap year.
Doomsday Algorithm
* It takes advantage of the fact that within any calendar year, some days (e.g., 3/1, 4/4, 6/6, 8/8, 10/10, 12/12, the last day of February) always occur on the same day of week - the so-called "doomsday".
DOOMSDAY(y) = (Tuesday + (y) + (y)/4 - (y)/100 + (y)/400)%7
*/
static enum dt_wday calculate_wday(union date_t ud) {
}
static short gc_calculate_yday(union date_t ud) {
}
static short gc_calculate_mweek(union date_t ud) {
}
static short gc_calculate_yweek(union date_t ud) {
}
static long gc_calculate_serial(union date_t ud) {
}
/** interprets a given date_t as a Gregorian calendar date */
struct dt * gcdate(date_t d) {
union date_t ud = { d };
dt_buf.mday = ud.bitf.mday ;
dt_buf.month= ud.bitf.month;
dt_buf.year = ud.bitf.year ;
dt_buf.isBCE= ud.bitf.isBCE;
gc_calculate_wday ();
gc_calculate_yday ();
gc_calculate_mweek ();
gc_calculate_yweek ();
gc_calculate_serial();
return &dt_buf;
}
date_t mkdate(struct dt * sd) {
}
}}}
{{{
#include <stdio.h>
#include <stdlib.h>
#include "date.h"
union date_t {
date_t ival;
struct {
unsigned mday : 5;
unsigned month: 4;
unsigned year :22;
unsigned isBCE: 1;
} bitf;
};
char * wday_name[] = { "Seguinda", "Terca", "Quarta", "Quinta", "Sexta", "Sabado" }
int main(int argc, char *argv[])
{
union date_t ud;
date_t d;
struct dt *sd;
d = date(NULL);
printf("hoje representado no tipo date_t: %ld\n",d);
sd = gcdate(d);
printf("hoje decomposto\t\t\t: %d %2d/%2d/%4d\n",sd->wday,sd->mday,sd->month,sd->year);
ud.bitf.mday = 7;
ud.bitf.month = September;
ud.bitf.year = 1822;
ud.bitf.isBCE = 0;
sd = gcdate(ud.ival);
printf("a idependência ocorreu num(a) %s \n",wday_name[sd->wday]);
//system("PAUSE");
return 0;
}
}}}
! Exercícios
# Conclua o exemplo {{{date.h}}}/{{{date.c}}}; Escreva as funções
** {{{date_t mkdate(struct dt *); /* code struct dt* in a date_t */}}}
** {{{struct dt * gcdate(date_t); /* decode date_t in a struct dt */}}}
** {{{struct dt * diffdate(date_t,date_t); /* interval between dates */}}}
** {{{size_t strfdate(char*, size_t, const char*, const struct dt*);}}}
** {{{ int printf_date(const char *, const struct dt*);}}}
** {{{int scanf_date (const char *, const struct dt*);}}}
# Escreva um programa que teste todas as funções criadas acima.
! Tipos de Dados
Em aulas anteriores dissemos que os TIPOS de DADO podem ser classificados em:
* ''básicos'' ou ''primitivos''
* ''compostos'' ou ''construídos''
! Tipos compostos
* Arranjos (matrizes e vetores)
* Ponteiros
* Definidos pelo usuário
** Estruturas
** Uniões
** Enumerações
** Campos de bits
** {{{typedef}}}s
! Estruturas
[img[img/cap7.struct1.png]]
[img[img/cap7.struct2.png]]
[img[img/cap7.struct3.png]]
[img[img/cap7.struct4.png]]
! Atividade : {{{asciimap}}}
# Crie um projeto C chamado asciimap
# Salve os arquivos abaixo no projeto
{{{
/* asciimap.h
*/
#define LAR_MAX 40
#define ALT_MAX 20
void ler_pontos(char asciimap[ALT_MAX][LAR_MAX]);
void imprimir(char asciimap[ALT_MAX][LAR_MAX]);
}}}
''NOTA'' : Sobre o uso de ARRANJOS em parametros de funções videL [[Matrizes e Parâmetros de Funções]].
{{{
/* asciimap.c
*/
#include "asciimap.h"
void ler_pontos(char asciimap[ALT_MAX][LAR_MAX]) {
char opc[10] = "sim";
while( strcmp(opc,"nao") != 0 ) {
unsigned short x,y;
char c;
printf("Ponto:\n");
printf(" x = "); scanf("%hu",&x);
printf(" y = "); scanf("%hu",&y);
if ( x >= LAR_MAX || y >= ALT_MAX ) {
printf("erro: Max x = %hu e Max y = %hu\n", LAR_MAX -1, ALT_MAX -1);
continue;
}
printf(" c = "); scanf(" %c" ,&c);
asciimap[y][x] = c;
printf("Outro? [sim|nao]\n");
scanf("%s",opc);
}
}
void imprimir(char asciimap[ALT_MAX][LAR_MAX]) {
int x,y;
for( y=0; y < ALT_MAX; y++ ) {
for( x=0; x < LAR_MAX; x++ )
printf("%c",asciimap[y][x]);
printf("\n");
}
}
}}}
{{{
/* asciimap-teste.c
*/
#include "asciimap.h"
main() {
char map[ALT_MAX][LAR_MAX];
memset(map,' ',LAR_MAX * ALT_MAX);
ler_pontos(map);
imprimir(map);
}
}}}
! Atividade 2 : {{{retangulo}}}
# crie um projeto C e salve com o nome de retangulo
# crie os arquivos abaixo no projeto retangulo
{{{
/* retangulo.h
*/
#include "asciimap.h"
struct ponto {
unsigned short x,y;
char c;
};
struct retangulo {
struct ponto ini;
unsigned short dx,dy;
};
#define min(a,b) ((a) < (b) ? (a) : (b))
void desenhar(char asciimap[ALT_MAX][LAR_MAX], struct retangulo ret);
}}}
{{{
/* retangulo.c
*/
#include "retangulo.h"
void desenhar(char asciimap[ALT_MAX][LAR_MAX], struct retangulo ret) {
int x,xf,y,yf;
xf = min(ret.ini.x + ret.dx, LAR_MAX);
for ( x = ret.ini.x ; x < xf; x++ )
asciimap[ret.ini.y][x] = ret.ini.c;
yf = min(ret.ini.y + ret.dy, ALT_MAX);
for ( y = ret.ini.y; y < yf; y++ )
asciimap[y][ret.ini.x] = ret.ini.c;
if ( ret.ini.y + ret.dy <= ALT_MAX )
for ( x = ret.ini.x ; x < xf; x++ )
asciimap[yf-1][x] = ret.ini.c;
if ( ret.ini.x + ret.dx <= LAR_MAX )
for ( y = ret.ini.y ; y < yf; y++ )
asciimap[y][xf-1] = ret.ini.c;
}
}}}
{{{
/* retangulo-teste.c
*/
#include "retangulo.h"
main() {
struct ponto p = {0, 0, '.'};
struct retangulo r = { p, 10, 4 };
struct retangulo r2= { {10,4,'-'}, 10, 10};
char map[ALT_MAX][LAR_MAX];
memset(map,' ', ALT_MAX*LAR_MAX);
desenhar(map,r);
desenhar(map,r2);
imprimir(map);
}
}}}
! Leitura Recomendada
* CCT cap 7
* http://www.di.ufpe.br/~if097/lprog1-p10/sld001.htm
! Exercícios
# Estenda o programa da atividade 2 para incluir o desenho de :
** retas (definida por dois pontos distintos; )
** circulos (definido por um ponto central e um raio );
# Escreva uma função que use as mesmas estruturas da atividade 2 para descobrir se um ponto está dentro de um retângulo.
# Defina uma estrutura que permita representar um triângulo, através das coordenadas dos seus vértices. Em seguida, escreva uma função que leia as coordenadas dos vértices de um triângulo e preencha a estrutura definida cujo endereço lhe é passado como parâmetro. Depois, escreva funções que determinem o perímetro e a área de um triângulo representado pela estrutura definida. Por fim, desenvolva um programa de teste de todas as funções criadas.
# Considere que uma empresa precisa armazenar os seguintes dados de um cliente:
** DADOS
*** Nome completo com no máximo 50 caracteres;
*** renda mensado do cliente;
*** ano de nascimento;
*** possui ou não carro.
**Defina um tipo e uma estrutura para armazenarem estes dados e escreva um programa que leia estes dados armazene-os em uma variável e em seguida os imprima.
# Considerando a mesma estrutura do exercício anterior, escreva um programa que leia os dados de 100 clientes e imprima:
** quantos clientes têm renda mensal acima da média;
** quantos clientes têm carro;
** quantos clientes nasceram entre 1960 (inclusive) e 1980 (exclusive).
# Considere que foi definida a seguinte estrutura:
{{{
typedef struct _frac {
int numerador, denominador;
} FRACAO;
}}}
Escreva um programa em C que calcule as quatro operações (+, -, * e / ) usando frações definidas com estruturas do tipo FRACAO. O programa deve ler duas frações e imprimir o resultado de cada uma das quatro operações.
#displayArea {background-color: #ffccff; }
#mainMenu {border: 1px solid #ffff88; }
#commandPanel {background-color: #008800; }
! arquivo "rpn.c"
{{{
#include "stack.h"
#include <stdlib.h>
#include <ctype.h>
char input[1024];
int main() {
while (1) {
printf("%d: ",stack_size());
scanf("%s",input);
if ( input[0] == '.' ) break; /* termina imediatamente o laço while */
switch ( input[0] ) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
stack_push( atof(input) );
continue;
default:
printf(" ^ invalid input!\n");
continue;
case '+':
stack_push( stack_pop() + stack_pop() );
break;
case '*':
stack_push( stack_pop() * stack_pop() );
break;
}
printf("-----\n");
printf(" = %f\n\n",stack_top());
stack_print();
}
}
}}}
Dado o código abaixo (que pode ser obtido como [[projeto Dev-Cpp neste link|src/list.zip]]), complemente o código do arquivo {{{lista.c}}} escrevendo as funções:
* {{{list_rem()}}}
* {{{list_get()}}}
* {{{list_set()}}}
!! main.c
{{{
/* main.c **/
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
#include "xcpt.h"
int main(int argc, char *argv[])
{
while (1) {
char str[1024];
int pos;
const char * xc;
printf("\nAdicionar\n");
printf(" pos = "); scanf("%d",&pos);
printf(" str = "); gets(str); gets(str);
list_add(str,pos);
/*
TRY(list_add(str,pos));
CATCH(INDEX_OUT_OF_BOUNDS_XCPT,xc)
printf("\npos invalida!\n");
CATCH(LIST_FULL_XCPT,xc)
printf("\nlista cheia!\n");
CATCH(LINE_TOO_LONG_XCPT,xc)
printf("\nstr muito grande!\n");
*/
printf("\nLista\n");
list_print();
}
}
}}}
!! list.h, list.c
{{{
/* list.h, Rev. 1.1
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements a list of strings.
**/
#ifndef LIST_H
#define LIST_H
#define LIST_MAX_SIZE 99
#define LINE_MAX_SIZE 60
#define LIST_FULL_XCPT "list full"
#define LINE_TOO_LONG_XCPT "line too long"
unsigned short list_size(void);
void list_add(const char * str, unsigned short pos);
char * list_rem(unsigned short pos);
void list_set(const char * str, unsigned short pos);
char * list_get(unsigned short pos);
void list_print(void);
#endif
}}}
{{{
/* list.c, Rev. 1.1
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements a list of strings.
**/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "list.h"
#include "xcpt.h"
/** private data */
static char list[LIST_MAX_SIZE][LINE_MAX_SIZE+1];
static unsigned short size = 0;
static char xcpt_cmsg[XCPT_CMSG_MAX_SIZE+1];
/** public functions */
unsigned short list_size(void) {
return size;
}
/*
Add a new element str in the list at a given position pos.
From pos to the end of the list, all existing elements are
shifted right.
Throws:
INDEX_OUT_OF_BOUNDS_XCPT when pos is invalid ( > size +1 )
LIST_FULL_XCPT when the list size equals LIST_MAX_SIZE
LINE_TOO_LONG_XCPT when str is greater than LINE_MAX_SIZE
**/
void list_add(const char * str, unsigned short pos) {
sprintf(xcpt_cmsg,"@%s[%d]\n> list_ins (\"%s\",%d);\n",
__FILE__,__LINE__,str,pos);
if ( pos > size + 1 ) {
THROW(INDEX_OUT_OF_BOUNDS_XCPT,xcpt_cmsg);
return ;
}
if ( size + 1 > LIST_MAX_SIZE ) {
THROW(LIST_FULL_XCPT,xcpt_cmsg);
return ;
}
if ( strlen(str) > LINE_MAX_SIZE ) {
THROW(LINE_TOO_LONG_XCPT,xcpt_cmsg);
}
if ( pos == 0 ) {
strncpy(list[size],str,LINE_MAX_SIZE);
} else {
int i;
for ( i = size ; i >= pos; i-- )
strcpy(list[i],list[i-1]);
strncpy(list[i],str,LINE_MAX_SIZE);
}
size++;
}
char * list_rem(unsigned short pos) {
}
void list_set(const char * str, unsigned short pos) {
}
char * list_get(unsigned short pos) {
}
void list_print(void) {
int i;
for ( i=0; i < size; i++ )
printf("%2d: %s\n",i+1,list[i]);
}
}}}
!! xcpt.h, xcpt.c
{{{
/* xcpt.h, Rev. 1.1
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements an exception handling mechanism inspired in Java.
**/
#ifndef XCPT_H
#define XCPT_H
#define XCPT_NAME_MAX_SIZE 32
#define XCPT_CMSG_MAX_SIZE 1024
#define THROW(e,m) __throw((e),(m))
#define TRY(f) __begin_try();f;__end_try();
#define CATCH(e,m) if(m=__catch(e))
#define NULL_POINTER_XCPT "null pointer"
#define INDEX_OUT_OF_BOUNDS_XCPT "index out of bounds"
#define OVERFLOW_XCPT "overflow"
#define UNDERFLOW_XCPT "underflow"
#define ILLEGAL_ARGUMENT_XCPT "illegal argument"
void __begin_try(void);
void __end_try(void);
const char * __catch(const char *name);
void __throw(const char *name, const char *cmsg);
#endif
}}}
{{{
/* xcpt.c, Rev. 1.1
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements an exception handling mechanism inspired in Java.
**/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "xcpt.h"
static char xcpt_name[XCPT_NAME_MAX_SIZE + 1];
static char xcpt_cmsg[XCPT_CMSG_MAX_SIZE + 1];
static int trying;
/*
Sets try_flag.
**/
void __begin_try(void) {
trying = 1;
}
/*
UnSets try_flag.
**/
void __end_try(void){
trying = 0;
}
/*
From exception name, gets the exception message thown by
__throw(n,m). Once cautch, the exception name is cleared .
**/
const char * __catch(const char * name) {
if ( strcmp(xcpt_name,name) == 0 ) {
xcpt_name[0] = '\0';
return xcpt_cmsg;
}
else
return NULL;
}
/*
Stores an exception contextual message.
When called outside a __begin_try(); ...; __end_try(); pair,
the exception message is also printed to the stderr stream .
**/
void __throw(const char * name,const char * cmsg) {
strncpy(xcpt_name,name,XCPT_NAME_MAX_SIZE);
strncpy(xcpt_cmsg,cmsg,XCPT_CMSG_MAX_SIZE);
if ( !trying )
fprintf(stderr,"exception: %s: %s\n",xcpt_name,xcpt_cmsg);
}
}}}
! arquivo "stack.h"
{{{
#ifndef STACK_H
#define STACK_H
#define STACK_MAX_SIZE 10
extern int stack_error;
int stack_size (void);
double stack_top (void);
void stack_push (double);
double stack_pop (void);
void stack_print (void);
#endif
}}}
! arquivo "stack.c"
{{{
/** stack.c */
#include "stack.h"
#include <stdio.h>
/* dados privados */
static double stack[STACK_MAX_SIZE];
static int ti = -1; /* guarda o índice do elemento
que é o atual topo da pilha */
/* funções públicas */
int stack_error;
/* stack_size()
retorna tamanho atual da pilha
**/
int stack_size(void) {
return ti + 1;
}
/* stack_top()
retorna elemento no topo da pilha
**/
double stack_top(void) {
if ( ti < 0 ) {
stack_error = -1;
return 0;
}
stack_error = 0;
return stack[ti];
}
/* stack_push(d)
coloca elemento d no topo da pilha
**/
void stack_push(double d) {
if ( ti >= STACK_MAX_SIZE ) {
stack_error = -1;
return;
}
stack_error = 0;
stack[++ti] = d;
}
/* stack_pop()
retira e retorna o elemento no topo da pilha
**/
double stack_pop(void) {
if ( ti < 0 ) {
stack_error = -1;
return 0;
}
stack_error = 0;
return stack[ti--];
}
/* stack_print()
imprime toda a pilha
**/
void stack_print(void) {
int i;
for( i=0 ; i <= ti ; i++ )
printf("%i: %f\n",i,stack[i]);
}
}}}
! Funções
Em C, um programa é uma coleção de FUNÇÕES. Uma //função// é um bloco de código que recebe um nome e que tem possivelmente PARÂMETROS. A partir do nome, o bloco de código que forma a função pode ser chamado. CHAMAR uma função significa iniciar a execução de um bloco de código. Caso a função possua parâmetros, durante a CHAMADA dela devem ser indicados ARGUMENTOS que são valores ou variáveis que irão corresponder aos parâmetros da função. Ao final da execução, uma função pode ainda retornar um valor para o código que fez a chamada da função.
! Definição de Função: Forma Geral
Uma função deve ser definida conforme o esquema abaixo:
{{{
ESPEC-DECLARAÇÃO ID( DECL-ID-1, ..., DECL-ID-n ) {
CORPO_FUNÇÃO
}
}}}
{{{ID}}} define o nome da função. A lista de declarações {{{DECL-ID-1, ..., DECL-ID-n}}} é dita LISTA de PARÂMETROS da função. Cada {{{ID-i}}} consiste em uma variável com escopo local na função e que irá receber, como valor inicial, o valor passado como ARGUMENTO durante a chamada da função.
Se pensarmos no ID de uma função como uma VARIÁVEL GLOBAL, os {{{ESPEC-DECLARAÇÃO}}} definem que características tem este ID:
* O tipo de dados ( {{{void}}}, {{{int}}}, {{{char *}}}, ... )
* Classe de armazenamento ( {{{static}}} ou {{{extern}}} )
* O tipo de acesso ( {{{const}}} ou {{{volatile}}} )
O {{{CORPO_FUNÇÃO}}} consiste em DECLARAÇÕES de VARIÁVEIS com escopo LOCAL seguidas de COMANDOS. Caso o tipo de dados constante nos {{{ESPEC-DECLARAÇÃO}}} seja diferente de {{{void}}}, deve haver ao menos um comando {{{return ...;}}} no {{{CORPO_FUNÇÃO}}}.
! Definição de Função: Formato Antigo
Por questões de compatibilidade, uma função pode ainda ser definida seguindo o formato originalmente proposto pelos projetistas da linguagem. Neste formato original, o que muda é a forma de se especificar os parâmetros da função:
{{{
ESPEC-DECLARAÇÃO ID( ID-1,...,ID-n )
DECL-ID-1;
...;
DECL-ID-n;
{
CORPO_FUNÇÃO
}
}}}
! Declaração de Funções: Protótipos
O ideal é que toda função, antes de ser usada, deve ser declarada. Caso a função encontra-se DEFINIDA no mesmo arquivo e em uma posição antes de seu uso, então a própria DEFINIÇÃO da função serve como DECLARAÇÃO da função. Caso contrário, a DECLARAÇÃO da função dever ser feita através de PROTÓTIPOS. Um protótipo é como se fosse um CABEÇALHO para a função, ou seja, o ID da função os ESPEC do tipo retornado pelo função e os ESPEC dos tipos de cada parâmetro da função:
{{{
ESPEC-DECLARAÇÃO ID( ESPEC-DECL-1, ..., ESPEC-DECL-n );
}}}
Em uma situação onde uma função {{{f}}} esteja sendo usada sem ter sido antes declarada, então implicitamente o compilador declarada a função como sendo:
{{{
int f();
}}}
! Um função f() é diferente de f(void) !
Um função declarada como
{{{
int f();
}}}
é diferente de uma função declarada como
{{{
int f(void);
}}}
No primeiro caso, o compilador não sabe se a função pode ou não receber argumentos durante a sua chamada. Quer dizer, é perfeitamente válido fazer:
{{{
int x = f(3.14);
int y = f(2.7, 4);
int z = f();
}}}
No segundo caso, o compilador é informado explicitamente que a função não deve receber nenhumar argumento. Assim, as duas primeiras linhas do código acima gerariam uma mensagem de erro e apenas a última seria considerada como válida.
! Lista de Parâmetros Variável
Quando se quer especificar uma função que possui uma lista de parâmetros variável em número e tipo, deve-se terminar a declaração dos parâmetros utilizando três pontos {{{...}}}
Por exemplo:
{{{
void f(int a, char * b, ... );
}}}
Qualquer função que use um número variável de parâmetros deve ter ao menos um deles explicitamente declarado.
!! va_arg(), va_start() e va_end()
[img[img/cap18.va_arg.png]]
[img[img/cap18.va_arg_exemplo.png]]
! Chamada de Função
Chamar uma função significa iniciar a execução de seu corpo de código. Caso a função tenha sido declarada com PARAMETROS, durante a chamada deve ser passados ARGUMENTOS que correspondam em número e tipo com os PARAMETROS da função.
PARAMETROS são variáveis locais à função que irão receber como valores iniciais os valores dos ARGUMENTOS utilizados na CHAMADA da função.
[img[img/cap6.chamada.png]]
''OBS.'': Em C, as chamadas de função são feitas por VALOR. No entanto, o conceitos de chamada por referência pode ser simulado em C através do uso de apontadores.
Exemplo: CHAMADA por VALOR
{{{
unsigned modulo(int x) {
x = x < 0 ? - x : x ;
return x;
}
int main () {
int a = - 2, ma = modulo(a);
printf("| %d | = %d\n", a, ma);
}
}}}
Ao executar o programa acima, vc. irá perceber que o valor da variável {{{a}}} não é modificado pela função módulo. Ou seja, a variável {{{a}}} e usada como ARGUMENTO em uma CHAMADA por VALOR de {{{modulo()}}}.
Exemplo: simulando CHAMADA por REFERÊNCIA
{{{
unsigned modulo(int * x) {
*x = *x < 0 ? - *x : *x ;
return *x;
}
int main () {
int a = - 2, ma = a;
modulo(&ma);
printf("| %d | = %d\n", a, ma);
}
}}}
!! Chamadas de Funções com ARRANJOS
O ID de vetores, matrizes e strings são conceitualmente apontadores para o primeiro elemento do arranjo. Assim, ao se usar o nome de vetores, matrizes ou strings em uma chamada de função está-se fazendo uma CHAMADA por REFERÊNCIA. Em outras palavras, vetores, matrizes ou strings quando passados como argumentos de funções e manipulados no interior dessas funções têm os seus valores modificados ao término da função (vide também: [[Matrizes e Parâmetros de Funções]] ).
Para evitar que modificações acidentais ocorram com vetores, matrizes e strings passados como argumentos de funções deve-se declará-los utilizando o qualificador {{{const}}}.
''Exemplos'':
{{{
/* *str não deve ser modificado no interior de strlen
*/
int strlen(const char str[]) {
int i;
/* str[0] = 'a'; - qualquer tentativa de modificar o conteúdo da string apontada
por str irá gerar uma mensagem de erro ! */
for(i =0; *str; i++, str++);
return i;
}
/* *str1 deve ser modificada no interior de strlen
já, *str2 não
*/
int strcpy(char * str1, const char * str2) {
int i = 0;
/* str2[0] = 'a'; - qualquer tentativa de modificar o conteúdo da string apontada
por str2 irá gerar uma mensagem de erro ! */
do
str1[i] = str2[i];
while ( str2[i++] );
return i - 1;
}
}}}
! Leituras Recomendadas
** CCT cap 6
** K&R
! Exercícios
''Obs.'': Nos exercícios abaixo, escolha cinco e para estes mostre como as funções ficam quando definidas utilizando o formato antigo de definição de funções.
# Em C, qual a diferença entre DECLARAÇÃO e DEFINIÇÃO de funções?
# O que significam:
## passagem de argumentos por valor?
## passagem de argumentos por referência?
# Escreva uma função que recebe um número inteiro n>0 e devolve o número de dígitos de n e o primeiro dígito de n.
# Escreva uma função que recebe como parâmetro um inteiro positivo ano e devolve 1 se ano for bissexto, 0 em caso contrário. (Um ano é bissexto se (ano % 4 = = 0 && (ano % 100 != 0 || ano % 400 = = 0)).)
# Escreva uma função que tem como parâmetros de entrada e saída três números inteiros, dia, mes e ano, representando uma data, e modifica esses inteiros de forma que eles representem o dia seguinte.
# Escreva um programa que leia um inteiro positivo n e uma seqüência de n datas e imprime, para cada data, o dia seguinte.
# Escreva uma função de cabeçalho {{{int divide (int *m, int *n, int d)}}} que recebe três inteiros positivos como parâmetros e devolve 1 se d divide pelo menos um entre *m e *n, 0 caso contrário. Fora isso, se d divide *m, divide *m por d, e o mesmo para o *n.
# Escreva um programa que lê dois inteiros positivos m e n e calcula, usando a função acima, o mínimo múltiplo comum entre m e n, ou seja, mmc(m,n).
# Escreva uma função com protótipo {{{void somabit (int b1, int b2, int *vaium, int *soma);}}} que recebe três bits (inteiros entre 0 e 1) b1, b2 e *vaium e devolve um bit soma representando a soma dos três e o novo um bit "vai-um" em *vaium.
# Escreva um programa que leia dois números em binário e calcula um número em binário que é a soma dos dois números dados. Utilize a função acima.
# Escreva uma função com o protótipo {{{void converte (char ch, int *tipo, char *valor);}}} que recebe um caractere ch e devolve em *tipo 0, se o caractere for um número inteiro, 1 se for uma letra (maiúscula ou minúscula) e 2 caso contrário; e além disso, no caso de ser uma letra, converte para maiúscula, senão devolve ch inalterado.
# Escreva um programa que leia uma seqüência de n caracteres e imprima a seqüência convertida para maiúscula, eliminando os caracteres que não forem letras ou números.
# Escreva uma função que lê, linha a linha, uma matriz real Amxn
# Escreva uma função que imprime uma matriz real Amxn
# Escreva uma função que calcula a soma dos elementos da linha i de uma matriz real Amxn.
# Escreva uma função que calcula o produto dos elementos da coluna j de uma matriz real Amxn.
# Escreva uma função que troca o conteúdo de duas variáveis.
# Escreva uma função que recebe dois inteiros, i e j, uma matriz real Amxne troca linha i pela linha j. Utilize a função do item anterior.
# Um conjunto pode ser representado por um vetor da seguinte forma: V[0] é o tamanho do conjunto; V[1], V[2], etc. são os elementos do conjunto (sem repetições).
## Faça uma função chamada intersecção que dados dois conjuntos de números inteiros A e B, constrói um terceiro conjunto C que é a intersecção de A e B. Lembre-se de que em C[0] a sua função deve colocar o tamanho da intersecção.
## Faça um programa que lê um inteiro n > 1 e uma seqüência de n conjuntos de números inteiros (cada um com no máximo 100 elementos) e constrói e imprime um vetor INTER que representa a intersecção dos n conjuntos.
*** Por exemplo, se n=3 e os conjuntos são {1, 2, 4, 9}, {2, 4, 7, 8, 9} e {5, 4, 9}, a entrada será:
{{{
3 O valor de n
4 V[0] = tamanho do primeiro conjunto
1 2 4 9 V[1] V[2] V[3] V[4]
5 V[0] = tamanho do segundo conjunto
2 4 7 8 9 V[1] V[2] V[3] V[4] V[5]
3 V[0] = tamanho do terceiro conjunto
5 4 9 V[1] V[2] V[3]
}}}
*** E o vetor INTER construído será
{{{
INTER[0] = 2 tamanho do conjunto
INTER[1] = 4 INTER[2] = 9 conjunto intersecção
}}}
*** NOTE que não é preciso ler todos os conjuntos de uma só vez. Você pode ler os dois primeiros conjuntos e calcular a primeira intersecção. Depois, leia o próximo conjunto e calcule uma nova intesecção entre esse conjunto lido e o conjunto da intersecção anterior, e assim por diante. Use obrigatoriamente a função do item anterior, mesmo que você não a tenha feito.
! A função main()
!! O que {{{main()}}} devolve?
De acordo com o padrão ANSI, a função {{{main()}}} devolve um inteiro para o processo chamador, que é, geralmente, o sistema operacional.
Devolver um valor em {{{main()}}} é equivalente a chamar {{{exit()}}} com o mesmo valor.
Se {{{main()}}} não devolve explicitamente um valor, o valor passado para o processo chamador é tecnicamente indefinido.
Na prática, a maioria dos compiladores C devolve {{{0}}}, mas não conte sempre com isso!
Pode-se também declarar {{{main()}}} como {{{void}}}.
Alguns compiladores geram uma ADVERTENCIA, se a função não é declarada como {{{void}}} e também não devolve um valor.
!! {{{argc}}} e {{{argv}}} - argumentos para {{{main()}}}
[img[img/cap6.main_args.png]]
{{{
int main ( int argc, char * argv[] ) {
for( ; argc -- ; )
printf("arg[%d] = %s\n", argc, argv[argc]);
}
}}}
[img[img/cap6.main_args2.png]]
! Recursão
Em C, como virtualmente em todo linguagem de programação, funções podem chamar a si mesmas, direta ou indiretamente.
Uma função é dita //recursiva// se em seu corpo a uma chamada (direta ou indireta) para si mesma.
Recursão é o processo de definir algo em termos de si mesmo e é, algumas vezes, chamado de definição circular.
Exemplos:
{{{
#include <stdlib.h>
#include <string.h>
char * gnu(int n) {
static char buf[1024];
if (n == 0)
strcpy(buf,"GNU");
else {
gnu(n-1);
strcat(buf," Not Unix");
}
return buf;
}
char * gnu2(int n) {
static char buf[1024];
if (n == 0)
return "GNU";
else {
char aux[1024];
strcpy(aux,gnu2(n-1));
sprintf(buf,"(%s %s)",aux,"Not Unix");
}
return buf;
}
int main(int argc, char * argv[]) {
printf("%s\n", gnu(atoi(argv[1])) );
printf("%s\n", gnu2(atoi(argv[1])) );
}
}}}
''OBSERVAÇÕES'':
* Quando uma função chama a si mesma, novos parâmetros e variáveis locais - quando estas não são {{{static}}} - são alocados na pilha e o código da função é executado com essas novas variáveis.
* No caso de variáveis locais {{{static}}}, todas as chamadas recursivas compartilham a mesma variável !
* Quando cada chamada recursiva retorna, as variáveis locais (não {{{static}}}) e os parâmetros são removidos da pilha e a execução recomeça do ponto da chamada à função dentro da função.
* Ao escrever funções recursivas, você deve ter um comando {{{if}}} em algum lugar para forçar a função a retornar sem que a chamada recursiva seja executada mais uma vez !
! Atividade 1 - Torres de HANOI
Em 1883, o matematico francesEdouard Lucas inventou o famoso quebra-cabeça das Torres de Hanoi, tambem conhecido por Torres de Brahma e contado em forma de lenda:
@@color(red):
<<<
"//No grande templo de Brahma em Benares, numa bandeja de metal sob a cúpula que marca o centro do mundo, três agulhas de diamante servem de pilar a sessenta e quatro discos de ouro puro. @@ Incansavelmente, os sacerdotes transferem os discos, um de cada vez, de agulha para agulha, obedecendo sempre à lei imutável de Brahma: Nenhum disco se podera sobrepor a um menor@@.
[img[http://members.tripod.com/vismath4/kappraff1/f2.jpg]]
No inıcio do mundo todos os sessenta e quatro discos de ouro, foram dispostos na primeira das três agulhas, constituindo a Torre de Brahma. No momento em que o menor dos discos for colocado de tal modo que se forme uma vez mais a Torre de Brahma numa agulha diferente da inicial, tanto a torre como o templo serão transformados em pó e o ribombar de um trovão assinalara o fim do mundo.//"
[http://www2.mat.ua.pt/rosalia/cadeiras/ADA/THpaper.pdf]
<<<
@@
Escreva um programa em C, que simule o trabalho dos sacerdotes conforme descrito acima! Na lenda, os sacerdotes movem 64 discos. No seu programa, trabalhe com n discos, onde n é um número informado pelo usuário. ''Dica'': usando recursão, o seu programa ficará bastante compacto.
{{{
int main(int c, char * v[]) {
/* assuma que atoi(v[1]) é o número n de discos a ser movido de um pilar para outro */
}
}}}
! Atividade 2 - Combinações
Quantos times de futebol diferentes podem ser feitos com uma turma de 26 alunos?! No segundo grau, você DEVE ter aprendido que esta questão pode ser resolvida utilizando a fórmula mágica de COMBINAÇÕES:
[img[http://upload.wikimedia.org/math/c/c/5/cc5911f0f66d76c8d9c83cbc51c3c0e9.png]]
Sendo n=26 e k=11
{{{
26! / [11! (26 - 11)!] = 26*25*24*23*22*21*20*19*18*17*16 / 11*10*9*8*7*6*5*4*3*2*1
= 308403583488000/ 39916800
= 7726160
}}}
Bom, se você for escrever um programa em C para calcular combinações de n tomados k a k e utilizar a definição acima você poderá ter sérios problemas de overflow! Repare que o número {{{308403583488000}}} quando escrito em binário fica:
{{{
10 0011 000 0111 1101 1100 1110 0000 1010 1001 0000 0000 0000
}}}
Isto indica que são necessário 7 bytes no mínimo para armazená-lo na memória do computador. Por outro lado, se observarmos o resultado final {{{7726160}}} que em binário é
{{{
111 0101 1110 0100 0101 0000
}}}
vemos que ele ocupa apenas 3 bytes! Em resumo, usando inteiros de 4bytes podemos armazenar o resultado final mas não poderemos armazenar resultados intermediários como os acima apresentados! O que fazer?
Vamos pensar um pouco: queremos formar times de 11 num universo de 26 alunos. Do ponto de vista de um aluno particular, os times a serem formados podem ser divididos em duas classes: os times nos quais o aluno participa e os times nos quais ele não participa. Os times nos quais um particular aluno participa são em número de COMB( 25, 10 ). Ou seja, o referido aluno mais dez dentre os 25 restantes. Já os times nos quais o aluno não participa são em número de COMB( 25, 11 ). Ou seja, o aluno está excluído e são formados times de 11 dentre os 25 restantes.
Este raciocínio pode ser repetido recursivamente agora para COMB( 25, 10 ) e COMB( 25, 11 ). O resultado final é o seguinte padrão recursivo:
[img[http://upload.wikimedia.org/math/1/d/b/1db9fb1fe567bfe79a61703a71657b52.png]]
Agora, partindo da fórmula acima podemos escrever um programa recursivo que calcular combinações sem os problemas de overflow indicados acima quando usamos a definição tradicional de combinações. Tal programa poderia usar a função abaixo:
{{{
int comb(int n, int k) {
if ( k > n )
return 0;
if ( k == 0 || k == n )
return 1;
else
return comb(n-1,k-1) + comb(n-1,k);
}
}}}
Resolvemos um problema mas também criamos um outro: o de tempo de execução. Faça um teste. Tente calcular {{{comb(36,11)}}} usando a função acima. Observe quanto tempo vai demorar para obter o resultado!
O que fazer então?! Na raiz do problema está o fato de que a função recursiva proposta faz inumeras vezes o mesmo trabalho. Por exemplo: COMB(36,11) depende de COMB(35,10) e COMB(35,11). Já COMB(35,11) depende de COMB(34,10) e COMB(34, 11); e, COMB(35,10) depende de COMB(34,9) e COMB(34,10). Observe que esta última combinação - COMB(34,10) - aparece em dois ramos distintos de recursão e por isso irá ser calculado duas vezes!
Uma solução para evitar este trabalho todo é criar uma tabela para registrar cálculos já feitos:
{{{
int comb(int n, int k) {
static int tab[50][50];
if ( k > n )
return 0;
if ( tab[n][k] == 0 ) {
if ( k == 0 || k == n )
tab[n][k] = 1;
else
tab[n][k] = comb(n-1,k-1) + comb(n-1,k);
}
return tab[n][k];
}
}}}
Teste as funções apresentadas acima e verifique se realmente as idéias discutidas fazem sentido.
! Leitura Recomendada
* CCT capítulo 6
! Exercícios
# Complete a atividade 1
# Na atividade 1, se cada disco pode ser movido de um lugar para outro em 1 nanosegundo (= 10^^-9^^ seg.), quanto tempo os monges irão levar para mover os 64 disco de uma torre para a outra?
# Complete a atividade 2
# Na atividade 2, qual os maiores {{{k}}} e {{{n}}} tais que {{{comb(n,k)}}} não estoure a representação baseada em {{{int}}} de 4 bytes?
# Defina uma função recursiva para determinar o maior divisor comum entre dois números naturais x e y, baseando-se nas regras abaixo. Em seguida, napresente uma versão iterativa do algoritmo capaz de realizar a mesma tarefa.
** mdc(x,y) = x, se x = y
** mdc(x,y) = mdc(y,x), se x < y
** mdc(x.y) = mdc(x-y,y), se x > y
# Escreva uma função recursiva {{{void fibo(int n);}}} que gere os {{{n}}} primeiros termos da série de Fibonacci.
# Faça de conta que na linguagem C não existem operadores para adição, subtração, multiplicação e nem divisão. Imagine que existam apenas os operadores de incremento {{{++N}}} e decremento {{{--N}}}. Usando como base apenas estes dois operadores- {{{++}}} e {{{--}}} (quer dizer, você não deve usar os operadores {{{+}}}, {{{-}}}, {{{*}}} e {{{/}}}) -, defina funções recursivas para:
** {{{int soma(int x,int y);}}} - retorna soma x mais y;
** {{{int subt(int x,int y);}}} - retorna subtração x menos y;
** {{{int mult(int x,int y);}}} - retorna multiplicação x vezes y;
** {{{int divi(int x,int y);}}} - retorna divisão inteira x dividido por y;
# Defina uma rotina recursiva para, dado um natural n, imprimi-lo em base binária.
! Tópicos
* As Origens de C
* C - Características
** Nível Médio
** Estruturada
** Para programadores
** Programação de sistemas
* Estrutura Geral de um programa em C
* Edição, compilação e Link Edição
* C versus C++
! As Origens de C
''Ken Thompson'' e ''Dennis Ritchie'' (da esquerda pra direita), os criadores das linguagens ''B'' e ''C'', respectivamente:
[img[http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Ken_n_dennis.jpg/300px-Ken_n_dennis.jpg]]
Para detalhes, leia:
* [[D. M. Ritchie; O Desenvolvimento da Linguagem C | http://cm.bell-labs.com/cm/cs/who/dmr/chistPT.html]]
* http://www.caloni.com.br/blog/archives/historia-da-linguagem-c-parte-1
* http://www.caloni.com.br/blog/archives/historia-da-linguagem-c-parte-2
!! Evolução das Linguagem de Programação
* Ref:
** [[History of programming languages | http://faramir.ugent.be/dungeon/histlang.html]]
** [[Computer Languages History | http://www.levenez.com/lang/]]
[img[http://faramir.ugent.be/dungeon/histtalen2.gif]]
!! Padronização ANSI
* Ref: Jones, Derek M. (2008) "[[The New C Standard: An Economic and Cultural Commentary|http://www.knosof.co.uk/cbook/cbook.html]]."
[img[img/c-history.png]]
! C - Características
* Nível Médio
* Estruturada
* Para programadores
* Programação de sistemas
!! Linguagem de Nível Médio
[img[img/cap1.tab1_1.png]]
!! Linguagem Estruturada
[img[img/cap1.cle.png]]
[img[img/cap1.cle2.png]]
!! Linguagem para Programadores
[img[img/cap1.clp1.png]]
!! Linguagem para Programação de Sistemas
[img[img/cap1.ps1.png]]
! Estrutura geral de um programa
!! Palavras Reservadas
[img[img/cap1.tab1_2.png]]
!! Funções
[img[img/cap1.main.png]]
[img[img/cap1.fig1_1.png]]
!! Exemplo
[img[img/media-c.png]]
! Edição, compilação e Link Edição
[img[img/cap1.ecl.png]]
[img[http://www.caloni.com.br/blog/wp-content/uploads/cpp-o-code.gif]]
!! IDE - Integrated Developmente Environments
** ''[[DevCpp|http://www.bloodshed.net/devcpp.html]]''
** ''[[Code::Blocks | http://www.codeblocks.org/]]'' + ''[[gcc|http://gcc.gnu.org/]]''
** ''[[jGRASP|http://www.jgrasp.org/]]'' + ''[[gcc|http://gcc.gnu.org/]]''
** ''[[TurboC|http://dn.codegear.com/article/20841]]''
!! Termos
** Compilação Separada
** Biblioteca Padrão ANSI
[img[img/cap1.termos.png]]
! C versus C++
[img[img/cap1.ccpp.png]]
!Leitura Recomendada
* CCT capítulo 1
* K&R capítulo 1
* D. Ritche, [[O Desenvolvimento da Linguagem C*|http://cm.bell-labs.com/cm/cs/who/dmr/chistPT.html]].
* [[Histórico das Linguagens de Programação | http://www.levenez.com/lang/ ]]
* [[Wikipedia: Ling. C | http://pt.wikipedia.org/wiki/Linguagem_de_programa%C3%A7%C3%A3o_C]]
!Exercícios
# A linguagem C é considerada uma linguagem de nível médio. Explique o que isto significa e quais as implicações em termos práticos.
# Programas escritos em C são ditos possuir alto grau de portabilidade. Explique o que isto significa e quais as implicações em termos práticos.
# A linguagem C, a exemplo de Pascal é dito ser uma linguagem estruturada. Pesquise e descreva as principais diferenças entre a programação estruturada em Pascal e a programação estruturada em C.
# Faça um resumo esquemáticos das datas e principais acontecimentos relatados no artigo [[O Desenvolvimento da Linguagem C*|http://cm.bell-labs.com/cm/cs/who/dmr/chistPT.html]] de D. Ritchie.
# A linguagem C é uma linguagem compacta com apenas 32 palavras reservadas. Pesquise e liste as palavras reservadas de C. Classifique-as em:
** especificadores de tipos
** controle de fluxo
** especificadores de classe de memória
** outros
# Modifique o programa {{{media.c}}} para exibir o nome do vetores {{{P}}} e {{{T}}} durante a leitura dos dados. Dica: redefina a função {{{ler}}} para aceitar como parametro o nome do vetor sendo lido, além do próprio vetor. De posse do nome do vetor sendo lido, exiba este nome antes da leitura de cada posição.
/***
|''Name:''|LegacyStrikeThroughPlugin|
|''Description:''|Support for legacy (pre 2.1) strike through formatting|
|''Version:''|1.0.2|
|''Date:''|Jul 21, 2006|
|''Source:''|http://www.tiddlywiki.com/#LegacyStrikeThroughPlugin|
|''Author:''|MartinBudden (mjbudden (at) gmail (dot) com)|
|''License:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.0|
***/
//{{{
// Ensure that the LegacyStrikeThrough Plugin is only installed once.
if(!version.extensions.LegacyStrikeThroughPlugin) {
version.extensions.LegacyStrikeThroughPlugin = {installed:true};
config.formatters.push(
{
name: "legacyStrikeByChar",
match: "==",
termRegExp: /(==)/mg,
element: "strike",
handler: config.formatterHelpers.createElementAndWikify
});
} //# end of "install only once"
//}}}
! Cursos de C em outras IES
* [[UFPE - IF097 - Linguagens de Programação I | http://www.di.ufpe.br/~if097/]]
* [[UFMG - DEE - Curso de Linguagem C | http://www.mtm.ufsc.br/~azeredo/cursoC/]]
* [[UFRJ - NCE - Computação para Informática | http://equipe.nce.ufrj.br/adriano/c/home.htm]]
* [[UNESP - Curso de Linguagem C | http://www.dee.feis.unesp.br/graduacao/disciplinas/langc/modulo_linguagemc/index.html ]]
* [[Estácio de Sá - Linguagem C | http://www.ericolisboa.eng.br/cursos/estacio/lingc/index.htm]]
! Referências
* D. Ritchie, C Reference Manual: http://cm.bell-labs.com/cm/cs/who/dmr/cman.pdf
* C Reference Card 2.2: http://www.digilife.be/quickreferences/QRC/C%20Reference%20Card%20(ANSI)%202.2.pdf
* Trott, G. (2005) [[ANSI STANDARD C - FUNCTION DEFINITIONS FOR THE CURIOUS, THE DESPERATE, THE FRANTIC AND THE SUICIDAL (Version 1.2.5)| http://members.aol.com/wantondeb/]]
* [[The GNU C Library|http://www.gnu.org/software/libc/manual/html_node/index.html]]
* Huss, E. (1997) [[The C Library Reference Guide | http://www.acm.uiuc.edu/webmonkeys/book/c_guide/]]
* [[ C Standard Library | http://www.utas.edu.au/infosys/info/documentation/C/CStdLib.html]]
! Softwares
!! IDE + Compilers
* DEV C++ : http://www.bloodshed.net/devcpp.html
* Turbo C : http://dn.codegear.com/article/20841
* TC Lite : http://www.tclite.fsnet.co.uk/
!! Apenas IDE
* Code::Blocks : http://www.codeblocks.org/
* jGrasp : http://www.jgrasp.org/
* eclipse CDT : http://www.eclipse.org/cdt/
!! Compiladores
* gnu gcc : http://gcc.gnu.org/
* djgpp (gcc,g++ port to windows) : http://www.delorie.com/djgpp/
* tcc : http://fabrice.bellard.free.fr/tcc/
!! Interpretadores
* Ch - C/C++ Interpreter : http://www.softintegration.com/
* CInt : http://root.cern.ch/twiki/bin/view/ROOT/CINT
! Outros
* [[What Every Computer Scientist Should Know About Floating-Point Arithmetic|http://docs.sun.com/source/806-3568/ncg_goldberg.html]]
* C puzzles
** http://www.gowrikumar.com/c/
* http://www.geocities.com/cantinhodoc/c.html
* sites interessantes: http://www.geocities.com/chicorapchan/disciplinas/s_prog/index.htm#Sites%20Interessantes
* criptografia : http://www.cristhom.com.br/press/crip_ass_sim.html
* numeros complexos : http://pt.wikipedia.org/wiki/N%C3%BAmero_complexo
* ascii-art
** http://www.c-sharpcorner.com/UploadFile/dheenu27/ImageToASCIIconverter03022007164455PM/ImageToASCIIconverter.aspx
[[Apresentação]]
[[Cronograma]]
[[Freqüência]]
[[Bibliografia]]
[[Links]]
GettingStarted
[img[img/matrizes-funcoes.png]]
[img[img/matrizes-funcoes2.png]]
[img[img/matrizes-funcoes3.png]]
[img[img/logomdp.jpg][http://www.deinf.ufma.br/~maratona/]]
[img[img/onlinejudgelogo.png][http://icpcres.ecs.baylor.edu/onlinejudge/]]
<<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>
Last Updated: 2008-06-23
Copyright © Luciano
! Objetivo
Na aula de HOJE iremos dar início ao estudo dos @@OPERADORES@@ da linguagem C. Os OPERADORES, em conjunto com @@CONSTANTES@@ e @@VARIÁVEIS@@, são os constituintes básicos de @@EXPRESSÕES@@. Serão detalhados os operadores utilizadoes em expressões:
* de atribuição
* aritmética
* e lógica
! Operadores
Em C, podemos classificar os OPERADORES em cinco grande categorias:
* Atribuições
* Aritméticos
* Lógicos e Relacionais
* ~Bit-a-Bit
* Especiais
! Atribuições
Forma geral:
{{{
VARIÁVEL = EXPRESSÃO;
}}}
[img[img/cap2.tab2_3.png]]
Atribuições múltiplas:
{{{
VAR1 = VAR2 = .... = VARn = EXPRESSÃO;
}}}
C Reduzido: (para todo operador ''op'' binário)
{{{
VAR = VAR op EXPRESSÃO;
}}}
é equivalente a:
{{{
VAR OP= EXPRESSÃO;
}}}
! Operadores Aritméticos
[img[img/cap2.tab2_4.png]]
[img[img/cap2.prec_op_aritm.png]]
''Obs.'':
* operadores com o mesmo nível de PRECEDÊNCIA são avaliados pelo compilador da ESQUERDA PARA a DIREITA
!! Exemplo 1
* Em :
{{{
int a = 3;
int b = 2;
int c = a + -b * 3 / 2 + a % 3 * 4;
}}}
Quanto vale a VAR {{{c}}}?
Resposta:
* operadores de maior precedência são avaliados primeiro
* operadores de mesma precedência são associados da esquerda para a direita
* então, a expressão acima seria avaliada assim:
{{{
int c = ((a + (((-b)*3)/2)) + ((a%3)*4));
}}}
!! Exemplo 2
Quanto valem {{{i}}} e {{{j}}} abaixo, após cada atribuição???
{{{
int i , j = 2;
i = j++;
i = -- j;
i = --j++;
}}}
Resposta:
{{{
i = j++; /* i == 2, j == 3; primeiro armazena o valor de j em i, depois incrementa j */
i = -- j; /* i == 2, j == 2; primeiro decrementa j, depois armazena o valor de j em i */
i = --j++; /* expressão inválida */
}}}
A última expressão é inválida pois incremento e decremento DEVEM sempre operar sobre variáveis e não sobre expressões!
!! Exemplo 3
* Em :
{{{
int c = 3;
c = c-- + c;
}}}
Quanto vale a VAR {{{c}}}?
Resposta:
* ''Atenção'': O uso de operadores de incremento ({{{++}}}) e decremento ({{{--}}}) em EXPRESSÕES frequentemente é AMBÍGUO! @@Evite-o SEMPRE!!!@@
* Assim, dependendo da ordem em que o compilador avalia as sub-expressões entre o operador {{{+}}} podemos ter resultados diversos para o valor da variável {{{c}}}!
!! Exemplo 4
''Veja esse exemplo retirado de um livro'':
[img[img/or_ex5.4_1.png]]
Quando eu rodo o exemplo acima no meu computador o resultado é {{{result == 8}}} !!!
Já o livro diz:
*** Avaliando da ''esquerda para a direita'':
[img[img/or_ex5.4_2.png]]
*** Avaliando da ''direita para a esquerda'':
[img[img/or_ex5.4_3.png]]
! Operadores Lógicos e Relacionais
[img[img/cap2.op_relog.png]]
[img[img/cap2.tab2_5.png]]
[img[img/cap2.prec_op_relog.png]]
!! Atividade 1: operadores lógicos {{{implica}}} e {{{ouexcl}}}
Em C, os operadores {{{&&}}}, {{{||}}} e {{{!}}} correspondem respectivamente aos conectivos E, OU e NÃO da lógica Booleana. Na lógica booleana, além destes conectivos, existem vários outros. Por exemplo:
* IMPLICAÇÃO
{{{
A B A -> B
-----------------
0 0 1
0 1 1
1 0 0
1 1 1
}}}
* OU EXCLUSIVO
{{{
A B A OUEXCL B
-----------------
0 0 0
0 1 1
1 0 1
1 1 0
}}}
Nesta atividade, implemente estes dois operadores como duas funções em C!
{{{
int implica(int a, int b) {
...
}
int ouexcl(int a, int b) {
...
}
}}}
Após criar as funções acima, teste-as por meio da função {{{main}}} abaixo:
{{{
int main() {
printf("teste implica:\n"
printf("%i -> %i = %i\n", 1, 7, implica(1,7));
printf("%i -> %i = %i\n", 3, 0, implica(3,0));
printf("%i -> %i = %i\n", 0, 1, implica(0,1));
printf("%i -> %i = %i\n", 0, 0, implica(0,0));
printf("teste ouexcl:\n"
printf("%i xor %i = %i\n", 3, 4, ouexcl(3,4));
printf("%i xor %i = %i\n", 1, 0, ouexcl(1,0));
printf("%i xor %i = %i\n", 0, 5, ouexcl(0,5));
printf("%i xor %i = %i\n", 0, 0, ouexcl(0,0));
}
}}}
! Leituras Recomendadas
* CCT capítulo 2
* K&R capítulos 2
* http://pt.wikipedia.org/wiki/Operadores_em_C_e_C%2B%2B
* http://www.mspc.eng.br/info/cpp_oper_10.shtml
! Exercícios
# Diga a ordem de cálculo e o resultado das expressões constantes abaixo:
## x = 5 * 4 / 6 + 7 ;
## x = 5 * 4.0 / 6 + 7 ;
## x = 5 * 4 % 6 + 7 ;
## x = ((4 / 2) + (3.0 * 5)) ;
## x = 3 + 2*4%3/2 – 1 ;
## x = 3 >= 2 && ! 2 || 0 ;
## x = 2 && 0 || 1 ;
# Escreva um programa que imprima a tabela verdade da funcao ou exclusivo.
# Escreva um programa que leia um ângulo em segundos e imprima quantos graus, minutos e segundos há neste ângulo.
# Escreva um programa que leia um tempo em segundos e imprima quantas horas, minutos e segundos há neste tempo.
# Escreva um programa que leia um comprimento em centímetros e imprima quantos metros, decímetros e centímetros há neste comprimento.
! Objetivos
Em C, @@OPERADORES@@ e @@EXPRESSÕES@@ podem ser classificados em cinco grande categorias:
* Atribuições
* Aritméticos
* Lógicos e Relacionais
* ~Bit-a-Bit
* Especiais
Na última aula, disticutimos as três primeiras categorias acima. HOJE, iremos dar prosseguimento ao estudo apresentado os OPERADORES e EXPRESSÕES:
* @@~Bit-a-Bit@@
* @@Especiais@@
Ao final, concluiremos o assunto mostrando um quadro que resume e compara os OPERADORES da linguagem C por ordem de precedência e associatividade.
! Manipulação de Bits
OPERADORES e EXPRESSÕES de manipulação de bits ( bit-a-bit ) referem-se a testar, atribuir ou deslocar os bits efetivos em um byte ou palavra que correspondem aos tipos básicos {{{char}}}, {{{int}}} e variantes.
''OBS''.:
* Operações bit-a-bit não podem ser feitas sobre {{{float}}}, {{{double}}}, {{{long double}}}, {{{void}}} ou outros tipos mais complexos.
[img[img/cap2.tab2_6.png]]
''Significados'':
* Os operadores {{{&}}}, {{{|}}} e {{{~}}} têm a mesma tabela verdade que {{{&&}}}, {{{||}}} e {{{!}}} (respectivamente), com a diferença que operam sobre os bits individuais da representação de dois números (ou apenas um, no caso de {{{~}}}) e não sobre expressões numéricas.
* o operador {{{^}}} tem a mesma tabela verdade que a função {{{xor()}}} discutida na aula passada (novamente operando sobre bits individuais e não sobre expressões numéricas).
* o operador {{{>>}}} desloca os bits de um número k casas para à esquerda fazendo com que os k bits mais à esquerda se percam e os k bits mais à direita sejam '0'
* o operador {{{<<}}} desloca os bits de um número k casas para à direita fazendo com que os k bits mais à direita se percam e os k bits mais à esquerda sejam '0'
''Exemplo 1'' ({{{<<}}} e {{{>>}}}):
Considere:
{{{
unsigned int x = 7;
}}}
Se pudéssemos olhar a representação do valor {{{7}}} (decimal) 'dentro' da variável {{{x}}}, veríamos os seguinte padrão de bits: {{{x = 0...00000111}}} ( a quantidade total de bits depende de quantos bytes são utilizados para armazenar um {{{unsigned int}}}, quantidade que depende da máquina alvo e compilador ).
A EXPRESSÃO abaixo (deslocamento à esquerda):
{{{
x = x << 2;
}}}
faz com que o padrão de bits representando o valor inicial {{{7}}} se transforme em {{{ x = 0...00011100}}}. Quer dizer, os bits, todos foram deslocados para a esquerda dois bits! Assim, o valor agora reresentado na variável {{{x}}} é 28 !
De maneira geral, se uma variável tem o seguinte padrão de bits:
* x = | b~~n-1~~ | b~~n-2~~ | ... | b~~2~~ | b~~1~~ | b~~0~~ |
* onde:
** a variável é representada por n bits
** cada um dos b~~i~~ (para 0 ≤ i ≤ n-1 ) denota um bit com valor '0' ou '1'
então:
* {{{x << k}}}, resulta em:
** x = | b~~n-k-1~~ | b~~n-k-2~~ | ... | b~~2~~ | b~~1~~ | b~~0~~ | 0 | 0 | .. | 0 |0 | 0 |
** onde a seq. final de '0's contém k '0's
* {{{x >> k}}}, resulta em:
** x = | 0 | 0 | ... | 0 | 0 | 0 | b~~n-1~~ | b~~n-2~~ | ... | b~~k-1~~ | b~~k~~ |
** onde a seq. inicial de '0's contém k '0's
''Exemplo 2'' ({{{~}}}):
Continuando o exemplo anterior, tem-se {{{ x = 0...00011100}}}.
A EXPRESSÃO abaixo ( complemento de 1 ):
{{{
x = ~ x;
}}}
tem o seguinte efeito na representação de x em binário: {{{ x = 1...11100011 }}}. Ou seja, os bits que são '0' passam a ser '1', os que são '1' tornam-se '0'.
''Exemplo 3'' ({{{|}}}):
Continuando o exemplo anterior, tem-se {{{ x = 1...11100011}}}.
A EXPRESSÃO abaixo ( OR ):
{{{
x = x | 8 ;
}}}
transforma x em : {{{ x = 1...11101011 }}}. Quer dizer, muda o quarto bit (da direita para a esquerda) de '0' para '1'. Isto acontece por que:
{{{
x = 1...11100011
4 = 0...00001000
--------------
x | 4 = 1...11101011 /* OU bit a bit */
}}}
* {{{|}}} é frequentemente utilizado para LIGAR bits particulares
''Exemplo 4'' ({{{&}}}):
Continuando o exemplo anterior, tem-se {{{ x = 1...11101011}}}.
A EXPRESSÃO abaixo ( AND ):
{{{
x = x & 0xf...f7 ;
}}}
transforma x em : {{{ x = 1...11100011 }}}. Quer dizer, muda o quarto bit (da direita para a esquerda) de '1' para '0'. Isto acontece por que:
{{{
x = 1...11101011
0xf...f7 = 1...11110111
--------------
x | 0xf...f7 = 1...11100011 /* AND bit a bit */
}}}
* {{{&}}} é frequentemente utilizado para DESLIGAR bits particulares
''Aplicações Típicas'':
* rotinas de SO, drivers de dispositivos
* criptografia
* compactação de dados
!! Atividade 1
Tendo em vista os significados de {{{|}}} e {{{&}}} que são, respectivamente, similares aos de {{{||}}} e {{{&&}}}, descreva - através de um exemplo - o significado de {{{^}}} que é similar à função {{{xor()}}} descrita na última aula.
!! Atividade 2
Uma tabela binária é uma tabela (matriz linhas x colunas ) onde cada célula armazena um dentre dois valores possíveis. Por exemplo, a [[Freqüência]] deste curso é em essência uma tabela binária uma vez que cada célula só pode conter ou '0' (presente) ou '2' (ausente).
Uma maneira simples de representar uma tabela binária é através da seguinte estrutura:
{{{
char tabela1[40][10];
}}}
Nesta representação são gastos : 40*10 = 400 bytes ( {{{sizeof char = 1 byte }}} ).
Uma maneira mais eficiente (do ponto de vista da quantidade de memória utilizada) seria utilizar um mapa de bits para armazenar a tabela binária. Tal mapa de bits é uma sequencia de bits mantidas pelos operadores bit a bit.
Para a tabela acima de 40 linhas por 10 colunas poderíamos ter a seguinte declaração:
{{{
char tabela2[ (40*10) / 8 ];
}}}
Nesta representação são gastos : (40*10)/8 = 50 bytes. A idéia aqui é, ao invés de usar um {{{char}}} (1 byte) para armazenar 0 ou 1, usar um bit individual dentro de um {{{char}}}. Vejamos como isto pode ser feito.
''Atribuindo valor a uma determinada célula (linha,coluna)''
Na primeira representação acima, uma dada célula pode ter seu valor modificado da seguinte maneira:
{{{
tabela1 [3][5] = 0; /* aluno 3 esteve presente */
tabela1 [7][5] = 2; /* aluno 7 faltou */
}}}
Na segunda representação acima, o mesmo processo tem de ser simulado através de uma função:
{{{
void set(unsigned x, unsigned y, int val) {
unsigned pos = ( x* 10 + y ) / 8;
unsigned des = ( x* 10 + y ) % 8;
if (val)
tabela2[pos] |= ( 1 << des );
else
tabela2[pos] &= ~( 1 << des );
}
}}}
''Recuperado o valor em uma determinada célula (linha,coluna)''
A consultar do valor em uma dada célula é feita de maneira direta para a primeira representação (utilizado índices linha e coluna). Já para a segunda representação devemos fazer uma função de consulta.
{{{
/* retorna 0 se na pos x,y está armazenado 0
retona 1 se na pos x,y está armazenado 1
**/
int get(unsigned x, unsigned y) {
...
}
}}}
Como exercício, escreva a função de consulta {{{get()}}}.
! Operadores Especiais
* Operador Condicional {{{ ? : }}}
* Operador {{{sizeof}}}
* Operadores de Conversão de Tipo ou //Casting// {{{(tipo)}}}
* Operador Vírgula {{{,}}}
* Operadores {{{()}}} e {{{[]}}}
Serão vistos em mais detalhes em aulas futuras:
* Operadores de ponteiros {{{*}}} e {{{&}}}
* Operadores de estruturas {{{.}}} e {{{->}}}
!! Operador Condicional {{{? :}}}
''Uso''
{{{
EXP1 ? EXP2 : EXP3;
}}}
''Significado''
EXP1 é avaliada ... Se ela for verdadeira, então EXP2 é avaliada e se torna o valor da expressão como um todo. ... Se EXP1 for falsa, então EXP3 é avaliada e se torna o valor da expressão como um todo.
Por exemplo, o comando condicional da função {{{set()}}} da atividade 2 poderia ser reescrito assim:
{{{
tabela2[ pos ] = val ?
tabela2[pos] | (1 << des) :
tabela2[pos] & ~ (1 << des) ;
}}}
!! b) Operador {{{sizeof}}}
''Uso''
{{{
sizeof ID-VAR;
sizeof (ESP-TIPO);
}}}
''Significado''
{{{sizeof}}} é um operador unário em tempo de compilação que retorna o tamanho, em BYTES, de uma variável ou de um especificador de tipo de dados, este último escrito entre parênteses.
Por exemplo, para tornar o código da função {{{set()}}} da atividade 2 mais PORTÁVEL, podemos fazer:
{{{
char tabela2 [ (40*10) / ((sizeof char)*8) + 1 ];
void set(unsigned x, unsigned y, int val) {
unsigned pos = ( x* 10 + y ) / ((sizeof char)*8);
unsigned des = ( x* 10 + y ) % ((sizeof char)*8);
...
}
}}}
!! c) Conversão Explícita de tipos (casting)
''Uso''
{{{
(ESPECIFICADOR-DE-TIPO) EXPRESSÃO;
}}}
''Significado''
Força - explicitamente - uma EXPRESSÃO a ser de um determinado tipo dado por {{{ESPECIFICADOR-DE-TIPO}}}.
Por exemplo, para deixar claro que em:
{{{
tabela2 |= ( 1 << des);
}}}
o valor {{{1}}} se trata de um {{{char}}} ( 1 byte ) podemos fazer de forma explícita:
{{{
tabela2 |= ( ((char) 1) << des );
}}}
Além de conversões explícitas, o compilador realiza algumas conversões implícitas ...
''Conversões Automáticas''
[img[img/cap2.conv_tipo.png]]
Exemplo:
[img[img/cap2.fig2_3.png]]
!! d) Operador vígula {{{,}}}
''Uso''
{{{
EXP1, EXP2;
}}}
''Significado''
O operador vígula é usado para encadear diversas expressões. O lado esquerdo (EXP1) é sempre avaliado como {{{void}}}. Assim, a expressão do lado direito (EXP2) torna-se o valor de toda a expressão separada por vírgula.
Por exemplo:
{{{
int x,y;
x = ( y = 3, y+1 );
}}}
primeiro o valor 3 é atribuído a {{{y}}} e, em seguida, o valor 4 é atribuído a {{{x}}}. Os parênteses são necessários porque o operador vírgula tem a menor precedência de todos os operadores de C.
Um outro exemplo é:
{{{
int i,x;
for ( i = 0 , x = 1; i < 10; i++ , x+=2) {
...
}
}}}
!! e) Operadores () e []
* Parênteses {{{()}}} são operadores que aumentam a precedência das operações dentro deles.
* Colchetes {{{[]}}} realizam indexação de vetores e matrizes.
! Quadro Geral de Operadores em C
A tabela 2.8 lista a precedência de todos os operadores de C. Note que todos os operadores, exceto os operadores unários e o {{{?}}}, associam da esquerda para a direita. Os operadores unários ( {{{*}}}, {{{!}}} e {{{~}}}) e o ternário {{{?}}} associam da direita para a esquerda.
[img[img/cap2.tab2_8.png]]
!! Ordem de Avaliação
O padrão C ANSI (C89) não estipula que as subexpressões de uma expressão devam ser avaliadas e uma ordem específica. Assim, seu código nunca deve contar com a ordem em que as subexpressões são avaliadas. Por exemplo, a expressão:
{{{
x = f() + g();
}}}
não garante que {{{f()}}} será chamada antes de {{{g()}}}!
! Leituras Recomendadas
* CCT capítulo 2
* K&R capítulos 2
* http://pt.wikipedia.org/wiki/Operadores_em_C_e_C%2B%2B
* http://www.mspc.eng.br/info/cpp_oper_10.shtml
! Exercícios
# Realize por completo a atividade 1
# Realize por completo a atividade 2, escrevendo a função {{{get()}}} e testando as funções {{{set()}}} e {{{get()}}} em um programa que lê do usário posições x e y, liga os bits nestas posições e ao final imprime a tabela completa.
# Observe o padrão abaixo:
** ( (0000 0001)~~2~~ {{{<<}}} 1 ) → (0000 0010)~~2~~ = 2
** ( (0000 0010)~~2~~ {{{<<}}} 1 ) → (0000 0100)~~2~~ = 4
** ( (0000 0100)~~2~~ {{{<<}}} 1 ) → (0000 1000)~~2~~ = 8
** ( (0000 1000)~~2~~ {{{<<}}} 1 ) → (0001 0000)~~2~~ = 16
** ( (0001 0000)~~2~~ {{{<<}}} 1 ) → (0010 0000)~~2~~ = 32
** ...
## desse padrão, o que se pode concluir com relação à operação de deslocamento à esquerda?
## e com relação à operação de deslocamento à direita?
## em termos numéricos o que significa x {{{<<}}} k ? Quer dizer, se x vale 5 quanto irá valer x {{{<<}}} k ?
## em termos numéricos o que significa x {{{>>}}} k ? Quer dizer, se x vale 35 quanto irá valer x {{{>>}}} k ?
# Para o programa abaixo, descreva como ele funciona e qual a saída gerada após a sua execução.
{{{
#include <stdio.h>
int g(float a, float b) {
static float f;
return f += a > b ? a / b : b / a , (int) f;
}
int main() {
printf("%i\n", g(7,2));
printf("%i\n", g(2,3));
}
}}}
<!--{{{-->
<div id='header' class='header'>
<div class='headerShadow'>
<span class='searchBar' macro='search'></span>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu'>
<span refresh='content' tiddler='MainMenu'></span>
<span id='noticeBoard' refresh='content' tiddler='NoticeBoard'></span>
</div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='MochaSideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<div id='contentFooter' refresh='content' tiddler='contentFooter'></div>
<!--}}}-->
TiddlyWiki can be extended by InstallingPlugins that implement new [[Macros]], [[Themes]], [[Tweaks]] or other features. The easiest way of InstallingPlugins is to use ImportTiddlers. Like other features that need to modify TiddlyWiki files, it only works when TiddlyWiki is loaded from a {{{file://}}} URL.
DaveGifford oversees an extensive catalogue of available plugins at [[TiddlyVault|http://tiddlyvault.tiddlyspot.com/]].
Some of the leading plugin sites from independent developers are here tagged as <<tag systemServer>> which also makes them available in ImportTiddlers.
ChrisKlimas has written [[The Macrocodex|http://gimcrackd.com/etc/src/codex/]], some superb documentation on writing plugins and macros for TiddlyWiki.
! Conceito
Um PONTEIRO ou APONTADOR é uma variável usada para armazenar um endereço de memória.
Normalmente, o endereço armazenado em um PONTEIRO é a posição de uma outra variável na memória. Se uma variável contém o endereço e uma outra, então a primeira variável é dita //apontar// para a segunda.
[img[img/cap5.fig5_1.png]]
! Declaração
De maneira geral, uma variável ponteiro de nome {{{ID}}} é declarada assim:
{{{
ESPECIFICADORES * ID = INICIALIZADOR;
}}}
onde, o {{{= INICIALIZADOR}}} é opcional (como em toda declaração de variável).
! Operadores de Ponteiros
Existem dois operadores especiais para ponteiros: o {{{*}}} e o {{{&}}}.
!! Operador &
Um operador unário que devolve o endereço na memória do seu operando.
{{{
int m;
int * p;
p = &m; /* p recebe o endereço onde se localiza a var. m */
...
}}}
!! Operador *
É o complemento de {{{&}}}. Quer dizer, devolve a variável localizada no endereço armazenado em um apontador.
{{{
p = &m;
m = 3;
printf("%p", p); /* imprime o endereço de m */
printf("%d", *p); /* imprime 3 que é o conteúdo de m */
...
}}}
! Ponteiros e Arranjos
Há uma estreita relação entre PONTEIROS e ARRANJOS (vetores, matrizes e strings).
O nome de um ARRANJO (vetor, matriz ou string) é sempre um PONTEIRO para o primeiro elemento do ARRANJO.
{{{
char str[80], *pstr;
pstr = str; /* pstr aponta para str[0] */
}}}
Assim, a décima posição de um ARRANJO (vetor, matriz ou string) pode ser acessada de duas maneiras:
{{{
pstr = str; /* pstr aponta para str[0] */
printf("%c", str[9] ); /* imprime o 10o elemento de str */
printf("%c",*(pstr + 9)); /* imprime o 10o elemento de str */
}}}
! Aritmética de Ponteiros
Existem apenas duas operações aritméticas que podem ser usadas com ponteiros: adição e subtração.
Cada vez que um ponteiro é incrementado, ele aponta para a posição de memória do próximo elementodo seu tipo base.
Cada vez que um ponteiro é decrementado, ele aponta para a posição de memória do elemento anterior.
[img[img/cap5.fig5_2.png]]
! Aplicações
O correto entendimento e uso de ponteiros é crítico para uma programação bem-sucedida em C. Há pelo menos três razões para isto:
* ponteiros fornecem os meios pelos quais as funções podem modificar seus argumentos
* formam a base para a //alocação dinâmica// (variáveis no //heap//)
* aumenta a eficiência de certas rotinas
De agora em diante, até o final do curso, iremos explorar em variados graus de detalhes o conceito básico de ponteiros.
! Atividade 1
Aplicando os conhecimentos adquiridos na [[última aula|Vetores, matrizes e strings]] e nesta, iremos agora implementar uma primeira versão de uma //lista de strings//.
Dado o código abaixo (que pode ser obtido como [[projeto Dev-Cpp neste link|src/list.zip]]), complemente o código do arquivo {{{lista.c}}} escrevendo as funções:
* {{{list_rem()}}}
* {{{list_get()}}}
* {{{list_set()}}}
!! main.c
{{{
/* main.c **/
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
#include "xcpt.h"
int main(int argc, char *argv[])
{
while (1) {
char str[1024];
int pos;
const char * xc;
printf("\nAdicionar\n");
printf(" pos = "); scanf("%d",&pos);
printf(" str = "); gets(str); gets(str);
list_add(str,pos);
/*
TRY(list_add(str,pos));
CATCH(INDEX_OUT_OF_BOUNDS_XCPT,xc)
printf("\npos invalida!\n");
CATCH(LIST_FULL_XCPT,xc)
printf("\nlista cheia!\n");
CATCH(LINE_TOO_LONG_XCPT,xc)
printf("\nstr muito grande!\n");
*/
printf("\nLista\n");
list_print();
}
}
}}}
!! list.h, list.c
{{{
/* list.h, Rev. 1.1
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements a list of strings.
**/
#ifndef LIST_H
#define LIST_H
#define LIST_MAX_SIZE 99
#define LINE_MAX_SIZE 60
#define LIST_FULL_XCPT "list full"
#define LINE_TOO_LONG_XCPT "line too long"
unsigned short list_size(void);
void list_add(const char * str, unsigned short pos);
char * list_rem(unsigned short pos);
void list_set(const char * str, unsigned short pos);
char * list_get(unsigned short pos);
void list_print(void);
#endif
}}}
{{{
/* list.c, Rev. 1.1
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements a list of strings.
**/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "list.h"
#include "xcpt.h"
/** private data */
static char list[LIST_MAX_SIZE][LINE_MAX_SIZE+1];
static unsigned short size = 0;
static char xcpt_cmsg[XCPT_CMSG_MAX_SIZE+1];
/** public functions */
unsigned short list_size(void) {
return size;
}
/*
Add a new element str in the list at a given position pos.
From pos to the end of the list, all existing elements are
shifted right.
Throws:
INDEX_OUT_OF_BOUNDS_XCPT when pos is invalid ( > size +1 )
LIST_FULL_XCPT when the list size equals LIST_MAX_SIZE
LINE_TOO_LONG_XCPT when str is greater than LINE_MAX_SIZE
**/
void list_add(const char * str, unsigned short pos) {
sprintf(xcpt_cmsg,"@%s[%d]\n> list_ins (\"%s\",%d);\n",
__FILE__,__LINE__,str,pos);
if ( pos > size + 1 ) {
THROW(INDEX_OUT_OF_BOUNDS_XCPT,xcpt_cmsg);
return ;
}
if ( size + 1 > LIST_MAX_SIZE ) {
THROW(LIST_FULL_XCPT,xcpt_cmsg);
return ;
}
if ( strlen(str) > LINE_MAX_SIZE ) {
THROW(LINE_TOO_LONG_XCPT,xcpt_cmsg);
}
if ( pos == 0 ) {
strncpy(list[size],str,LINE_MAX_SIZE);
} else {
int i;
for ( i = size ; i >= pos; i-- )
strcpy(list[i],list[i-1]);
strncpy(list[i],str,LINE_MAX_SIZE);
}
size++;
}
char * list_rem(unsigned short pos) {
}
void list_set(const char * str, unsigned short pos) {
}
char * list_get(unsigned short pos) {
}
void list_print(void) {
int i;
for ( i=0; i < size; i++ )
printf("%2d: %s\n",i+1,list[i]);
}
}}}
!! xcpt.h, xcpt.c
{{{
/* xcpt.h, Rev. 1.1
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements an exception handling mechanism inspired in Java.
**/
#ifndef XCPT_H
#define XCPT_H
#define XCPT_NAME_MAX_SIZE 32
#define XCPT_CMSG_MAX_SIZE 1024
#define THROW(e,m) __throw((e),(m))
#define TRY(f) __begin_try();f;__end_try();
#define CATCH(e,m) if(m=__catch(e))
#define NULL_POINTER_XCPT "null pointer"
#define INDEX_OUT_OF_BOUNDS_XCPT "index out of bounds"
#define OVERFLOW_XCPT "overflow"
#define UNDERFLOW_XCPT "underflow"
#define ILLEGAL_ARGUMENT_XCPT "illegal argument"
void __begin_try(void);
void __end_try(void);
const char * __catch(const char *name);
void __throw(const char *name, const char *cmsg);
#endif
}}}
{{{
/* xcpt.c, Rev. 1.1
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements an exception handling mechanism inspired in Java.
**/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "xcpt.h"
static char xcpt_name[XCPT_NAME_MAX_SIZE + 1];
static char xcpt_cmsg[XCPT_CMSG_MAX_SIZE + 1];
static int trying;
/*
Sets try_flag.
**/
void __begin_try(void) {
trying = 1;
}
/*
UnSets try_flag.
**/
void __end_try(void){
trying = 0;
}
/*
From exception name, gets the exception message thown by
__throw(n,m). Once cautch, the exception name is cleared .
**/
const char * __catch(const char * name) {
if ( strcmp(xcpt_name,name) == 0 ) {
xcpt_name[0] = '\0';
return xcpt_cmsg;
}
else
return NULL;
}
/*
Stores an exception contextual message.
When called outside a __begin_try(); ...; __end_try(); pair,
the exception message is also printed to the stderr stream .
**/
void __throw(const char * name,const char * cmsg) {
strncpy(xcpt_name,name,XCPT_NAME_MAX_SIZE);
strncpy(xcpt_cmsg,cmsg,XCPT_CMSG_MAX_SIZE);
if ( !trying )
fprintf(stderr,"exception: %s: %s\n",xcpt_name,xcpt_cmsg);
}
}}}
! Leitura recomendada
* CCT Cap 5
! Exercícios
# Termine a atividade 1 acima, escrevendo as funções:
** {{{list_rem()}}}
** {{{list_get()}}}
** {{{list_set()}}}
* código fonte : [[seno.c | src/seno.c]]
[img[img/jgrasp-exp-fat.png]]
[img[img/jgrasp-seno.png]]
[img[img/jgrasp-main-seno.png]]
! Leitura Recomendada
* [[CCT-cap10]]
! Introdução
Um programa em C é transformado em código objeto em duas etapas: uma de PRE-PROCESSAMENTO e a outra de COMPILAÇÃO propriamente dita. Na primeira etapa, as DIRETIVAS de PRE-PROCESSAMENTO são convertidas em código C; na segunda etapa, o código C resultante é compilado.
Abaixo iremos estudar o PRE-PROCESSADOR de C e suas DIRETIVAS. Ao longo da explicação utilizaremos como exemplo os arquivos de programa {{{main.c, list.c, list.h, xcpt.c e xcpt.h}}} discutidos ao final da aula [[Ponteiros]].
[img[img/preproc.png]]
! #include
[img[img/preproc-include.png]]
!! Exemplo
{{{
/* main.c **/
#include <stdio.h> /* arquivos de cabeçalho padrão */
#include <stdlib.h>
#include "list.h" /* arquivos de cabeçalho do projeto */
#include "xcpt.h"
int main(int argc, char *argv[])
{
...
}
}}}
! #define
[img[img/preproc-define.png]]
<<<
[img[img/preproc-define+2.png]]
<<<
<<<
[img[img/preproc-define+1.png]]
<<<
[img[img/preproc-define-macro.png]]
!! Exemplo
{{{
/* xcpt.h, Rev. 1.1
(c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
Implements an exception handling mechanism inspired in Java.
**/
#ifndef XCPT_H
#define XCPT_H
#define XCPT_NAME_MAX_SIZE 32
#define XCPT_CMSG_MAX_SIZE 1024
#define THROW(e,m) __throw((e),(m))
#define TRY(f) __begin_try();f;__end_try();
#define CATCH(e,m) if(m=__catch(e))
#define NULL_POINTER_XCPT "null pointer"
#define INDEX_OUT_OF_BOUNDS_XCPT "index out of bounds"
#define OVERFLOW_XCPT "overflow"
#define UNDERFLOW_XCPT "underflow"
#define ILLEGAL_ARGUMENT_XCPT "illegal argument"
void __begin_try(void);
void __end_try(void);
const char * __catch(const char *name);
void __throw(const char *name, const char *cmsg);
#endif
}}}
! #if, #else, #elif e #endif
[img[img/preproc-if.png]]
<<<
[img[img/preproc-if-exemplo.png]]
<<<
[img[img/preproc-elif.png]]
!! Exemplo-1
[img[img/preproc-elif-exemplo.png]]
!! Exemplo-2
{{{
/** date.h
Author: Luciano R. Coutinho, 2007.
lrc@deinf.ufma.br
*/
#ifndef DATE_H
#define DATE_H
#include <limits.h>
/*
* A type for storing dates in the range:
* from Jan 1st , year 2^22 BCE
* to Dec 31th, year 2^22
*/
#if ( UINT_MAX < 0xffffffff )
typedef long date_t;
#else
typedef int date_t;
#endif
...
}}}
! #ifdef
[img[img/preproc-ifdef.png]]
!! Exemplo
Vide inicio dos exemplos anteriores. Eles começam assim:
{{{
#ifndef FILENAME_H
#define FILENAME_H
...
#endif
}}}
! #undef
[img[img/preproc-undef.png]]
! #line
[img[img/preproc-line.png]]
! Macros pré-definidas
[img[img/preproc-predef.png]]
!! Exemplo
Veja um exemplo de uso de {{{__LINE__}}} e {{{__FILE__}}} no trecho de programa abaixo que foi apresentado na aula [[Ponteiros]]:
{{{
/*
Add a new element str in the list at a given position pos.
From pos to the end of the list, all existing elements are
shifted right.
Throws:
INDEX_OUT_OF_BOUNDS_XCPT when pos is invalid ( > size +1 )
LIST_FULL_XCPT when the list size equals LIST_MAX_SIZE
LINE_TOO_LONG_XCPT when str is greater than LINE_MAX_SIZE
**/
void list_add(const char * str, unsigned short pos) {
sprintf(xcpt_cmsg,"@%s[%d]\n> list_ins (\"%s\",%d);\n",
__FILE__,__LINE__,str,pos);
if ( pos > size + 1 ) {
THROW(INDEX_OUT_OF_BOUNDS_XCPT,xcpt_cmsg);
return ;
}
...
}
}}}
! {{{#pragma}}}
[img[img/preproc-pragma.png]]
<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>
Prof. ''Luciano R. Coutinho''
email:lrc@deinf.ufma.br
[img[img/cabecalho2.jpg][http://www.deinf.ufma.br]]
.: CP 5593.6, 2008.1 -- Linguagem de Programação
/***
|''Name:''|SparklinePlugin|
|''Description:''|Sparklines macro|
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};
//--
//-- Sparklines
//--
config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
var data = [];
var min = 0;
var max = 0;
var v;
for(var t=0; t<params.length; t++) {
v = parseInt(params[t]);
if(v < min)
min = v;
if(v > max)
max = v;
data.push(v);
}
if(data.length < 1)
return;
var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
box.title = data.join(",");
var w = box.offsetWidth;
var h = box.offsetHeight;
box.style.paddingRight = (data.length * 2 - w) + "px";
box.style.position = "relative";
for(var d=0; d<data.length; d++) {
var tick = document.createElement("img");
tick.border = 0;
tick.className = "sparktick";
tick.style.position = "absolute";
tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
tick.style.left = d*2 + "px";
tick.style.width = "2px";
v = Math.floor(((data[d] - min)/(max-min)) * h);
tick.style.top = (h-v) + "px";
tick.style.height = v + "px";
box.appendChild(tick);
}
};
}
//}}}
/*{{{*/
/*Mocha TiddlyWiki Theme*/
/*Version 1.0*/
/*Design and CSS originally by Anthonyy, ported to TiddlyWiki by Saq Imtiaz.*/
/*}}}*/
/*{{{*/
#contentWrapper{
margin: 0 3.4em;
font-family: Lucida Grande, Tahoma, Arial, Helvetica, sans-serif; /* Lucida Grande for the Macs, Tahoma for the PCs */
font-size: 11px;
line-height: 1.6em;
color: #666;
}
.header {
background: #fff;
padding-top: 10px;
clear: both;
border-bottom: 4px solid #948979;
}
.headerShadow { padding: 2.6em 0em 0.5em 0em; }
.siteTitle {
font-family: 'Trebuchet MS' sans-serif;
font-weight: bold;
font-size: 32px;
color: #CC6633;
margin-bottom: 30px;
background-color: #FFF;
}
.siteTitle a{color:#CC6633; border-bottom:1px dotted #cc6633;}
.siteSubtitle {
font-size: 1.0em;
display: block;
margin: .5em 3em; color: #999999;
}
#mainMenu {
position:relative;
float:left;
margin-bottom:1em;
display:inline;
text-align:left;
padding: 2em 0.5em 0.5em 0em;
width:13em;
font-size:1em;
}
#sidebar{
position:relative;
float:right;
margin-bottom:1em;
padding-top:2em;
display:inline;
}
#displayArea {
margin: 0em 17em 0em 15em;
}
.tagClear {clear:none;}
#contentFooter {background:#575352; color:#BFB6B3; clear: both; padding: 0.5em 1em;}
#contentFooter a {
color: #BFB6B3;
border-bottom: 1px dotted #BFB6B3;
}
#contentFooter a:hover {
color: #FFFFFF;
background-color:#575352;
}
a,#sidebarOptions .sliderPanel a{
color:#CC6714;
text-decoration: none;
}
a:hover,#sidebarOptions .sliderPanel a:hover {
color:#CC6714;
background-color: #F5F5F5;
}
.viewer .button, .editorFooter .button{
color: #666;
border: 1px solid #CC6714;
}
.viewer .button:hover,
.editorFooter .button:hover{
color: #fff;
background: #CC6714;
border-color: #CC6714;
}
.viewer .button:active, .viewer .highlight,.editorFooter .button:active, .editorFooter .highlight{color:#fff; background:#575352;border-color:#575352;}
#mainMenu a {
display: block;
padding: 5px;
border-bottom: 1px solid #CCC;
}
#mainMenu a:link, #navlist a:visited {
color:#CC6714;
text-decoration: none;
}
#mainMenu a:hover {
background: #000000 url(arrow.gif) 96% 50% no-repeat;
background-color: #F5F5F5;
color:#CC6714;
}
#mainMenu a:hover, #mainMenu a:active, #mainMenu .highlight, #mainMenu .marked {
background: #000000 url(arrow.gif) 96% 50% no-repeat;
background-color: #F5F5F5;
color:#CC6714;
}
#mainMenu span {position:relative;}
#mainMenu br {display:none;}
#sidebarOptions a {
color:#999;
text-decoration: none;
}
#sidebarOptions a:hover {
color:#4F4B45;
background-color: #F5F5F5;border:1px solid #fff;
}
#sidebarOptions {line-height:1.4em;}
.tiddler {
padding-bottom: 40px;
border-bottom: 1px solid #DDDDDD;
}
.title {color:#CC6633;}
.subtitle, .subtitle a { color: #999999; font-size: 1.0em;margin:0.2em;}
.shadow .title{color:#948979;}
.selected .toolbar a {color:#999999;}
.selected .toolbar a:hover {color:#4F4B45; background:transparent;border:1px solid #fff;}
.toolbar .button:hover, .toolbar .highlight, .toolbar .marked, .toolbar a.button:active{color:#4F4B45; background:transparent;border:1px solid #fff;}
.listLink,#sidebarTabs .tabContents {line-height:1.5em;}
.listTitle {color:#888;}
#sidebarTabs .tabContents {background:#fff;}
#sidebarTabs .tabContents .tiddlyLink, #sidebarTabs .tabContents .button{color:#999;}
#sidebarTabs .tabContents .tiddlyLink:hover,#sidebarTabs .tabContents .button:hover{color:#4F4B45;background:#fff}
#sidebarTabs .tabContents .button:hover, #sidebarTabs .tabContents .highlight, #sidebarTabs .tabContents .marked, #sidebarTabs .tabContents a.button:active{color:#4F4B45;background:#fff}
.tabSelected{color:#fff; background:#948979;}
.tabUnselected {
background: #ccc;
}
.tabSelected, .tabSelected:hover {
color: #fff;
background: #948979;
border: solid 1px #948979;
padding-bottom:1px;
}
.tabUnselected {
color: #999;
background: #eee;
border: solid 1px #ccc;
padding-bottom:1px;
}
#sidebarTabs .tabUnselected { border-bottom: none;padding-bottom:3px;}
#sidebarTabs .tabSelected{padding-bottom:3px;}
#sidebarTabs .tabUnselected:hover { border-bottom: none;padding-bottom:3px;color:#4F4B45}
#sidebarOptions .sliderPanel {
background: #fff; border:none;
font-size: .9em;
}
#sidebarOptions .sliderPanel a {font-weight:normal;}
#sidebarOptions .sliderPanel input {border:1px solid #999;}
.viewer blockquote {
border-left: 3px solid #948979;
}
.viewer table {
border: 2px solid [[ColorPalette::TertiaryDark]];
}
.viewer th, thead td {
background: #948979;
border: 1px solid #948979;
color: #fff;
}
.viewer pre {
border: 1px solid #948979;
background: #f5f5f5;
}
.viewer code {
color: #2F2A29;
}
.viewer hr {
border-top: dashed 1px #948979;
}
.editor input {
border: 1px solid #948979;
}
.editor textarea {
border: 1px solid #948979;
}
.popup {
background: #948979;
border: 1px solid #948979;
}
.popup li.disabled {
color: #000;
}
.popup li a, .popup li a:visited {
color: #eee;
border: none;
}
.popup li a:hover {
background: #575352;
color: #fff;
border: none;
}
.tagging, .tagged {
border: 1px solid #eee;
background-color: #F7F7F7;
}
.selected .tagging, .selected .tagged {
background-color: #eee;
border: 1px solid #BFBAB3;
}
.tagging .listTitle, .tagged .listTitle {
color: #bbb;
}
.selected .tagging .listTitle, .selected .tagged .listTitle {
color: #666;
}
.tagging .button, .tagged .button {
color:#aaa;
}
.selected .tagging .button, .selected .tagged .button {
color:#4F4B45;
}
.highlight, .marked {background:transparent; color:#111; border:none; text-decoration:underline;}
.tagging .button:hover, .tagged .button:hover, .tagging .button:active, .tagged .button:active {
border: none; background:transparent; text-decoration:underline; color:#000;
}
h1,h2,h3,h4,h5 { color: #666; background: transparent; padding-bottom:2px; font-family: Arial, Helvetica, sans-serif; }
h1 {font-size:18px;}
h2 {font-size:16px;}
h3 {font-size: 14px;}
#messageArea {
border: 4px solid #948979;
background: #f5f5f5;
color: #999;
font-size:90%;
}
#messageArea a:hover { background:#f5f5f5;}
#messageArea .button{
color: #666;
border: 1px solid #CC6714;
}
#messageArea .button:hover {
color: #fff;
background: #948979;
border-color: #948979;
}
* html .viewer pre {
margin-left: 0em;
}
* html .editor textarea, * html .editor input {
width: 98%;
}
.searchBar {float:right;font-size: 1.0em;}
.searchBar .button {color:#999;display:block;}
.searchBar .button:hover {border:1px solid #fff;color:#4F4B45;}
.searchBar input {
background-color: #FFF;
color: #999999;
border: 1px solid #CCC; margin-right:3px;
}
#sidebarOptions .button:active, #sidebarOptions .highlight {background:#F5F5F5;}
*html #contentFooter { padding:0.25em 1em 0.5em 1em;}
#noticeBoard {font-size: 0.9em; color:#999; position:relative;display:block;background:#fff; clear: both; margin-right:0.5em; margin-top:60px; padding:5px; border-bottom: 1px dotted #CCC; border-top: 1px dotted #CCC;}
#mainMenu #noticeBoard a,#mainMenu #noticeBoard .tiddlyLink {display:inline;border:none;padding:5px 2px;color:#DF9153 }
#noticeBoard a:hover {border:none;}
#noticeBoard br {display:inline;}
#mainMenu #noticeBoard .button{
color: #666;
border: 1px solid #DF9153;padding:2px;
}
#mainMenu #noticeBoard .button:hover{
color: #fff;
background: #DF9153;
border-color: #DF9153;
}
.searchbar {position:relative; width:11em;}
.searchbar .button{margin:0; width:11em;}
#header {display:inline-block;}
/*}}}*/
[[Bookmarklets|http://en.wikipedia.org/wiki/Bookmarklet]] can be useful for TiddlyWiki hackers. They are browser bookmarks that contain embedded JavaScript that can reach into the currently loaded TiddlyWiki page to manipulate them and extract data.
Drag these links to your bookmark/favourites bar, or right click on them and choose "add to bookmarks" or "add to favourites":
* [[Scrub shadow tiddlers|javascript:(function(){if(window.version&&window.version.title=='TiddlyWiki'){for(var s in config.shadowTiddlers){store.removeTiddler(s);}refreshDisplay();}})()]] - deletes any overridden shadow tiddlers, reverting them to their default values. Handy when you’ve gone mad with PageTemplate customisations and your TiddlyWiki document won’t display properly
* [[Scrub tiddler fields|javascript:(function(){if(window.version&&window.version.title=='TiddlyWiki'){store.forEachTiddler(function(title,tiddler){tiddler.fields={};});refreshDisplay();}})()]] - all the extended fields from a TiddlyWiki document, including that pesky “changecount” field
* [[Rescue raw TiddlyWiki content|javascript:(function(){if(window.version&&window.version.title=='TiddlyWiki'){var w=window.open();w.document.open();w.document.write('<html><body><pre>');w.document.write(store.allTiddlersAsHtml().htmlEncode());w.document.write('</pre></body></html>');w.document.close();}})()]] - opens a new window containing the raw content of a TiddlyWiki. Handy when you’ve inadvertently been editing an online version of TiddlyWiki that isn’t letting you save changes in the usual way
If you're creating your own bookmarklets, this [[editor|http://subsimple.com/bookmarklets/jsbuilder.htm]] and these [[tips|http://subsimple.com/bookmarklets/tips.asp]] are useful resources.
Considere as declarações:
{{{
int * x [10];
int (* y)[10];
int * * z;
}}}
Questões:
* O que significam?
* Quais dos usos abaixo são válidos?
{{{
int i,j,k[10],l[10][5],m[5][10];
x[1] = &i;
x[3] = j;
x[5] = k;
x[7] = k[2];
x[9] = k + 5;
x[0] = l[1];
x[2] = l + 1;
x[4] = m[1];
x[6] = &l[3][2];
x[8] = m[3] + 2;
y = &i;
y = k;
y[2] = k;
y = &k;
y = l;
y = m;
y = l[1];
y = m + 2;
z = k;
z = l;
z = m;
}}}
! Exercícios
* Seja o seguinte trecho de programa:
{{{
int i=3,j=5;
int *p, *q;
p = &i;
q = &j;
}}}
** Qual é o valor das seguintes expressões ?
*** {{{p == &i}}}
*** {{{ *p - *q }}}
*** {{{ **&p }}}
*** {{{3* - *p/(*q)+7}}}
* Qual será a saída do programa abaixo supondo que i ocupa o endereço 4094 na memória?
{{{
main() {
int i=5, *p;
p = &i;
printf(“%x %d %d %d %d \n”, p,*p+2,**&p,3**p,**&p+4);
}
}}}
* Qual é o resultado do seguinte programa?
{{{
#include <conio.h>
#include <stdio.h>
void main(){
float vet[5] = {1.1,2.2,3.3,4.4,5.5};
float *f;
int i;
f = vet;
printf("contador/valor/valor/endereco/endereco");
for(i = 0 ; i <= 4 ; i++){
printf("\ni = %d",i);
printf(" vet[%d] = %.1f",i, vet[i]);
printf(" *(f + %d) = %.1f",i, *(f+i));
printf(" &vet[%d] = %X",i, &vet[i]);
printf(" (f + %d) = %X",i, f+i);
}
}
}}}
* Considere os dois programas abaixo. O que fazem quando executados?
{{{
#include <conio.h>
#include <stdio.h>
void main() {
int vet[] = {4,9,12};
int i,*ptr;
ptr = vet;
for(i = 0 ; i < 3 ; i++) {
printf("%d ",*ptr++);
}
}
}}}
{{{
#include <conio.h>
#include <stdio.h>
void main(){
int vet[] = {4,9,12};
int i,*ptr;
ptr = vet;
for(i = 0 ; i < 3 ; i++) {
printf("%d ",(*ptr)++);
}
}
}}}
* Seja vet um vetor de 4 elementos: TIPO vet[4]. Supor que depois da declaração, vet esteja armazenado no endereço de memória 4092 (ou seja, o endereço de vet[0]). Qual o valor de vet+1, vet+2 e vet+3 se:
** TIPO = char?
** TIPO = int?
** TIPO = float?
* O que significam as seguintes declarações:
{{{
int * pi;
int ** ppi;
int * vpi[5];
int (* pvi)[3];
int (* pmi)[3][5];
int * mpi[5][3];
}}}
* Dê exemplo de uma declaração de:
** vetor para ponteiros para matrizes
** ponteiro para vetor de matrizes
** matriz de vetores de ponteiros
** matriz de ponteiros para vetores
* Reescreva o programa abaixo, substituindo o comando {{{while}}} pelo comando {{{for}}}.
{{{
#include <stdio.h>
#define NUMS 5
void main (void)
{
int nums[NUMS] = {16,54,7,43,-5};
int total = 0, *n_pt;
n_pt = nums; /*armazena o endereço de nums[0] em n_pt*/
while (n_pt < nums + NUMS)
total+=*n_pt++;
printf(“O total dos elementos do vetor é %d”, total);
}
}}}
* Determine a saída do seguinte programa:
{{{
#include <stdio.h>
void arr(int (*val)[3])
{
printf(“\n %d”, *(*val));
printf(“\n %d”, *(*val +1));
printf(“\n %d”, *(*(val+1)+2));
printf(“\n %d”, *(*val)+1);
}
void main (void)
{
int nums[2][3]={{33,16,29},{54,67,99}};
arrs(nums);
}
}}}
* Dada a declaração para val na função arr, a referência val[1][2] é válida dentro da função?
! Introdução
Um ARRANJO ( VETOR, MATRIZ ou STRING) é uma coleção de variáveis do mesmo tipo que é referenciada por um nome comum.
Um elemento específico em um ARRANJO é acessado por meio de um ÍNDICE.
VETORES e STRINGS são ARRANJOS unidimensionais. Isto é, necessita-se apenas um ÍNDICE para acessar um elemento.
MATRIZES são ARRANJOS multidimensionais. Ou seja, dois ou mais ÍNDICES são necessários para acessar um elemento de uma MATRIZ.
Em C, ARRAJOS são armazenados em posições de memória contíguas. O endereço mais baixo corresponde ao primeiro elemento e mais alto, ao último elemento.
! VETORES
''Declaração''
ESPECIFICADORES ID[ @@color(red):TAMANHO@@ ] @@color(red):= { ~LISTA_INICIALIZADORES }@@;
Onde os elementos em @@color(red):vermelho@@ são opcionais.
''Obs.: ''
* indices começam em 0 e vão até TAMANHO - 1
** ID[0] - primeiro elemento
** ID[1] - segundo elemento
** ...
** ID[TAMANHO - 1] - ultimo elemento
* não há verificação automática se o acesso aos elementos ocorre dentro da faixa 0 .. TAMANHO -1; o programador tem de tomar esta tarefa para si!
! MATRIZES
''Declaração''
ESPECIFICADORES ID[ @@color(red):~TAMANHO1@@ ][~TAMANHO2] ... [~TAMANHOn] @@color(red):= { ~LISTA_INICIALIZADORES }@@;
Onde os elementos em @@color(red):vermelho@@ são opcionais.
''Obs.: ''
* os indices de cada dimensão i começam em 0 e vão até TAMANHOi - 1
** ID[0][0]...[0] - primeiro elemento
** ...
** ID[TAMANHO1 - 1][TAMANHO2 - 1] ... [TAMANHOn -1] - ultimo elemento
* não há verificação automática se o acesso aos elementos ocorre dentro da faixa 0 .. TAMANHOi -1; o programador tem de tomar esta tarefa para si!
[img[img/cap4.fig4_2.png]]
! STRINGS
Em C, strings são VETORES de caracteres terminadas pelo caracter '\0' (NULO).
''Declaração''
ESPECIFICADORES ID[ @@color(red):TAMANHO@@ ] @@color(red):= { ~LISTA_INICIALIZADORES }@@;
ou
ESPECIFICADORES ID[ @@color(red):TAMANHO@@ ] @@color(red):= ~CONST_STRING@@;
Onde os elementos em @@color(red):vermelho@@ são opcionais.
''Obs.:'' Para armazenar um string com n caracteres não nulos você deve reservar n+1 posições. Uma a mais para o caracter '\0' !
!! #include <string.h>
[img[img/cap4.string_h.png]]
! Leitura Recomendada
* CCT cap4
! Exercícios
# Escreva um programa que leia uma linha de até 80 caracteres do teclado e imprima quantos caracteres foram lidos.
# Escreva um programa que leia uma linha de caracteres do teclado e imprima quantas vezes um caracter, também fornecido pelo teclado, aparece nesta linha. O programa também deve imprimir em que posições o caracter foi encontrado.
# Escreva um programa que leia uma linha do teclado e em seguida um par de caracteres. O programa deve procurar este par na linha e imprimir em que posições o par foi encontrado.
# Escreva um programa que leia uma linha do teclado e imprima todas as vogais encontradas no texto e o total de vezes que elas aparecem. Obs: Tamanho maximo da linha deve ser 40 caracteres.
# Oimperador romano Cesar usava um sistema simples para codificar as mensagens que enviava aos seus generais. Neste sistema cada letra era substituída por três letras a frente no alfabeto. A sua missão é mais simples ainda, escrever um programa que converta cada letra, e somente as letras, de uma mensagem de até 80 caracteres para a letra imediatamente posterior. Note que a letra 'z' deve ser convertida para a letra 'a', e a letra 'Z' para 'A'.
# Escreva um programa que leia uma frase de 80 caracteres e a imprime retirando os espaços em branco.
# Escreva um programa que leia uma linha do teclado de tamanho 80 caracteres. A linha somente contém letras. Divida a linha em blocos de 5 letras. Dentro de cada bloco o seu programa deve trocar a primeira letra pela seguinte, a segunda letra por duas letras adiante, a terceira por três letras e assim até a quinta. Os espaços em branco devem ser retirados da frase. Considere o seguinte exemplo.
** Frase lida: EVA VIU A UVA
** Retirada dos espaços em branco: EVAVIUAUVA
** Divisão em blocos de 5 (Espaços em branco mostrados para facilitar entendimento): EVAVI UAUVA
** Criptografia: FYDAN VCYAF
** O que será impresso: FYDANVCYAF
# Escreva um programa que leia uma matriz de 3x3 que contém somente caracteres 0 e X e procure linhas que contenham somente um dos dois caracteres. O caracter a ser procurado deve ser lido do teclado.
# Escreva um programa que leia uma linha de caracteres do teclado e converta o primeiro caracter de cada palavra para maiúsculas. Assuma que as palavras são sempre separadas por um branco.
# Escreva um programa que leia para um vetor um conjunto de números inteiros. Assuma que o conjunto de números lidos é menor que o tamanho do vetor. O programa deve inserir no vetor em uma posição especificada pelo usuário um número lido do teclado. Assuma que a posição especificada pelo usuário corresponde ao índice do vetor.
# Faça um programa que inverta uma string. O programa deve ler a string com gets e armazená-la invertida em outra string. Use o comando for para varrer a string até o seu final.
# Faça um programa que leia duas matrizes 3x3 e imprima seu produto.
# Escreva um programa que leia um conjunto de nomes para uma matriz e imprima estes nomes em ordem alfabética. Assuma que os nomes serão lidos somente em letras maiúsculas. Assuma também que os nomes têm no máximo 40 caracteres e serão lidos 10 nomes ao todo.
powered by [[TiddlyWiki|http://www.tiddlywiki.com]] © Osmosoft, [[Mocha Theme|http://tiddlythemes.com/#Mocha]]
//{{{
//This ensures that the footer sticks to the bottom of the screen when there are no tiddlers open. If that is not desirable, it can be deleted.
function setFooter() {
if (document.getElementById && document.getElementById("contentFooter") ) {
var windowHeight=findWindowHeight();
if (windowHeight>0) {
var contentHeight= document.getElementById('mainMenu').offsetHeight + document.getElementById("header").offsetHeight + document.getElementById("contentFooter").offsetHeight;
var menu= document.getElementById('mainMenu');
if (windowHeight-(contentHeight)>=0) {
menu.style.position='relative';
menu.style.marginBottom=(windowHeight-(contentHeight))+'px';
}
else {
menu.style.position='';
menu.style.marginBottom='';
}
}
}
}
window.onresize = function() {
setFooter();
}
Story.prototype.refreshTiddler_footerhack=Story.prototype.refreshTiddler;
Story.prototype.refreshTiddler = function (title,template,force)
{
var theTiddler = Story.prototype.refreshTiddler_footerhack.apply(this,arguments);
setFooter();
return theTiddler;}
//}}}
[img[img/cap7.typedef.png]]
!! Exemplo
{{{
#ifndef MENU_H
#define MENU_H
typedef struct item {
char * str;
void(* fun)(void);
struct item * sub;
struct item * sup;
struct item * nxt;
struct item * prv;
} Item;
void addMenuItem (const char * str, void(* fun)(void));
void addMenuSubItem (const char * str_i,const char * str_si, void(* fun)(void));
void loopMenu(void);
#endif
}}}
{{{
/** menu.c */
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include "buffer.h"
#include "menu.h"
Item * menu;
Item * menu_sel;
int sub_items_visible;
...
}}}
[img[img/cap5.ptr_funcao.png]]
!! Exemplo
{{{
/** menu.c */
...
void addMenuItem (const char * str, void(* fun)(void)) { /** PARAM PONT. FUNCAO */
Item * ptr;
if ( menu == NULL ) {
menu = (Item *) malloc(sizeof (Item));
ptr = menu;
ptr->prv = NULL;
} else {
ptr = menu;
while ( ptr->nxt ) {
if ( strcmp(ptr->str,str) == 0 )
return;
ptr = ptr->nxt;
}
ptr->nxt = (Item *) malloc(sizeof (Item));
ptr->nxt->prv = ptr;
ptr = ptr->nxt;
}
ptr->str = strdup(str);
ptr->fun = fun; /** ATRIBUICAO PONTEIRO FUNCAO **/
ptr->sub = NULL;
ptr->sup = NULL;
ptr->nxt = NULL;
}
...
{
...
case ENTER:
if ( menu_sel->fun )
(*(menu_sel->fun))(); /** CHAMADA FUNCAO VIA PONTEIRO **/
else
...
}
}}}
[img[img/cap7.union.png]]
{{{
#define ENTER 13
#define ESC 27
#define RTARR 77
#define LTARR 75
#define UPARR 72
#define DWARR 80
union u_type{
int i;
char ch;
} ich;
void loopMenu() {
while ( 1 ) {
ich.i = getch();
switch ( ich.ch ) {
case ENTER:
....
}}}
! CÓDIGO COMPLETO
O código abaixo implementa um sistema de menus para um programa de controle acadêmico.
{{{
/** main.c */
#include <stdio.h>
#include <stdlib.h>
#include "menu.h"
void f() {
printf("function activation!");
getch();
}
extern Item * menu;
extern Item * menu_sel;
extern int sub_items_visible;
int main(int argc, char *argv[])
{
addMenuItem("CADASTRO",NULL);
addMenuItem("MATRICULA",NULL);
addMenuItem("RELATORIO",NULL);
addMenuSubItem("CADASTRO","Alunos",f);
addMenuSubItem("CADASTRO","Professores",f);
addMenuSubItem("CADASTRO","Disciplinas",f);
addMenuSubItem("MATRICULA","Matriculas",f);
addMenuSubItem("MATRICULA","Turma",f);
loopMenu();
return 0;
}
}}}
{{{
#ifndef MENU_H
#define MENU_H
typedef struct item {
char * str;
void(* fun)(void);
struct item * sub;
struct item * sup;
struct item * nxt;
struct item * prv;
} Item;
void addMenuItem (const char * str, void(* fun)(void));
void addMenuSubItem (const char * str_i,const char * str_si, void(* fun)(void));
void loopMenu(void);
#endif
}}}
{{{
/** menu.c */
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include "buffer.h"
#include "menu.h"
Item * menu;
Item * menu_sel;
int sub_items_visible;
void addMenuItem (const char * str, void(* fun)(void)) {
Item * ptr;
if ( menu == NULL ) {
menu = (Item *) malloc(sizeof (Item));
ptr = menu;
ptr->prv = NULL;
} else {
ptr = menu;
while ( ptr->nxt ) {
if ( strcmp(ptr->str,str) == 0 )
return;
ptr = ptr->nxt;
}
ptr->nxt = (Item *) malloc(sizeof (Item));
ptr->nxt->prv = ptr;
ptr = ptr->nxt;
}
ptr->str = strdup(str);
ptr->fun = fun;
ptr->sub = NULL;
ptr->sup = NULL;
ptr->nxt = NULL;
}
void addMenuSubItem (const char * str_i,const char * str_si, void(* fun)(void)) {
Item * ptr;
ptr = menu;
while ( ptr ) {
if ( strcmp(ptr->str,str_i) == 0 )
break;
ptr = ptr->nxt;
}
if ( ptr == NULL )
return;
if ( ptr->sub == NULL ) {
ptr->sub = (Item *) malloc(sizeof (Item));
ptr->sub->prv = NULL;
ptr->sub->sup = ptr;
ptr = ptr->sub;
} else {
ptr = ptr->sub;
while ( ptr->nxt ) {
if ( strcmp(ptr->str,str_si) == 0 ) {
ptr->fun = fun;
return;
}
ptr = ptr->nxt;
}
ptr->nxt = (Item *) malloc(sizeof (Item));
ptr->nxt->prv = ptr;
ptr->nxt->sup = ptr->sup;
ptr = ptr->nxt;
}
ptr->str = strdup(str_si);
ptr->fun = fun;
ptr->sub = NULL;
ptr->nxt = NULL;
}
void drawMenu(void) {
Item * ptr = menu, * sel_ptr;
int x = 1, y = 1 , sel_x;
int n = strlen( ptr->str);
while ( ptr ) {
if ( menu_sel == ptr || menu_sel->sup == ptr ) {
sel_ptr = ptr;
sel_x = x;
}
if ( menu_sel == ptr ) {
xyputs(x,y,">");
xyputs(x+n+4,y,"<");
}
xyputs(x+2,y,ptr->str);
x += n + 5 , ptr = ptr->nxt;
}
if ( sub_items_visible ) {
int i;
ptr = sel_ptr -> sub;
for (i = 0 ; i<n; i++ )
xyputs(sel_x+2+i,y+1,"-");
y +=2 ;
while ( ptr ) {
if ( menu_sel == ptr )
xyputs(sel_x,y,">");
xyputs(sel_x+2,y,ptr->str);
y++ , ptr = ptr->nxt;
}
}
}
#define ENTER 13
#define ESC 27
#define RTARR 77
#define LTARR 75
#define UPARR 72
#define DWARR 80
union {
int i;
char ch;
} ich;
void loopMenu() {
menu_sel = menu;
while ( 1 ) {
clearBuf();
drawMenu();
displayBuf();
ich.i = getch();
switch ( ich.ch ) {
case ENTER:
if ( menu_sel->fun )
(*(menu_sel->fun))();
else
if ( menu_sel -> sub ) {
sub_items_visible = 1;
menu_sel = menu_sel->sub;
}
break;
case ESC:
if ( menu_sel -> sup ) {
sub_items_visible = 0;
menu_sel = menu_sel->sup;
break;
} else
return;
case UPARR:
if ( menu_sel->sup && menu_sel->prv )
menu_sel = menu_sel->prv;
else
if ( menu_sel->sup ) {
sub_items_visible = 0;
menu_sel = menu_sel->sup;
}
else
sub_items_visible = 0;
break;
case DWARR:
if ( menu_sel -> sub ) {
sub_items_visible = 1;
menu_sel = menu_sel->sub;
} else
if ( menu_sel->nxt )
menu_sel = menu_sel->nxt;
break;
case LTARR:
if ( menu_sel->sup ) {
if ( menu_sel->sup->prv )
menu_sel = menu_sel->sup->prv;
} else
if ( menu_sel->prv )
menu_sel = menu_sel->prv;
break;
case RTARR:
if ( menu_sel->sup ) {
if ( menu_sel->sup->nxt )
menu_sel = menu_sel->sup->nxt;
} else
if ( menu_sel->nxt )
menu_sel = menu_sel->nxt;
break;
}
}
}
}}}
{{{
/** buffer.h */
#ifndef BUFFER_H
#define BUFFER_H
void clearBuf(void);
void xyputs(unsigned short x, unsigned short y, const char * str);
void displayBuf(void);
#endif
}}}
{{{
/** buffer.c */
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#define BUFW 80
#define BUFH 24
char buf[BUFH][BUFW];
void clearBuf(void){
int x,y;
for( y = 0; y < BUFH; y++ ) {
for( x = 0; x < BUFW; x++ )
buf[y][x] = ' ';
}
}
void xyputs(unsigned short x, unsigned short y, const char * str) {
x %= BUFW;
y %= BUFH;
for ( ; *str ; str++ ) {
switch( *str ) {
case '\n' : x = 0, y = (y + 1) % BUFH;
break;
case '\b' :
if ( x == 0 ) {
x = BUFW - 1;
y = y == 0 ? BUFH - 1 : y -1;
} else
x --;
break;
default :
buf[y][x] = *str;
x = (x+1)%BUFW;
y = x == 0 ? (y+1)%BUFH : y;
}
}
}
void displayBuf(void) {
//fseek(stdout,sizeof buf,SEEK_END);
system("cls");
fwrite(&buf,sizeof buf ,1,stdout);
}
}}}