Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

Apostila em C, Notas de estudo de Informática

Logica de programação

Tipologia: Notas de estudo

Antes de 2010

Compartilhado em 13/10/2009

mony-machado-7
mony-machado-7 🇧🇷

1 documento

1 / 170

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Universidade Federal de Santa Catarina
UFSC
Centro Tecnológico
-
CTC
Departamento de Automação e Sistemas
-
DAS
Sistemas Industriais Inteligentes
S2i
http://s2i.das.ufsc.br/
Curso de Linguaguem
Computacional C/C++
Florianópo
lis, janeiro de 2002.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42
pf43
pf44
pf45
pf46
pf47
pf48
pf49
pf4a
pf4b
pf4c
pf4d
pf4e
pf4f
pf50
pf51
pf52
pf53
pf54
pf55
pf56
pf57
pf58
pf59
pf5a
pf5b
pf5c
pf5d
pf5e
pf5f
pf60
pf61
pf62
pf63
pf64

Pré-visualização parcial do texto

Baixe Apostila em C e outras Notas de estudo em PDF para Informática, somente na Docsity!

Universidade Federal de Santa Catarina – UFSC

Centro Tecnológico - CTC

Departamento de Automação e Sistemas - DAS

Sistemas Industriais Inteligentes – S2i

http://s2i.das.ufsc.br/

Curso de Linguaguem

Computacional C/C++

Florianópolis, janeiro de 2002.

________________________________________________________________________________________________

________________________________________________________________________________________________

1 Programação em C

Atualmente, empregam-se cada vez mais sistemas computacionais na automatização de processos industriais. Os sistemas computacionais empregados (ver Figura 1) variam desde um simples circuito lógico digital, passando por uma circuito composto por um microprocessador ou um CLP, até sistemas complexos envolvendo um ou mais microcomputadores ou até estações de trabalho. Um engenheiro que atua nesta área deve conhecer os sistemas computacionais disponíveis e ser capaz de selecionar o melhor equipamento para uma dada aplicação. Além disto, este profissional deve conseguir instalar este sistema, configurá-lo e acima de tudo programá-lo para que este execute a tarefa de automatização atendendo os requisitos industrias do sistema, como imunidade a falhas ou comportamento determinístico com restrições temporais (sistemas tempo- real). Neste contexto, a programação destes sistemas se faz de suma importância. Basicamente, a inteligência dos sistemas automatizados é implementada através de programas computacionais, comandando os componentes de hardware para executar a tarefa com o comportamento desejado.

Sistemas Digitais

Microprocessadores

CLP

Micro-Computador

Redes de Computadores

capacidade

computacional

custoflexibilidadecomplexidadeexpandabilidade

Figura 1 : Comparação entre os diversos sistemas computacionais para aplicações industriais.

Nas últimas décadas, o desenvolvimento em hardware permitiu que cada vez mais os processos industrias sejam automatizados e interligados através de sistemas computacionais. Entretanto, a evolução em software não se deu em tamanha velocidade como a de hardware. Desta forma, um dos grandes paradigmas tecnológicos hoje é o desenvolvimento de programas para a realização de tarefas complexas e que exigem um alto grau de inteligência. A maneira de se comunicar com um computador chama-se programa e a única linguagem que o computador entende chama-se linguagem de máquina. Portanto todos os programas que se comunicam com a máquina devem estar em linguagem de máquina. Para permitir uma maior flexibilidade e portabilidade no desenvolvimento de software, foram implementados nos anos 50 os primeiros programas para a tradução de linguagens semelhantes à humana (linguagens de "alto nível" ) em linguagem de máquina. A forma como os programas são traduzidos para a linguagem de máquina classifica-se em duas categorias:

  • Interpretadores : Um interpretador lê a primeira instrução do programa, faz uma consistência de sua sintaxe e se não houver erro converte-a para a linguagem de máquina para finalmente executá-la. Segue, então, para a próxima instrução, repetindo o processo até que a última instrução seja executada ou a consistência aponte algum erro. São muito bons para a função de depuração ( "debugging" ) de programas, mas são mais lentos. Ex.: BASIC Interpretado, Java.
  • Compiladores : Traduzem o programa inteiro em linguagem de máquina antes de serem executados. Se não houver erros, o compilador gera um programa em disco com o sufixo

________________________________________________________________________________________________

.OBJ com as instruções já traduzidas. Este programa não pode ser executado até que sejam agregadas a ele rotinas em linguagem de máquina que lhe permitirão a sua execução. Este trabalho é feito por um programa chamado “ linkeditor ” que, além de juntar as rotinas necessárias ao programa .OBJ , cria um produto final em disco com sufixo .EXE que pode ser executado diretamente do sistema operacional.

Compiladores bem otimizados produzem código de máquina quase tão eficiente quanto aquele gerado por um programador que trabalhe direto em Assembly. Oferecem em geral menos facilidades de depuração que interpretadores, mas os programas são mais rápidos (na ordem de 100 vezes ou mais). Ex.: BASIC Compilado, FORTRAN, PASCAL, MÓDULA - 2, C, C++. Além da velocidade, outras vantagens podem ser mencionadas:

  • é desnecessária a presença do interpretador ou do compilador para executar o programa já compilado e linkeditado;
  • programas .EXE não podem ser alterados, o que protege o código-fonte.

Desta forma, os compiladores requerem o uso adicional de um editor de ligações ( "Linker" ), que combina módulos-objetos ( "Traduzidos" ) separados entre si e converte os módulos assim "linkados" no formato carregável pelo sistema operacional (programa .EXE ). Estudaremos aqui uma das linguagens de alto-nível mais utilizadas na indústria: a linguagem "C" e, posteriormente, a sua sucessora a linguagem “C++”, resultado da introdução da programação “Orientada a Objetos” à linguagem “C”. A programação é uma atividade que requer paciência, concentração e organização. O aprendizado desta técnica deve acontecer de forma gradual para que o programador entenda bem os conceitos envolvidos e compreenda os diversos mecanismos disponíveis. Por isso, o aluno deve prosseguir neste aprendizado no seu ritmo, permitindo-se consolidar os conhecimentos através dos exemplos e exercícios. O aluno deve buscar formar uma boa “base” antes de se preocupar com as estruturas mais complexas. A caminhada é feita passo a passo, com calma e segurança.

________________________________________________________________________________________________

Primeiro, datilografe o seu programa com o auxílio de um processador de textos em modo ASCII. Grave o programa em disco dando a ele um nome como sufixo .C. O programa gerado é chamado de código fonte. Na seqüência, compile o fonte seguindo as instruções do seu compilador, o que criará um programa com o sufixo .OBJ em disco. O programa gerado é chamado de objeto. Por fim, basta linkeditar o objeto seguindo as instruções do seu linkeditor o que criará um programa com sufixo .EXE em disco. O programa gerado é chamado de executável. A Figura 2 apresenta o processo de geração de um programa em C.

2.3 A Estrutura Básica de um Programa em C

A forma geral de um programa em "C" é a seguinte:

< diretivas do pré-processador > < declarações globais >; main() { < declarações locais >; /∗ comentário ∗/ < instruções >; } < outras funções >

Vamos começar por um programa bem simples em C. Você pode escrever este programa em um arquivo ASCII e salvá-lo com um nome terminando em “.C”. O programa serve para escrever na tela a frase “Bom Dia!!!!”.

/* Programa : Bom Dia! */ #include <stdio.h>

void main() { printf(“Bom Dia!!!!”); }

Na primeira linha, os símbolos /* e */ servem para delimitar um comentário do programa. É muito importante que os programas sejam comentados de forma organizada. Isto permite que outras pessoas possam facilmente entender o código fonte. Os comentários não são interpretados pelo compilador, servindo apenas para a documentação e esclarecimento do programador. Depois, segue-se com uma diretiva para o pré-processador “#include <stdio.h>”. Isto advém do fato de C ter um núcleo pequeno de funções básicas. Ao escrever esta linha de código, o pré-processador irá acrescentar ao programa todas as funcionalidades definidas na biblioteca “stdio” e irá linká-la posteriormente ao programa. Desta forma, você poderá usufruir todos os serviços disponíveis nesta biblioteca. Por fim, temos a função “main()”. Esta função indica ao compilador em que instrução deve ser começada a execução do programa. Portanto, esta função deve ser única, aparecendo somente uma vez em cada programa. O programa termina quando for encerrada a execução da função main(). No caso deste programa exemplo, ela não recebe nenhum parâmetro e também não retorna parâmetro nenhum. Isto fica explícito através da palavra-chave void escrita na frente do programa. Se em vez de void tivéssemos escrito int, isto significaria que a função main() deveria retornar um valor do tipo inteiro ao final de sua execução. Como este é o valor retornado

________________________________________________________________________________________________

pela função main(), este também será o valor retornado pelo programa após a sua execução. As funções e as suas características serão apresentadas em detalhes nos próximos capítulos.

int main() { printf(“Bom Dia!!!!”); return 0; /* indica ao OS que não ocorreu nenhum erro durante a execução do programa */ }

Todo o corpo de uma função em C é inicializado e finalizado através das chaves { e }. Estas chaves definem o bloco de instruções a serem executados por esta função. A primeira instrução dada dentro do programa é “ printf(“Bom Dia!!!!”);”. Printf é uma função definida em “stdio.h” para escrever dados na janela console. Todas as instruções de programa têm que ser declaradas dentro de alguma função (na main() ou outra qualquer). Todas as instruções devem estar dentro das chaves que iniciam e terminam a função e são executadas na ordem em que as escrevemos. As instruções C são sempre encerradas por um ponto-e-vírgula (;). O ponto-e-vírgula é parte da instrução e não um simples separador. Esta instrução é uma chamada à função printf();, os parênteses nos certificam disso e o ponto-e-vírgula indica que esta é uma instrução. Nota-se que a função é chamada escrevendo-se o nome desta e colocando-se os parâmetros desta dentro dos parênteses. A final de cada instrução em C, faz-se necessário o acréscimo de um ponto-vírgula “;”. As variáveis em C podem estar dentro de uma função ou no início do arquivo fonte. Variáveis declaradas no início do arquivo fonte são consideradas “globais”, isto é, são visíveis (i.e. acessíveis) para todas as funções do programa. Variáveis declaradas dentro de uma função são consideradas “locais”, isto é, visíveis somente pela função onde são declaradas. "C" distingue nomes de variáveis e funções em maiúsculas de nomes em minúsculas. Você pode colocar espaços, caracteres de tabulação e pular linhas à vontade em seu programa, pois o compilador ignora estes caracteres. Em C não há um estilo obrigatório. Entretanto, procure manter os programas tão organizados quanto for possível, pois isto melhora muito a legibilidade do programa, facilitando o seu entendimento e manutenção.

2.4 Variáveis

As variáveis são o aspecto fundamental de qualquer linguagem de computador. Uma variável em C é um espaço de memória reservado para armazenar um certo tipo de dado e tendo um nome para referenciar o seu conteúdo. O espaço de memória de uma variável pode ser compartilhado por diferentes valores segundo certas circunstâncias. Em outras palavras, uma variável é um espaço de memória que pode conter, a cada tempo, valores diferentes.

/* Programa : Exemplo de variáveis! */ #include <stdio.h>

void main() { int num; /* declaracao / num = 2; / atribui um valor / printf(“Este é o número dois: %d”, num); / acessa a variável */

________________________________________________________________________________________________

float 4 Bytes ±3,4E-38 a ±3,4E+ long float 8 Bytes (^) ±1,7E-308 a ±1,7E+ double 8 Bytes ±1,7E-308 a ±1,7E+

Observação: As declarações que aparecem na tabela acima entre parênteses (), indicam que estas declarações são optativas. Por exemplo “short unsigned int” indica a mesma precisão que “unsigned int”. O tipo int tem sempre o tamanho da palavra da máquina, isto é, em computadores de 16 bits ele terá 16 bits de tamanho. Emprega-se o complemento de dois dos números positivos para o cálculo e representação dos números negativos. A escolha de nomes significativos para suas variáveis pode ajudá-lo a entender o que o programa faz e prevenir erros. Uma variável não pode ter o mesmo nome de uma palavra-chave de C. Em C, letras minúsculas e maiúsculas são diferentes.

Tabela de Palavras Chaves em C:

auto default float register struct volatile break do for return switch while case double goto short typedef char else if signed union const enum int sizeof unsigned continue extern long static void

Exemplo de um programa que emprega as variáveis apresentadas.

void main() { float y; /∗ variável Real não inicializada ∗/ int i; /∗ variável Inteira não inicializada ∗/ double x = 3.24; /∗ variável Double inicializada com ‘3.24’ ∗/ char c = 'a'; /∗ variável Char inicializada com ‘a’ ∗/ i = 100; /∗ variável ‘i’ recebe o valor 100 ∗/ y = (float) i; /∗ converte tipos ∗/ }

Preste atenção na operação “y= (float) i;”. Esta operação é muito empregada para conversão de tipos de variáveis diferentes. Suponha que você tenha uma variável ‘x’ de tipo A e queira convertê-la para o tipo B e armazená-la em y deste tipo. Você pode executar esta operação através do operador: y = ((B) x); Atenção: Cuidado ao converter variáveis com precisão grande para variáveis com precisão pequena, ou seja, variáveis que utilizam um número diferente de bits para representar dados. Você pode perder informações importantes por causa desta conversão. Por exemplo, se você converter um float num int, você perderá todos os dígitos depois da vírgula (precisão).

void main() { float y = 3.1415; int x = 0;

________________________________________________________________________________________________

x = (int) y; /* Equivalente à: x = 3; */ }

2.6 Constantes

Um constante tem valor fixo e inalterável. No primeiro programa exemplo, mostramos o uso de uma cadeia de caracteres constante juntamente com a função printf(): printf(“Bom Dia!!!!”);

Há duas maneiras de declarar constantes em C: a) usando a diretiva #define do pré-processador: #define < nome da constante > < valor >

Esta diretiva faz com que toda aparição do nome da constante no código seja substituída antes da compilação pelo valor atribuído. Não é reservado espaço de memória no momento da declaração define. A diretiva deve ser colocada no inicio do arquivo e tem valor global (isto é, tem valor sobre todo o código). Exemplo: #define size 400 #define true 1 #define false 0 /* → não usa ";" nem "=" */

b) utilizando a palavra-chave " const ": const < tipo > < nome > = < valor >;

Esta forma reserva espaço de memória para uma variável do tipo declarado. Uma constante assim declarada só pode aparecer do lado direito de qualquer equação (isto equivale a dizer que não pode ser atribuido um novo valor aquela “variável” durante a execução do programa). Exemplo: const char letra = 'a'; const int size = 400; const double gravidade = 9.81;

/* Programa: Exemplo do uso de Constantes */ #define Size 4

void main() { const char c = ‘c’; const int num = 10; int val = Size; }

Em C uma constante caractere é escrita entre aspas simples, uma constante cadeia de caracteres entre aspa duplas e constantes numéricas com o número propriamente dito. Exemplos de constantes: a) caracter: ‘a’ b) cadeia de caracteres: “Bom Dia !!!!” c) número: -3.

________________________________________________________________________________________________

j = 2; /* j recebe o valor ‘2’ / ptr = &i; / ptr recebe o valor do endereço de i */ *ptr = ptr + j; / equivale a: i = i + j */ } Nosso objetivo neste momento não é apresentar todas as potencialidades dos ponteiros. Estamos aqui apresentando os ponteiros primeiramente como um tipo de dado especial. O importante aqui é entender o conteúdo de um ponteiro e como este pode ser empregado. Posteriormente, apresentaremos as funcionalidades dos ponteiros à medida que formos evoluindo no aprendizado de C.

2.8 Exercícios

2.1 Crie o seu programa “Hello, World!” ou “Olá, Mamãe!”;

2.2 Crie um programa que contenha todos os tipos de variáveis possíveis e as combinações dos modificadores possíveis. Inicialize estas variáveis com valores típicos. Use o método para a conversão de tipos para converter: a) A variávelo do tipo char em todos os outros tipos de variáveis. b) A variávelo do tipo double em todos os outros tipos de variáveis. Discuta o que acontece com a precisão das variáveis.

2.3 Crie um programa que exemplifique a utilização de ponteiros. Que contenha pelo menos a declaração de um ponteiro, sua inicialização com zero, a obtenção do endereço de uma variável com o operador ‘&’ e o acesso ao dado representado pelo ponteiro.

2.4 Utilize as diretivas #define para criar constantes e emprege estas constantes para inicializar as variáveis do programa acima.

2.5 Analise o seguinte programa:

/* Testando 1,2,3 */

#define Default_Y 2

void main() { const int num = 10; int y = Default_Y; const int *ptr = 0; ptr = # *ptr = *ptr + y; }

Aponte onde está o erro e explique por quê.

________________________________________________________________________________________________

3 Entrada/Saída Console

As rotinas de entrada/saída do console se encontram nas bibliotecas "stdio.h" e "conio.h" e, por isso, estas bibliotecas devem ser incluídas nos programas aplicativos através da diretiva ‘include’: #include <stdio.h> #include <conio.h>

Algumas das funções de entrada e saída para a console mais utilizadas são apresentadas a seguir:

3.1 Printf()

A função printf()é uma das funções de E/S (entrada e saída) que podem ser usadas em C. Ela não faz parte da definição de C mas todos os sistemas têm uma versão de printf() implementada. Ela permite a saída formatada na tela. Já vimos duas aplicações diferentes da função printf(): printf(“Bom Dia!!!!”); printf(“Este é o número dois: %d”, num);

A função printf()pode ter um ou vários argumentos. No primeiro exemplo nós colocamos um único argumento: “Bom Dia !!!!”. No segundo entretanto, colocamos dois: “Este é o número dois: %d” que está à esquerda e o valor 2 à direita da vírgula que separa os argumentos. Sintaxe de printf(): printf(“string-formatação“, < lista de parâmetros >);

A string de formatação pode conter caracteres que serão exibidos na tela e códigos de formatação que indicam o formato em que os argumentos devem ser impressos. No nosso segundo exemplo, o código de formatação %d solicita a printf() para imprimir o segundo argumento em formato decimal na posição da string onde aparece o %d. Cada argumento deve ser separado por uma vírgula. Além do código de formatação decimal ( %d ), printf()aceita vários outros. O próximo exemplo mostra o uso do código %s para imprimir uma cadeia de caracteres:

/* Exemplo da função Printf() */ #include <stdio.h>

int main(int argc, char* argv[]) { printf(“%s esta a %d milhoes de milhas \n do sol.”, “Venus”, 67);

}

A saída será:

Venus está a 67 milhoes de milhas do sol.

Aqui, além do código de formatação, a expressão de controle de printf() contém um conjunto de caracteres estranho: \n.

________________________________________________________________________________________________

%p (^) Pointer xxxx (offset) se Near, xxxx : xxxx (base: offset) se Far %s Apontador de string, emite caracteres até aparecer caracter zero (00H) %u (^) Inteiro decimal sem sinal (unsigned int) %x Hexadecimal

Abaixo segue alguns exemplos da formatação apresentada acima:

/* Programa de Exemplo da formatação da saída com Printf() */

#include <stdio.h>

int main(int argc, char* argv[]) { float x; double y = -203.4572345; int a, b; a = b = 12; x = 3.141523; printf("Bom dia"); printf("\n\t\tBom dia\n"); /* pula linha após escrever bom dia */ printf("O valor de x é %7.3f\n", x); printf("Os valores de i, j e y são: %d %d %lf \n", a, b, y); }

Observação: Caso você queira imprimir na tela os caracteres especiais ‘\’ ou ‘%’, você deve escrevê-los na função printf() de forma duplicada, o que indicará ao compilador que este não se trata de um parâmetro da função printf() mas sim que deseja-se imprimir realmente este caracter. O exemplo abaixo apresenta este caso:

#include <stdio.h> void main() { int reajuste = 10; printf(“O reajuste foi de %d%%. \n”, reajuste); } a saída será: O reajuste foi de 10%.

3.2 Cprintf()

Basicamente cprintf() é igual a printf(), mas usa as coordenadas atuais do cursor e da janela que forem ajustados anteriormente, bem como ajustes de côr de caracteres. Utilize esta função para escrever na tela em posições pré-definidas.

3.3 Scanf()

A função scanf() é outra das funções de E/S implementadas em todos os compiladores C. Ela é o complemento de printf() e nos permite ler dados formatados da entrada padrão (teclado). A função scanf() suporta a entrada via teclado. Um espaço em branco ou um CR/LF (tecla “Enter”) definem o fim da leitura. Observe que isto torna inconveniente o uso de scanf()

________________________________________________________________________________________________

para ler strings compostas de várias palavras (por exemplo, o nome completo de uma pessoa). Para realizar este tipo de tarefa, veremos outra função mais adequada na parte referente à strings. Sua sintaxe é similar à de printf(), isto é, uma expressão de controle seguida por uma lista de argumentos separados por vírgula. Sintaxe: scanf(“string de definição das variáveis”, <endereço das variáveis>);

A string de definição pode conter códigos de formatação, precediddos por um sinal % ou ainda o caracter * colocado após o % que avisa à função que deve ser lido um valor do tipo indicado pela especificação, mas não deve ser atribuído a nenhuma variável (não deve ter parâmetros na lista de argumentos para estas especificações). A lista de argumentos deve consistir nos endereçoes das variáveis. O endereço das variáveis pode ser obtido através do operador ‘&’ apresentado na secção sobre ponteiros (ver 2.7). Exemplo:

/* Programa exemplo do uso de Scanf() */ #include <stdio.h>

void main() { float x; printf ("Entre com o valor de x : "); scanf ("%f", &x); /* lê o valor do tipo float (%f) e armazena na variável x (&x) */ }

Esta função funciona como o inverso da função printf(), ou seja, você define as variáveis que deveram ser lidas da mesma forma que definia estas com printf(). Desta forma, os parâmetros de scanf() são em geral os mesmos que os parâmetros de printf(), no exemplo acima observa-se esta questão. O código de formatação de scanf()é igual ao código de formatação de printf(). Por isso, veja as tabelas de formatação de printf() para conhecer os parâmetros de scanf(). Outro exemplo de scanf():

/* Segundo Programa exemplo do uso de Scanf() */ #include <stdio.h>

main() { float anos, dias; printf(“Digite a sua idade em anos: ”); scanf(“%f”, &anos); dias = anos*365; printf(“Sua idade em dias e´ %.0f.\n”, dias); }

3.4 Getch(), Getche() e Getchar()

Em algumas situações, a função scanf()não se adapta perfeitamente pois você precisa pressionar [enter] depois da sua entrada para que scanf() termine a leitura. Neste caso, é melhor usar getch(), getche() ou getchar().