(Parte 1 de 10)

Faculdade de Ciências Aplicadas de Cascavel – FACIAP Curso de Ciência da Computação

UNIDADE 1 – CONSIDERAÇÕES INICIAIS SOBRE A LINGUAGEM C1
1.1 AS ORIGENS DO C/C++1
1.2 COMPILADORES E INTERPRETADORES2
1.3 WARNINGS E ERROS3
1.4 A LINGUAGEM C/C++ É CASE-SENSITIVE3
1.5 FUNÇÕES EM C3
1.5.1 FUNÇÕES COM ARGUMENTOS4
1.5.2 FUNÇÕES QUE RETORNAM VALORES5
1.5.3 A FORMA GERAL DE UMA FUNÇÃO6
1.6 PALAVRAS RESERVADAS DA LINGUAGEM C6
UNIDADE 2 – TIPOS DE DADOS, CONSTANTES, OPERADORES E EXPRESSÕES7
2.1 NOMES DE IDENTIFICADORES7
2.2 TIPOS DE DADOS7
2.2.1 MODIFICADORES DE TIPOS8
2.3 DEFINIÇÃO DE VARIÁVEIS9
2.4 DEFINIÇÃO DE CONSTANTES9
2.4.1 CONSTANTES HEXADECIMAIS E OCTAIS10
2.4.3 CÓDIGOS DE BARRA INVERTIDA11
2.5 OPERADORES11
2.5.1 OPERADOR DE ATRIBUIÇÃO12
2.5.2 OPERADORES ARITMÉTICOS12
2.5.3 OPERADORES RELACIONAIS12
2.5.4 OPERADORES LÓGICOS12
2.5.5 MANIPULAÇÃO DE BITS13
2.5.6 OPERADORES DE ASSINALAMENTO13
2.5.7 OPERADORES DE PRÉ E PÓS-INCREMENTO14
2.5.8 OPERADORES DE ENDEREÇO14
2.6 TABELA DE OPERADORES DO C14
2.7 EXPRESSÕES15
2.7.1 CONVERSÕES DE TIPOS EM EXPRESSÕES15
2.7.2 MODELADORES (CASTS)16
2.7.3 ESPAÇAMENTO E PARÊNTESES16
2.8 ESQUELETO DE UM PROGRAMA EM C17
3.1 COMANDOS E BLOCOS18
3.2 PRINTF( )18
3.3 SCANF( )20
3.4 A DECLARAÇÃO if23
3.4.1 USANDO A DECLARAÇÃO else24
3.4.2 O ENCADEAMENTO if-else-if25
3.4.3 A EXPRESSÃO CONDICIONAL26
3.4.4 ifs ANINHADOS27
3.5 A DECLARAÇÃO switch28
3.5.1 A DECLARAÇÃO break29
3.5.2 DECLARAÇÕES switch ANINHADAS30
3.6 LAÇOS DE REPETIÇÃO33
3.7 O LAÇO for33
3.7.1 VARIÁVEIS DO LAÇO for35
3.7.4 USANDO LAÇOS for SEM CONTEÚDO38
3.8 O LAÇO while38
3.9 O LAÇO do-while40
3.10 LAÇOS ANINHADOS41
3.1 QUEBRANDO UM LAÇO43
3.12 A DECLARAÇÃO CONTINUE44
3.13 RÓTULOS E goto45
UNIDADE 4 – VETORES, MATRIZES E STRINGS47
4.1 INTRODUÇÃO47
4.2 DECLARAÇÃO DE VETORES UNIDIMENSIONAIS47
4.3 CADEIAS DE CARACTERES (STRINGS)49
4.4 DECLARAÇÃO DE VETORES MULTIDIMENSIONAIS (MATRIZES)51
4.5 VETORES DE CADEIAS DE CARACTERES52
4.6 INICIALIZAÇÃO DE VETORES53
4.7 LIMITES DE VETORES E SUA REPRESENTAÇÃO EM MEMÓRIA54
UNIDADE 5 – APONTADORES (PONTEIROS)56
5.1 PONTEIROS SÃO ENDEREÇOS56
5.2 VARIÁVEIS PONTEIRO57
5.3 OS OPERADORES DE PONTEIROS57
5.4 IMPORTÂNCIA DO TIPO BASE59
5.5 EXPRESSÕES COM PONTEIROS59
5.5.1 ATRIBUIÇÃO DE PONTEIROS59
5.5.2 ARITMÉTICA COM PONTEIROS60
5.5.3 COMPARAÇÃO COM PONTEIROS61
5.6 PONTEIROS E MATRIZES61
5.6.1 INDEXANDO UM PONTEIRO63
5.6.2 PONTEIROS E STRINGS63
5.6.3 OBTENDO O ENDEREÇO DE UM ELEMENTO DA MATRIZ64
5.6.4 MATRIZES DE PONTEIROS64
5.6.5 PROGRAMA EXEMPLO: TRADUTOR INGLÊS-PORTUGUÊS65
5.7 PONTEIROS PARA PONTEIROS69
5.8 INICIALIZANDO PONTEIROS70
5.9 PROBLEMAS COM PONTEIROS72
UNIDADE 6 – TIPOS DE DADOS DEFINIDOS PELO USUÁRIO74
6.1 ESTRUTURAS74
6.1.1 REFERENCIANDO OS CAMPOS DA ESTRUTURA75
6.1.2 MATRIZES DE ESTRUTURAS75
6.1.3 ATRIBUINDO ESTRUTURAS76
6.1.4 PASSANDO ESTRUTURAS PARA FUNÇÕES76
6.1.5 PONTEIROS PARA ESTRUTURAS78
6.1.6 MATRIZES E ESTRUTURAS DENTRO DE ESTRUTURAS81
6.2 UNIÕES82
6.3 ENUMERAÇÕES83
6.4 typedef86
UNIDADE 7 – ESTUDO DETALHADO DE FUNÇÕES87
7.1 FORMA GERAL DE UMA FUNÇÃO87
7.2 A DECLARAÇÃO return87
7.2.1 RETORNANDO DE UMA FUNÇÃO88
7.2.2 RETORNANDO UM VALOR88
7.3 FUNÇÕES RETORNANDO VALORES NÃO-INTEIROS90
7.4 REGRAS DE ESCOPO DE FUNÇÕES93
7.4.1 VARIÁVEIS LOCAIS94
7.4.2 PARÂMETROS FORMAIS96
7.4.3 VARIÁVEIS GLOBAIS96
7.5 ARGUMENTOS E PARÂMETROS DE FUNÇÕES98
7.5.1 CHAMADA POR VALOR, CHAMADA POR REFERÊNCIA98
7.5.2 CRIANDO UMA CHAMADA POR REFERÊNCIA99
7.5.3 CHAMANDO FUNÇÕES COM MATRIZES100
7.5.4 OS ARGUMENTOS argc, argv PARA A FUNÇÃO main( ):103
7. 6 FUNÇÕES RECURSIVAS104
UNIDADE 8 – ARQUIVOS107
8.1 INTRODUÇÃO107
8.2 O PONTEIRO DE ARQUIVO107
8.3 ABRINDO UM ARQUIVO108
8.4 ESCREVENDO UM CARACTERE NUM ARQUIVO110
8.5 LENDO UM CARACTERE DE UM ARQUIVO110
8.6 USANDO A FUNÇÃO feof( )110
8.7 FECHANDO UM ARQUIVO111
8.9 USANDO fopen( ), getc( ), putc( ) E fclose( )112
8.10 fgets( ) E fputs( )113
8.1 fread( ) E fwrite( ):13
8.12 ACESSO RANDÔMICO A ARQUIVOS: fseek( )116
8.13 fprintf( ) E fscanf( )116
8.14 APAGANDO ARQUIVOS: remove( )118
8.15 PROGRAMA EXEMPLO: MANIPULAÇÃO DE ARQUIVOS119
9.1 INTRODUÇÃO126
9.1.1 OBJETOS126
9.1.2 POLIMORFISMO127
9.1.3 HERANÇA127
9.2 CONSIDERAÇÕES FUNDAMENTAIS SOBRE O C++127
9.3 COMPILANDO UM PROGRAMA C++128
9.4 INTRODUÇÃO A CLASSES E OBJETOS128
9.5 SOBRECARGA DE FUNÇÕES132
9.6 SOBRECARGA DE OPERADOR134
9.7 HERANÇA134
9.8 CONSTRUTORES E DESTRUTORES138
9.9 FUNÇÕES FRIEND140
9.10 A PALAVRA RESERVADA this144

UNIDADE 1 – CONSIDERAÇÕES INICIAIS SOBRE A LINGUAGEM C 1.1 AS ORIGENS DO C/C++

A história do C/C++ começa nos anos 70 com a invenção da linguagem C.

A linguagem C foi inventada e implementada pela primeira vez por Dennis Ritchie em um DEC PDP-1, usando o sistema operacional UNIX. A linguagem C é o resultado do processo de desenvolvimento iniciado com outra linguagem, chamada BCPL, desenvolvida por Martin Richards. Esta linguagem influenciou a linguagem inventada por Ken Thompson, chamado B, a qual levou ao desenvolvimento da linguagem C.

A linguagem C tornou-se uma das linguagens de programação mais usadas. Flexível, ainda que poderosa, a linguagem C tem sido utilizada na criação de alguns dos mais importantes produtos de software dos últimos anos. Entretanto, a linguagem encontra seus limites quando o tamanho de um projeto ultrapassa um certo ponto. Ainda que este limite possa variar de projeto para projeto, quanto o tamanho de um programa se encontra entre 25.0 e 100.0 linhas, torna-se problemático o gerenciamento, tendo em vista que é difícil compreende-lo como um todo. Para resolver este problema, em 1980, enquanto trabalhava nos laboratórios da Bell, em Murray Bill, New Jersey, Bjarne Stroustrup acrescentou várias extensões à linguagem C e chamou inicialmente esta nova linguagem de “C com classes”. Entretanto, em 1983, o nome foi mudado para C++.

Muitas adições foram feitas pós-Stroustrup para que a linguagem C pudesse suportar a programação orientada a objetos, às vezes referenciada como POO. Stroustrup declarou que algumas das características da orientação a objetos do C++ foram inspiradas por outra linguagem orientada a objetos chamada de Simula67.

A linguagem C é freqüentemente referenciada como uma linguagem de nível médio, posicionando-se entre o assembler (baixo nível) e o Pascal (alto nível)1. Uma das razões da invenção da linguagem C foi dar ao programador uma linguagem de alto nível que poderia ser utilizada como uma substituta para a linguagem assembly.

Como você provavelmente sabe, a linguagem assembly utiliza a representação simbólica das instruções executadas pelo computador. Existe um relacionamento de um para um entre cada instrução da linguagem assembly e a instrução de máquina. Ainda que este relacionamento possibilite escrever programas altamente eficientes, isso torna a programação um tanto quanto tediosa e passível de erro. Por outro lado, linguagens de alto nível, como Pascal, estão extremamente distantes da representação de máquina. Uma instrução em Pascal não possui essencialmente nenhum relacionamento com a seqüência de instruções de máquina que são executadas.

Entretanto, ainda que a linguagem C possua estruturas de controle de alto nível, como é encontrado na Pascal, ela também permite que o programador manipule bits, bytes e endereços de uma maneira mais proximamente ligada à máquina, ao contrário da abstração apresentadas por outras linguagens de alto nível. Por esse motivo, a linguagem C tem sido ocasionalmente chamada de “código assembly de alto nível”. Por sua natureza dupla, a linguagem C permite que sejam criado programas rápidos e eficientes sem a necessidade de se recorrer a linguagem

1 SCHILDT, H. Turbo C++: guia do usuário. São Paulo : Makron Books,1992.

assembly.

A filosofia que existe por trás da linguagem C é que o programador sabe realmente o que está fazendo. Por esse motivo, a linguagem C quase nunca “colocase no caminho” do programador, deixando-o livre para usar (ou abusar) dela de qualquer forma que queira. Existe uma pequena verificação de erro de execução runtime error. Por exemplo, se por qualquer motivo você quiser sobrescrever a memória na qual o seu programa está atualmente residindo, o compilador nada fará para impedi-lo. O motivo para essa “liberdade na programação” é permitir ao compilador C criar códigos muito rápidos e eficientes, já que ele deixa a responsabilidade da verificação de erros para você. Em outras palavras, a linguagem C considera que você é hábil o bastante para adicionar suas próprias verificações de erro quando necessário.

Quando C++ foi inventado, Bjarne Stroustrup sabia que era importante manter o espírito original da linguagem C, incluindo a eficiência, a natureza de nível médio e a filosofia de que o programador, não a linguagem, está com as responsabilidades, enquanto, ao mesmo tempo, acrescentava o suporte à programação orientada a objetos. Assim, o C++ proporciona ao programador a liberdade e o controle da linguagem C junto com o poder dos objetos. As características da orientação a objetos em C++, usando as palavras de Stroustrup, “permite aos programas serem estruturados quanto à clareza e extensibilidade, tornando fácil a manutenção sem perda de eficiência”.

1.2 COMPILADORES E INTERPRETADORES

Os termos compilador e interpretador referem-se à maneira pela qual um programa é executado. Na teoria, qualquer linguagem de programação pode ser tanto compilada como interpretada, mas algumas linguagem são usualmente executadas de uma forma ou de outra. Por exemplo, o BASIC geralmente é interpretado e o C++, compilado. A maneira como um programa é executado não é definida pela linguagem na qual ele é escrito. Tanto compiladores como interpretadores são simplesmente programas sofisticados que agem sobre o códigofonte do seu programa.

Um interpretador lê o código-fonte do seu programa uma linha por vez e executa uma instrução específica contida naquela linha. O interpretador deverá estar presente toda vez que o programa estiver sendo executado.

Um compilador lê o programa inteiro e converte-o em um código executável. O código executável também é referenciado como código objeto, binário ou de máquina. Entretanto, neste contexto, o termo objeto não tem nenhuma relação com os objetos definidos em um programa C++. Uma vez o programa compilado, uma linha de código-fonte está significativamente distante do código executável. O compilador não é necessário para executar o programa, desde que ele já esteja compilado.

Existem dois termos que você verá freqüentemente: tempo de compilação e tempo de execução. O termo tempo de compilação refere-se aos eventos que acontecem durante o processo de compilação e tempo de execução, aos eventos que ocorrem enquanto o programa está sendo executado. Infelizmente, você verá constantemente esses termos relacionados a mensagens de erros, como em erros de tempo de compilação e erros de tempo de execução. Mas, por sorte, após adquirir experiência na programação em C/C++, você verá essas mensagens raras vezes.

1.3 WARNINGS E ERROS

A linguagem C foi projetada para ser uma linguagem bastante tolerante e para permitir que qualquer coisa que sintaticamente esteja correta seja compilada. Entretanto, algumas declarações, ainda que sintaticamente corretas, são suspeitas. Quando o compilador C/C++ encontra uma situação dessas, imprime um warning (advertência). Você, como programador, decide, então, se a suspeita é justificada. Algumas vezes, mensagens de advertência falsas são geradas como um efeito colateral de um erro real, mas você indubitavelmente encontrará muitas advertências enquanto continuar a escrever programas em C.

1.4 A LINGUAGEM C/C++ É CASE-SENSITIVE

É importante saber que as letras maiúsculas e minúsculas são tratadas como caracteres distintos. Por exemplo, em algumas linguagens, os nomes de variáveis count, Count e COUNT são três maneiras de se especificar a mesma variável. Entretanto na linguagem C/C++, serão três variáveis diferentes. Então, quando você digitar programas em C/C++ seja cuidadoso na utilização correta das letras.

1.5 FUNÇÕES EM C

A linguagem C é baseada no conceito de blocos de construção. Os blocos de construção são chamados de funções. Um programa em C é uma coleção de uma ou mais funções. Para escrever um programa, você primeiro cria funções e, então, coloca-as juntas.

Em C, uma função é uma sub-rotina que contém uma ou mais declarações e realiza uma ou mais tarefas. Em programas bem-escritos, cada função realiza somente uma tarefa. Cada função tem um nome e uma lista de argumentos que receberá. Em geral, pode-se dar qualquer nome a uma função, com exceção de main, que é reservada para a função que começa a execução dos programas.

Uma convenção notacional tornou-se padrão quando se escreve sobre a linguagem C. Haverá parênteses depois do nome da função. Por exemplo, se o nome de uma função é max( ), ela será escrita como max( ) quando referenciada no texto. Essa notação ajudará você a distinguir nomes de variáveis de nomes de funções neste texto. Segue um primeiro programa exemplo em linguagem C:

#include <stdio.h> void main(){ printf (“Meu primeiro programa em C!!!\n”); }

Neste exemplo temos a função main( ) que, ao ser executada, exibirá uma mensagem na tela.

A impressão da mensagem é executada pela função printf( ) que recebe como parâmetro a mensagem “Meu primeiro programa em C!!!\n”.

A constante “\n” ao final da mensagem significa que o cursor deverá retornar ao início de uma nova linha.

Um novo programa, com o mesmo objetivo, pode ser escrito da seguinte forma:

#include <stdio.h> void hello(){ printf (“Meu primeiro programa em C!!!\n”); } void main(){ hello(); }

Neste novo programa criamos uma função hello( ), responsável por exibir a mensagem. Note que a função hello( ) foi chamada a partir da função main( ).

1.5.1 FUNÇÕES COM ARGUMENTOS

Um argumento de função é simplesmente um valor que é passado para a função no momento em que ela é chamada. Você já viu uma função que leva argumento: printf( ). Você também pode criar funções que passam argumentos. Por exemplo, a função sqr( ), neste programa, leva um argumento inteiro e mostra o seu quadrado:

#include <stdio.h> int sqr (int x){ //o parâmetro foi declarado dentro dos parênteses printf (“%d elevado ao quadrado é %d\n”, x, x * x); } void main(){ int num; num = 100; sqr(num); //chama sqr com o parâmetro num }

Como você pode ver na declaração de sqr( ), a variável x que receberá o valor passado por sqr( ) é declarada dentro dos parênteses que seguem o nome da função. Funções que não passam argumentos não necessitam de quaisquer variáveis, de maneira que os parênteses ficam vazios.

Quando sqr( ) é chamada, o valor de num – neste caso 100 – é passado para x. Desse modo, a linha “100 elevado ao quadrado é 10000” é apresentada. Você deve executar este programa para se convencer do que ele realmente faz, operando como esperado.

É importante fixar dois termos. Primeiro, o argumento refere-se ao valor que é usado para chamar uma função. A variável que recebe o valor dos argumentos usados na chamada da função é um parâmetro formal da função. Na verdade, funções que levam argumentos são chamados de funções parametrizadas. O importante é que a variável usada como argumento em uma chamada de função não tenha nada a ver com o parâmetro formal que recebe o seu valor.

Um outro exemplo de uma função parametrizada é mostrado aqui. A função mul( ) imprime o produto de dois argumentos inteiros. Note que os parâmetros para a função mul( ) são declarados usando-se uma lista separada por vírgula.

#include <stdio.h> void mul (int a, int b){ printf (“%d”, a * b); } void main(){ mul (10, 1); }

Lembre-se que o tipo de argumento usado para chamar uma função deverá ser igual ao do parâmetro formal que está recebendo o dado argumento. Por exemplo, você não deve tentar chamar a função mul( ) com dois argumentos de ponto flutuante.

1.5.2 FUNÇÕES QUE RETORNAM VALORES

Antes de deixar a discussão sobre funções, é necessário mencionar as funções que retornam valores. Muitas das funções de biblioteca que você usará retornam valores. Em C, uma função pode retornar um valor para uma rotina chamadora usado a palavra reservada return. Para ilustrar, o programa anterior, que imprime o produto de dois números, pode ser reescrito como o programa seguinte. Note que o valor de retorno é associado a uma variável, colocando-se a função do lado direito de uma declaração de atribuição.

#include <stdio.h> /* um programa com função que retorna valores*/ int mul (int a, int b){ return (a * b); } void main(){ int resposta; resposta = mul (10, 1); //atribui o valor de retorno printf (“A resposta é %d\n”, resposta); }

Nesse exemplo, a função mul( ) retorna o valor de a * b usando a declaração return. Então, esse valor é atribuído a resposta. Isto é, o valor retornado pela declaração return torna-se o valor de mul( ) na chamada de rotina.

Assim como existem tipos diferentes de variáveis, existem tipos diferentes de valor de retorno. Certifique-se de que a variável que recebe o valor de retorno de uma função seja do mesmo tipo que o valor retornado pela função. O tipo retornado pela rotina mul( ) é int. Quando não explicitamos o tipo retornado por uma função, a linguagem C assume que é um int.

É possível fazer com que uma função retorne usando-se a declaração return sem qualquer valor associada a ela, tornando o valor retornado indefinido. Também pode haver mais que um return numa função.

1.5.3 A FORMA GERAL DE UMA FUNÇÃO

A forma geral de uma função é mostrada aqui:

(Parte 1 de 10)

Comentários