Você está na página 1de 154

PROGRAMAÇÃO

PROF. ESP. FRANCISCO LUÍS


BORGHI NASCIMENTO
Diretor Geral | Valdir Carrenho Junior


A Faculdade Católica Paulista tem por missão exercer uma
ação integrada de suas atividades educacionais, visando à
geração, sistematização e disseminação do conhecimento,
para formar profissionais empreendedores que promovam
a transformação e o desenvolvimento social, econômico e
cultural da comunidade em que está inserida.

Missão da Faculdade Católica Paulista

Av. Cristo Rei, 305 - Banzato, CEP 17515-200 Marília - São Paulo.
www.uca.edu.br

Nenhuma parte desta publicação poderá ser reproduzida por qualquer meio ou forma
sem autorização. Todos os gráficos, tabelas e elementos são creditados à autoria,
salvo quando indicada a referência, sendo de inteira responsabilidade da autoria a
emissão de conceitos.
PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

SUMÁRIO
AULA 01 PARADIGMA DE PROGRAMAÇÃO ORIENTADO A 05
OBJETOS

AULA 02 SISTEMAS DISTRIBUÍDOS 14

AULA 03 ARQUITETURA CLIENTE-SERVIDOR 24

AULA 04 INTRODUÇÃO À LINGUAGEM “C” 32

AULA 05 MANIPULAÇÃO DE VARIÁVEIS LOCAIS, GLOBAIS 43


E SUPERGLOBAIS;

AULA 06 OPERADORES 52

AULA 07 ESTRUTURA DE DESVIO CONDICIONAL 64

AULA 08 ESTRUTURA DE LAÇO DE REPETIÇÃO 74

AULA 09 ESTRUTURA DE MÉTODOS/ FUNÇÕES 84

AULA 10 PASSAGEM DE ARGUMENTOS POR VALORES E 93


REFERÊNCIAS

AULA 11 PRINCIPAIS FUNÇÕES DO C# 104

AULA 12 MANIPULAÇÃO DE VETORES (ARRAY) 111

AULA 13 MANIPULAÇÃO DE MATRIZES 120

AULA 14 RECURSIVIDADE, TRATAMENTO DE EXCEÇÕES 129


E PERSISTÊNCIA DE DADOS

AULA 15 INTERFACES GRÁFICAS E EVENTOS 139

FACULDADE CATÓLICA PAULISTA | 3


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

INTRODUÇÃO

Há diversas linguagens de programação no mercado. Muitas delas têm diversas


finalidades. Desde a programação para aplicações locais, aquelas que rodam no seu
computador, bem como aplicativos para celulares e programas para executar na
internet.
Neste conteúdo, vamos entender como utilizarmos a linguagem de programação
C, na sua variação C# (C – Sharp).

Fonte: https://growiz.com.br/wp-content/uploads/2020/08/kisspng-c-programming-language-logo-microsoft-visual-stud-atlas-portfolio-5b899192d
7c600.1628571115357423548838.png

Vamos entender o que é uma programação orientada a objetos, manipular variáveis,


desvios condicionais, estrutura de laços, matrizes e vetores dentro da programação.
Teremos exemplos práticos e passo a passo para instalação da ferramenta e também
realizar as atividades de forma que ajude o aprendizado e você consiga ver em tempo
real a execução dos exemplos.

FACULDADE CATÓLICA PAULISTA | 4


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 1
PARADIGMA DE PROGRAMAÇÃO
ORIENTADO A OBJETOS

A programação orientada a objetos (POO) é um dos paradigmas mais utilizados


atualmente no desenvolvimento de sistemas. Com linguagens de programação
analistas e programadores constroem classes e implementam métodos que permitem
construir programas baseados em objetos que representam o mundo real, por meio
de características, estados e comportamentos. Neste capítulo, você estudará sobre
classes, objetos e métodos no paradigma da POO.
Antes de entrarmos no conceito de POO, temos que entender um outro tipo de
programação: Programação Orientada a Procedimentos (POP). A Programação
Procedural é uma metodologia para modelar o mundo real do problema a ser resolvido,
determinando a ordem das fases a serem seguidas para que o resultado desejado seja
alcançado. Os blocos de construção são procedimentos conhecidos como “rotinas”
ou “métodos”. São segmentos de código que podem ser chamados várias vezes no
programa. Quando os procedimentos são bem projetados, eles podem ser reutilizáveis,
acelerando o processo de desenvolvimento, facilitando as modificações do sistema e
reduzindo a base de código onde os defeitos podem ocorrer. Exemplo: “Limpar Campos”
ou “Gravar Dados” podem ser chamados em qualquer parte da programação.
Já a Programação Orientada a Objeto lida com as partes básicas elementares ou
blocos de construção do problema, enquanto a programação procedural se concentra
nas etapas necessárias para produzir o resultado desejado. É uma metodologia de
programação prática e útil que incentiva o design de módulos e reutilização de software.
Um de seus principais recursos é o suporte para abstração de dados, a capacidade
de definir novos tipos de objetos cujo comportamento é definido abstratamente,
sem referência a detalhes de implementação, como a estrutura de dados usada para
representar os objetos.
A programação orientada a objetos é um importante conjunto de técnicas que
podem ser utilizadas para realizar o desenvolvimento de programas mais eficientes,
melhorando a confiabilidade dos programas de computação. Na programação orientada
a objetos, os objetos são os elementos principais de construção. Entretanto, a simples
compreensão. Em ciência da computação, um programa é composto por uma série

FACULDADE CATÓLICA PAULISTA | 5


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

de comandos, que são executados em um computador ou um circuito eletrônico. A


programação de um computador é o processo de escrever um algoritmo e é também
o processo de codificar um algoritmo em uma notação denominada como linguagem
de programação.
A POO lida sobre como as informações são representadas na mente humana. Como
uma abordagem de programação de computador, a POO é útil de forma a fornecer
uma modelagem fácil para a dinâmica da construção e desenvolvimento de entidades
reais. Esta abordagem visa modelar as entidades e, também, as relações existentes
entre eles. A POO permite que os programadores definam as classes necessárias
para criar os objetos e apliquem essas modificações (manipulações) sobre eles. Além
disso, pode fornecer recursos de herança, polimorfismo e encapsulamento para os
desenvolvedores.
De acordo com Ledgard (1996), o paradigma de programação é um estilo fundamental
de programação de computadores que classifica as linguagens de programação. A
abordagem orientada a objetos permite dividir um sistema complexo em partes menores
e em módulos gerenciáveis ​​que tornam o processo de desenvolvimento mais fácil de
entender e compartilhar entre os membros de uma equipe de desenvolvedores, e mais
fácil de se comunicar com os usuários que são necessários para fornecer requisitos e
confirmar o quão bem o sistema atende aos requisitos ao longo do processo. Assim,
a POO permite a aplicação da modularidade e abstração com maior compreensão,
manutenção e expansão do código.

ISTO ESTÁ NA REDE

A programação procedural trata de escrever procedimentos ou métodos que


realizam operações nos dados, enquanto a programação orientada a objetos trata
da criação de objetos que contêm dados e métodos. 
A programação orientada a objetos possui várias vantagens sobre a programação
procedural, como, por exemplo:  
• mais rápido e fácil de executar; 
• fornece uma estrutura clara para os programas; 
• torna o código mais fácil de manter, modificar e depurar; 
• torna possível criar aplicativos totalmente reutilizáveis ​​com menos código e
menor tempo de desenvolvimento. 
Ao longo do texto, será possível compreender o significado dos princípios da POO
– Programação Orientada a Objetos e a sua aplicação em uma linguagem de
programação (Java). 
Disponível no seguinte link: https://www.devmedia.com.br/programacao-orientada-a-objetos-com-java/18449.  

FACULDADE CATÓLICA PAULISTA | 6


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

1.1. Classes e Objetos

O conceito de classes na orientação a objetos gira em torno da abstração, que é a


definição simplificada dos objetos e apresenta informações relevantes para os usuários,
porém, esconde detalhes que são irrelevantes para determinado contexto. Na Unified
Modeling Language (UML), uma classe pode ser representada pelas especificações
nome da classe, atributos e métodos, como você pode observar a seguir:
• Nome da classe: é o identificador da classe e define o nome pelo qual a classe é
referenciada, em geral, utiliza-se apenas a primeira letra maiúscula na declaração
de uma classe.
• Atributos: é o conjunto de características da classe, isto é, os campos que
armazenam e definem as propriedades do objeto. Assim como as variáveis,
esses campos possuem um tipo, por exemplo, int, float, string, etc.
• Métodos: definem o comportamento da classe por meio das operações que ela
pode executar, ou seja, compreende as funcionalidades da classe.

Por exemplo, imagine que você comprou um carro recentemente e decide modelar
esse carro usando programação orientada a objetos. O seu carro tem as características
que você estava procurando: um motor 1.5 turbo, cinza escuro, quatro portas e câmbio
automático.
O veículo também possui comportamentos que, provavelmente, foram o motivo de
sua compra, como acelerar, desacelerar, acender os faróis, buzinar e tocar música.
Este carro novo é um objeto, em que suas características são seus atributos (dados
atrelados ao objeto) e seus comportamentos são ações ou métodos.
O carro adquirido é um objeto que te pertence, mas, na loja onde você o comprou
existiam vários outros, muito similares, com quatro rodas, volante, câmbio, retrovisores,
faróis, entre outras partes.
Observe que, apesar do seu carro ser único (por exemplo, possui um registro único no
Departamento de Trânsito), podem existir outros com exatamente os mesmos atributos,
ou parecidos, ou mesmo totalmente diferentes, mas que ainda são considerados
carros. Podemos dizer então que seu objeto pode ser classificado como um carro, e
que seu carro nada mais é que uma instância dessa classe chamada “carro”.

FACULDADE CATÓLICA PAULISTA | 7


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Fonte: https://www.alura.com.br/artigos/assets/poo-programacao-orientada-a-objetos/class-analogy.png

Note que os objetos “polo”, “mini” e “beetle” são instâncias da classe “car”. Assim,
abstraindo um pouco a analogia, uma classe é um conjunto de características e
comportamentos que definem o conjunto de objetos pertencentes à essa classe. Repare
que a classe em si é um conceito abstrato, como um molde, que se torna concreto
e palpável através da criação de um objeto. Chamamos essa criação de instanciação
da classe, como se estivéssemos usando esse molde (classe) para criar um objeto.
O algoritmo para se criar uma classe pode ser observado a seguir:

classe Carro {
Real velocidade;
Caractere modelo;

Carro(Caractere modelo) {
carro.modelo = modelo;
carro.velocidade = 0;
}

função acelerar() {
/* código do carro para acelerar */
}

função frear() {
/* código do carro para frear */
}

função acenderFarol() {
/* código do carro para acender o farol */
}
}

FACULDADE CATÓLICA PAULISTA | 8


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Note que acima estão as definições da classe. Isto é, estão feitas as declarações.
No exemplo acima temos a CLASSE. Os objetos “polo”, “mini” e “beetle” são instâncias
da classe Carro, que pode ser criado a partir do exemplo a seguir:

Tipo Obj_carro = novo(carro(‘polo‘));

Obj_carro.acelerar();

O código acima exemplifica a criação da instância “polo” do objeto Carro e executa


o método acelerar.

1.2. Encapsulamento

Ainda, no exemplo do carro, sabemos que ele possui características e comportamentos.


Os métodos do carro, como acelerar, podem usar atributos e outros métodos do carro
como o mecanismo de injeção de combustível, a coleta do combustível no tanque,
etc., uma vez que acelerar gasta combustível.

Fonte: https://www.alura.com.br/artigos/assets/poo-programacao-orientada-a-objetos/oop-car-methods-and-attributes.png

No entanto, se alguns desses atributos ou métodos forem facilmente visíveis e


modificáveis, como o mecanismo de aceleração do carro, isso pode dar liberdade
para que alterações sejam feitas, resultando em efeitos colaterais imprevisíveis. Nessa
analogia, uma pessoa pode não estar satisfeita com a aceleração do carro e modifica
a forma como ela ocorre, criando efeitos colaterais que podem fazer o carro por

FACULDADE CATÓLICA PAULISTA | 9


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

exemplo, nem andar. Nesse caso, o método de aceleração do carro não é visível por
fora do próprio carro. Na POO, um atributo ou método que não é visível de fora do
próprio objeto é chamado de “privado”; quando é visível, é chamado de “público”.

Fonte: https://www.alura.com.br/artigos/assets/poo-programacao-orientada-a-objetos/encapsulation.png

Como saber como o nosso carro acelera? Simples: não sabemos. Para acelerar,
devemos pisar no acelerador e, de resto, o objeto sabe como executar essa ação
sem expor como o faz. Neste caso, podemos afirmar que a aceleração do carro está
encapsulada, pois sabemos o que ele vai fazer ao executarmos esse método, mas
para o programa não importa como o objeto o faz, só que ele o faça.
O mesmo vale para atributos. Não se sabe como o carro demonstra qual velocidade
mostrar no velocímetro ou como ele calcula sua velocidade, mas não precisamos
saber como isso é feito, ele só precisa dar a velocidade certa.
O encapsulamento de atributos e métodos impede o chamado “vazamento de
escopo”, onde um atributo ou método é visível por alguém que não deveria vê-lo,
como outro objeto ou classe. Isso evita a confusão do uso de variáveis globais no
programa, deixando mais fácil de identificar em qual estado cada variável vai estar
a cada momento do programa, já que a restrição de acesso nos permite identificar
quem consegue modificá-la.

1.3. Herança

No exemplo, foi instanciado o objeto “carro” com os atributos que procurava.


Apesar de ser único, existem carros com exatamente os mesmos atributos ou formas
modificadas. Digamos que você tenha comprado o modelo Y, da montadora “ABC”.
Esse modelo possui uma outra versão, chamada Y+ (ou “Y plus”), que possui muitos
atributos da versão clássica, mas com diferenças bem grandes: o motor é híbrido

FACULDADE CATÓLICA PAULISTA | 10


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

(elétrico e à combustão), possui um sistema de suspensão diferente e, vamos supor


que, além disso, ele tenha um sistema de tração diferente (tração nas quatro rodas).
Não são só alguns atributos, mas também alguns mecanismos (ou métodos,
traduzindo para POO) que mudam. No entanto, essa versão “plus” ainda é do modelo
Y, ou melhor, é um tipo do modelo.

Fonte: https://www.alura.com.br/artigos/assets/poo-programacao-orientada-a-objetos/inheritance.png

Quando uma classe A é um tipo de classe B, dizemos que a classe A herda as


características da classe B, e que a classe B é mãe da classe A, estabelecendo então
uma relação de herança entre elas. No caso do carro, Y+ é um tipo de Y, e o que
muda são alguns atributos (para-lama reforçado, altura da suspensão etc.), e um
dos métodos da classe (acelerar, pois agora há tração nas quatro rodas), mas todo o
resto permanece o mesmo, e o novo modelo recebe os mesmos atributos e métodos
do modelo clássico.

ANOTE ISSO

Uma classe é a descrição de um conjunto de objetos; consta de métodos e dados


que resumem características comuns de um conjunto de objetos. Podemos definir
muitos objetos da mesma classe, ou seja, uma classe é a declaração de um tipo de
objeto (Aguilar, 2008). 

1.4. Interface

Muitos métodos dos carros são comuns em vários veículos. Tanto um carro quanto
uma motocicleta são classes cujos objetos podem acelerar, parar, acender o farol etc.,
pois são coisas comuns a automóveis. Podemos dizer, então, que ambas as classes
“carro” e “motocicleta” são “veículos”.

FACULDADE CATÓLICA PAULISTA | 11


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Quando duas ou mais classes possuem comportamentos comuns que podem


ser separados em uma outra classe, costuma-se dizer que a classe comum é uma
interface, que pode ser “herdada” pelas outras classes. Note que colocamos a interface
como classe comum, que pode ser “herdada” (com aspas), porque uma interface não
é exatamente uma classe, mas um conjunto de métodos que todas as classes que
herdarem dela devem possuir (implementar) - portanto, uma interface não é “herdada”
por uma classe, mas sim implementada.
No mundo do desenvolvimento de software, dizemos que uma interface é como
se fosse um contrato: uma classe que implementa uma interface deve fornecer uma
implementação a todos os métodos que a interface define, e em compensação, a classe
implementadora é do tipo da interface. No nosso exemplo, “carro” e “motocicleta” são
classes que implementam os métodos da interface “veículo”, logo, podemos dizer que
qualquer objeto dessas duas primeiras classes, como um carro Y ou uma motocicleta
H, são veículos.
Um pequeno detalhe: uma interface não pode ser herdada por uma classe, mas
implementada. No entanto, uma interface pode herdar de outra interface, criando uma
hierarquia de interfaces. Usando um exemplo completo com carros, dizemos que a
classe “Y+” herda da classe “Y”, que, por sua vez, herda da classe “Carro”. A classe
“Carro” implementa a interface “Veículo” que, por sua vez, pode herdar (por exemplo)
uma interface chamada “Transporte”, uma vez que, tanto um “veículo” quanto uma
“bicicleta” são meios de transporte, ainda que bicicleta não seja um automóvel.

1.5. Polimorfismo

A palavra “polimorfismo” vem do grego poli = muitas e morphos = forma. Digamos


que um dos motivos da escolha do carro foi a qualidade do sistema de som. Todavia,
digamos que a reprodução só pode ser feita via bluetooth, enquanto no veículo antigo
carro, podia ser feita apenas via pendrive. Em ambos os carros está presente o método
“tocar música”. No entanto, como o sistema de som deles é diferente, a forma como o
carro toca músicas é diferente. Neste caso, o método «tocar música» é uma forma de
polimorfismo, pois dois objetos, de duas classes diferentes, têm um mesmo método
que é implementado de formas diferentes, ou seja, um método possui várias formas,
várias implementações diferentes em classes diferentes, mas que possuem o mesmo
efeito.

FACULDADE CATÓLICA PAULISTA | 12


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

1.6. Sobrecarga

A sobrecarga de métodos é um conceito do polimorfismo que consiste basicamente


em criar variações de um mesmo método, ou seja, a criação de dois ou mais métodos
com nomes totalmente iguais em uma classe. A Sobrecarga permite que utilizemos o
mesmo nome em mais de um método contanto que suas listas de argumentos sejam
diferentes para que seja feita a sua separação.
Para entender melhor a sobrecarga, vamos pensar que estamos implementando
uma calculadora simples que some apenas dois valores do mesmo tipo por vez. Nela
teremos o método calcula que será sobrecarregado com variações de tipos de soma.
A seguir, um exemplo de sobrecarga:

classe calculadora{

Função Inteiro calcula(inteiro a, inteiro b){


retorna a+b;
}
Função Real calcula(Real a, Real b){
Retorna a+b;
}
Função Caractere calcula(Caractere a, Caractere b){
Retorna a+b;
}

Como você pode perceber, as três funções acima se chamam “calcula()”. Como o objeto
vai entender qual o método a ser utilizado? Através da passagem dos parâmetros. Exemplo:
• Se for implementado o método “calcula(1,3)” passando como parâmetro os
valores 1 e 3, o resultado dessa função será 4. O objeto entende que os valores
são do tipo “inteiro” e irá retornar a operação implementada na Função Inteiro
Calcula().
• Se for implementado o método “calcula(1.5, 3.1)”, a função retornará o número
real “4,6”.
• Finalmente, se for implementado o método “calcula(“a”,”b”)”, a função retornará o
caractere “ab”. Note que o código executado na função é o que foi determinado
na assinatura do método, isto é, os parâmetros que foram passados na função.

FACULDADE CATÓLICA PAULISTA | 13


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 2
SISTEMAS DISTRIBUÍDOS

Segundo Monteiro (2020), a principal característica do sistema distribuído é


permitir que várias funções sejam conectadas em rede para que os usuários
possam compartilhá-los. Desde uma simples impressora compartilhada em rede até
aglomerados de computadores dedicados à execução de uma aplicação em larga
escala, a disponibilidade de recursos, abstração, sistema aberto e escalabilidade geram
diversos desafios para seu desenvolvimento e sua implantação.
Um sistema distribuído tem como característica a abstração, pois os usuários não
percebem que sua aplicação está executando de tal forma. Eles não notam que partes
de um programa ou aplicação estão executando em diferentes computadores. Os
usuários podem interagir com o sistema distribuído de forma consistente e uniforme,
independentemente de onde e quando a interação ocorrer.

Fonte: https://pplware.sapo.pt/wp-content/uploads/2015/10/img0_thumb.jpg

O fato desse tipo de sistema distribuído atuar em diferentes computadores, possibilita


a expansão e o aumento da oferta de recursos físicos de processamento. Em um

FACULDADE CATÓLICA PAULISTA | 14


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

sistema distribuído, os usuários não podem ser prejudicados quando uma operação é
realizada, seja ela por indisponibilidade de recursos ou pela falha de um hardware ou
software. Quando um processo da aplicação precisa ser migrado para outro computador
ou quando um hardware é substituído para manutenção, os usuários não devem
perceber essa movimentação:

O estágio de implementação do desenvolvimento de software é


o processo de conversão de uma especificação do sistema em
um sistema executável. Sempre envolve processos de projeto e
programação de software, mas, se for usada uma abordagem
incremental para o desenvolvimento, também pode envolver o
refinamento da especificação do software.
Um projeto de software é uma descrição da estrutura do software a
ser implementado, dos modelos e estruturas de dados usados pelo
sistema, das interfaces entre os componentes do sistema e, às vezes,
dos algoritmos usados. Os projetistas não chegam a um projeto
final imediatamente, mas desenvolvem-no de forma iterativa. Eles
acrescentam formalidade e detalhes, enquanto desenvolvem seu
projeto por meio de revisões constantes para correção de projetos
anteriores.
A maioria dos softwares interage com outros sistemas de software,
incluindo o sistema operacional, o banco de dados, o middleware
e outros aplicativos. Estes formam a ‘plataforma de software’, o
ambiente em que o software será executado. Informações sobre
essa plataforma são entradas essenciais para o processo de projeto,
pois os projetistas devem decidir a melhor forma de integrá-la ao
ambiente do software. A especificação de requisitos é uma descrição
da funcionalidade que o software deve oferecer, e seus requisitos
de desempenho e confiança. Se o sistema for para processamento
de dados existentes, a descrição desses dados poderia ser incluída
na especificação da plataforma; caso contrário, a descrição dos
dados deve ser uma entrada para o processo de projeto, para que a
organização dos dados do sistema seja definida. (SOMMERVILLE,
2011, p. 25).

Por exemplo, um sistema que suporta um processamento automático de pedidos,


os usuários do departamento de vendas podem estar distribuídos por todo país e os
pedidos são feitos de notebooks ou celulares conectados através da rede. Estes pedidos
chegam, são processados e enviados automaticamente para algum setor disponível.
Os usuários não sabem por onde os pedidos navegam pelo sistema, mas para os
usuários, o sistema parece que opera com um único banco de dados centralizado.

FACULDADE CATÓLICA PAULISTA | 15


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Fonte: Monteiro 2020

Diferentes tipos de entidades computacionais, controladas por diferentes S.O. e


conectadas por diferentes tipos de rede podem compor um sistema distribuído. Os
protocolos de rede são usados para tornar a comunicação entre essas entidades
transparente. No entanto, algumas aplicações requerem o uso de um Middleware para
assegurar a coerência na comunicação.
O Middleware é um conjunto de funcionalidades e padronizações que atua entre
a aplicação e a plataforma, oferecendo uma abstração para a comunicação e
representação dos dados, permitindo que diferentes aplicações rodando em diferentes
plataformas se comuniquem de forma transparente em um sistema distribuído.

ISTO ACONTECE NA PRÁTICA

Um sistema distribuído é o conjunto de computadores autônomos conectados


por meio de uma rede de comunicação e que se comunicam por meio de
mensagens. Os diferentes processadores têm sua própria memória local. Eles usam
um middleware de distribuição, que ajudam no compartilhamento de diferentes
recursos e capacidades para fornecer aos usuários uma rede coerente única e
integrada. A computação distribuída é um campo da ciência da computação que
estuda sistemas distribuídos e o programa de computador executado em um
sistema distribuído é chamado de programa distribuído. Um sistema distribuído
requer componentes simultâneos, rede de comunicação e um mecanismo de
sincronização. Um sistema distribuído permite o compartilhamento de recursos,
incluindo software por sistemas conectados à rede. 

FACULDADE CATÓLICA PAULISTA | 16


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

2.1 Disponibilidade de Recursos

O sistema distribuído precisa ser capaz de tornar os recursos técnicos acessíveis aos
usuários e permitir o compartilhamento de maneira eficiente e controlada. Um recurso
pode ser uma impressora, um computador, dados, internet, entre outros. Compartilhar
recursos é uma forma mais econômica de lidar com eles.
Por exemplo, em vez de todas as pessoas de uma família contratarem um serviço
de streaming individualmente, é mais barato fazer um único contrato, pois, em razão
dos diferentes padrões de comportamento de uso da plataforma, a maior parte do
tempo eles não estarão usando a capacidade total contratada.
A internet é um claro exemplo da facilidade de conectar usuários e recursos, tornando
a colaboração e a troca de informações (arquivos, documentos, áudios e/ou vídeos)
mais fáceis. No entanto, é um fator que gera preocupação quanto à segurança nos
sistemas distribuídos. É preciso se ter garantias de que a troca de informações é
segura e o indivíduo é realmente quem acusa ser.

2.2. Tipos de sistemas distribuídos

2.2.1 Sistemas Computacionais Distribuídos

São construídos para tarefas que necessitam de alto desempenho computacional.


Segundo Tanenbaum(2007) apud Monteiro(2020), podem ser subdivididos em clusters
computacionais e grades computacionais. Os clusters computacionais possuem uma
coleção de computadores dedicados e ligados por meio de uma rede de interconexão
de alta velocidade, tornando-se popular quando as estações de trabalho diminuíram de
preço e aumentaram seu desempenho. Assim, a construção de máquinas superpotentes
passou a ser atrativa do ponto de vista financeiro e técnico. Normalmente esses
sistemas são usados para programação em paralelo, na qual um único programa de
computação intensiva pode ser executado em múltiplas máquinas.

Fonte: Monteiro 2020

FACULDADE CATÓLICA PAULISTA | 17


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

A ilustração acima é um exemplo baseado em sistemas operacionais Linux. Cada


nodo possui instalado um mesmo SO local e estão conectados com o mesmo tipo
de rede. Esses nodos são controlados e gerenciados pelo nodo mestre, responsável
por alocar os nodos auxiliares para um determinado programa paralelo, gerenciar
uma fila de lotes de trabalhos e oferecer uma interface de sistema para os usuários
interagirem. Dessa forma, o mestre atua como se fosse um middleware para a execução
de programas e o gerenciamento do cluster, ao passo que os nodos auxiliares precisam
apenas do sistema.
A arquitetura em grade pode ser organizada em camadas. O nível 1 oferece uma
interface para reservar os recursos locais de um site. O segundo nível é a de abstração
e envolve oferecer protocolos de comunicação para suportar as transações da grade,
as quais permitem o uso de múltiplos recursos. Na camada de nível 3, o sistema é
responsável por gerenciar múltiplos recursos e usuários, como serviços de descoberta
de recursos, alocação e escalonamento de tarefas para múltiplos recursos, replicação
de dados, entre outros. O nível 4 é a camada de aplicação, na qual, dentro de uma
organização virtual, as aplicações executam em um ambiente de grade computacional.

2.2.2. Sistemas de informações distribuídos

Permite que um sistema se comunique com outro de forma transparente, normalmente


é acessado por meio de um navegador ou aplicativo que se comunica com um provedor.
Além disso, diversos tipos de dispositivos podem se conectar à internet e acessar esse
serviço. Os dados e o processamento ficam do lado do provedor enquanto os clientes
enviam requisições que, depois de processadas, são devolvidas ao cliente. Toda essa
operação deve ocorrer, preferencialmente, de maneira transparente ao usuário.

Fonte: Monteiro 2020

FACULDADE CATÓLICA PAULISTA | 18


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

A ilustração acima demonstra um cenário clássico de um sistema de informação


distribuído, que precisa lidar com várias transações vindas de diferentes clientes e
distribui-las para servidores. As informações, então, são armazenadas ou consultadas
e o monitoramento do processamento de transações é necessário para permitir que
uma aplicação do cliente consiga acessar múltiplos bancos de dados (Monteiro 2020).

2.3. Tipos de sistemas distribuídos

Um sistema distribuído deve possuir as seguintes características para entregar o


máximo de desempenho para os usuários:
• Tolerante a Falhas: consiste em um grande número de hardware e módulos
de software que estão fadados a falhar a longo prazo. Os sistemas devem ser
capazes de se recuperar de falhas de componentes sem realizar ações errôneas.
O objetivo é evitar falhas no sistema, mesmo na presença de falhas para fornecer
um serviço ininterrupto. Um sistema é considerado tolerante a falhas se puder
mascarar a presença de falhas. A confiabilidade de um sistema é definida como
a probabilidade de que o sistema sobrevive até aquele momento. Normalmente,
a tolerância a falhas é obtida fornecendo redundância.
• Escalonável: três técnicas são empregadas para gerenciar escala: replicação,
distribuição e armazenamento em cache:
ം Replicação cria várias cópias de recursos. Seu uso em nomenclatura,
autenticação e serviços de arquivo reduzem a carga em servidores individuais
e aumentam a confiabilidade e disponibilidade dos serviços como um todo.
As duas questões importantes de replicação são a colocação das réplicas
e os mecanismos pelos quais são mantidas de forma consistente. Se um
serviço está sendo replicado para reduzir os atrasos da rede quando o
serviço é acessado, as réplicas são espalhadas pelo sistema. Se a maioria
dos usuários é local, e se o serviço está sendo replicado para melhorar
sua disponibilidade ou para distribuir a carga por vários servidores, então
as réplicas podem ser colocadas perto uma da outra. Se uma mudança
for feita no objeto, a mudança deve ser perceptível para todos no sistema.
Por exemplo, o sistema envia as atualizações para qualquer réplica, e essa
réplica encaminha a atualização para as outras conforme elas se tornam
disponíveis.

FACULDADE CATÓLICA PAULISTA | 19


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ം A distribuição, outro mecanismo de gerenciamento de escala em sistemas


distribuídos, permite que as informações mantidas por um serviço distribuído
sejam estendidas a vários servidores. Distribuir dados em vários servidores
reduz o tamanho do banco de dados que deve ser mantido por cada servidor,
reduzindo o tempo necessário para pesquisar o banco de dados. A distribuição
também distribui a carga entre os servidores, reduzindo o número de
solicitações que são tratadas por cada um. No sistema estruturado em árvore,
se as cópias em cache estiverem disponíveis em servidores subordinados,
os níveis superiores podem ser evitados.
ം Armazenamento em cache é outra técnica importante para a construção
de sistemas escaláveis, pois diminui a carga nos servidores e na rede. Os
dados em cache podem ser acessados ​​mais rapidamente do que se um
novo pedido for feito. A diferença entre replicação e cache é que os dados
em cache são dados de curto prazo. Em vez de propagar as atualizações
em dados em cache, a consistência é mantida anulando os dados em cache
quando a consistência não pode ser garantida. A cache geralmente é realizada
pelo cliente, reduzindo as solicitações frequentes para os serviços de rede.
O armazenamento em cache também pode ocorrer nos servidores que
executam esses serviços. Ler um arquivo da cópia em cache da memória
no servidor de arquivos é mais rápido do que o ler no disco local do cliente.
• Desempenho previsível: várias métricas de desempenho, como tempo de
resposta (tempo decorrido entre o final de uma consulta ou demanda em um
sistema de computador e o início de uma resposta), throughput (a taxa em
que uma rede envia ou recebe os dados), utilização do sistema, capacidade da
rede etc. são empregadas para avaliar a atuação. O desempenho previsível é
a capacidade de fornecer a capacidade de resposta desejada em tempo hábil.
• Abertura: garante que um subsistema esteja continuamente aberto para a
interação com outros sistemas. Os serviços da Web são sistemas de software
projetados para suportar a interação interoperável entre as máquinas em uma
rede. Esses protocolos permitem que os sistemas distribuídos sejam estendidos e
escalados. Um sistema distribuído independente da heterogeneidade do ambiente
subjacente, como as plataformas de hardware e software alcançam a propriedade
de abertura. Portanto, todo serviço é igualmente acessível a todos os clientes
(locais ou remotos) do sistema. A implementação, instalação e depuração

FACULDADE CATÓLICA PAULISTA | 20


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

de novos serviços não deve ser muito complexa em um sistema que possui
característica de abertura.
• Segurança: os sistemas distribuídos devem permitir a comunicação entre
programas/ usuários/ recursos em diferentes computadores, reforçando os
arranjos de segurança necessários. Os recursos de segurança têm como
objetivo principal fornecer confidencialidade, integridade e disponibilidade.
Confidencialidade (privacidade) é a proteção contra divulgação a pessoas
não autorizadas. A violação da confidencialidade varia do desconfortável ao
catastrófico. A integridade fornece proteção contra alteração e corrupção.
A disponibilidade mantém o recurso acessível. Muitos incidentes de hacking
comprometem a integridade dos bancos de dados e outros recursos. Ataques de
“negação de serviço” são ataques contra a disponibilidade. Outras preocupações
de segurança importantes são o controle de acesso e o não-repúdio. Mantendo o
controle de acesso, os usuários poderão acessar apenas os recursos e serviços
a que têm direito. O não-repúdio fornece proteção contra a negação por uma
das entidades envolvidas em uma comunicação. Os mecanismos de segurança
colocados em prática devem garantir o uso adequado de recursos por diferentes
usuários no sistema.
• Transparência: os sistemas distribuídos devem ser percebidos pelos usuários e
pelos desenvolvedores como um todo, e não como uma coleção de componentes
cooperativos. As localizações dos sistemas de computador envolvidos nas
operações, replicação de dados, descoberta de recursos de vários sites, falhas,
recuperação de sistema etc. são ocultados dos usuários. A transparência oculta
a natureza distribuída do sistema de seus usuários e mostra ao usuário que o
sistema está aparecendo e funcionando normalmente. A transparência pode
ser empregada de diferentes maneiras em um sistema distribuído, como segue:
ം Transparência de acesso facilita para os usuários de um sistema distribuído
o acesso local e recursos remotos usando operações idênticas (por exemplo,
navegação na web).
ം Transparência de localização descreve nomes usados para
​​ identificar recursos
de rede (por exemplo, o endereço IP) independentemente da localização do
usuário e do recurso. Em outras palavras, a transparência da localização
facilita ao usuário acessar recursos de qualquer lugar da rede sem saber
onde o recurso está localizado. Um arquivo pode estar no próprio PC do
usuário ou a milhares de quilômetros de distância em outros servidores.

FACULDADE CATÓLICA PAULISTA | 21


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ം Transparência de simultaneidade permite que vários processos operem


simultaneamente usando objetos de informação compartilhados sem
interferência entre eles (por exemplo: a rede de caixas automáticos). Os
usuários não perceberão a existência de outros usuários no sistema (mesmo
que acessem os mesmos recursos).
ം Transparência de replicação permite que o sistema faça cópias adicionais
de arquivos e outros recursos para fins de desempenho e/ ou confiabilidade,
sem que os usuários percebam. Se um recurso é replicado entre vários locais,
ele deve aparecer para o usuário como um único recurso (por exemplo,
espelhamento - sites espelho geralmente são usados para oferecer várias
fontes das mesmas informações como uma forma de fornecer acesso
confiável a grandes downloads).
ം Transparência de falhas permite que os aplicativos concluam suas tarefas,
apesar das falhas que ocorrem em certos componentes do sistema. Por
exemplo, se um servidor falhar, os usuários devem ser redirecionados
automaticamente para outro servidor e o usuário nunca deve perceber a
falha (esse processo diz-se que o sistema mostra alta transparência de
falha). A transparência de falhas é um dos tipos de transparência mais
difíceis de realizar, uma vez que é difícil determinar se um servidor realmente
falhou, ou se está simplesmente respondendo muito lentamente. Além disso,
geralmente é inviável alcançar transparência total de falhas em um sistema
distribuído, uma vez que as redes não são confiáveis.
ം Transparência da migração facilita os recursos para mover de um local
para outro sem ter seus nomes mudados (por exemplo: páginas da Web).
Os usuários não devem ser informados (estar cientes) se um recurso ou
entidade de computação possui a capacidade para mudar de um local físico
ou lógico diferente.
ം Transparência de desempenho garante que a variação de carga não deve levar
à degradação do desempenho. Isso pode ser alcançado por reconfiguração
automática como resposta às mudanças da carga (por exemplo: distribuição
de carga).
ം Transparência da escalabilidade permite que o sistema permaneça eficiente,
mesmo com um aumento significativo no número de usuários e recursos
conectados (por exemplo, World-Wide-Web, banco de dados distribuído).

FACULDADE CATÓLICA PAULISTA | 22


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ISTO ESTÁ NA REDE

Na palestra “Raciocinando sobre sistemas distribuídos”, o profissional Renan


Ranelli (engenheiro de software e consultor independente) apresenta temas
importantes, como: consistência, disponibilidade, deploy, arquiteturas de dados,
redes, relógios, testes e performance. Ao longo da palestra discute acerca do
desenvolvimento e gestão dos sistemas distribuídos e trata sobre computação
ponto a ponto e redes de sensores. Ao final, é possível refletir sobre arquiteturas
que refletem o progresso feito na organização de sistemas distribuídos, além de
apresentar sistemas descentralizados e computação ponto a ponto. Disponível
em: https://www.infoq.com/br/presentations/raciocinando-sobre-sistemas-
distribuidos/.

FACULDADE CATÓLICA PAULISTA | 23


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 3
ARQUITETURA
CLIENTE-SERVIDOR

A arquitetura de processos colabora com a identificação de suas responsabilidades


no sistema, a verificação de cargas de trabalhos e a identificação de falhas de forma
mais isolada. Classificam-se os processos como:
• Cliente: processos que, em geral, acessam os recursos oferecidos pelo sistema
e realizam solicitações;
• Servidor: processos que aceitam os pedidos e processam os respectivos serviços
solicitados pelos clientes.

Tanto clientes como servidores podem ser diferentes componentes, como clientes,
web services, clusters, grades, entre outros (Monteiro, 2020).

Para tornar os modelos físicos para sistemas distribuídos vistos até agora mais
concretos, apresentaremos em detalhes os protocolos utilizados no modelo cliente/
servidor. Esse modelo se trata de um estilo arquitetônico de ampla utilização nos
projetos físicos de sistemas distribuídos.

Fonte: https://i1.wp.com/4.bp.blogspot.com/_xVuusqQvFWI/S83DmWhrrzI/AAAAAAAAAC4/NPWIkf0MYBo/s1600/ClienteServidor.png

FACULDADE CATÓLICA PAULISTA | 24


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Uma das principais características é a centralização de recursos. Sua ideia geral


é acessar e concorrer por recursos compartilhados, portanto, os processos clientes
interagem com os processos servidores, localizados fisicamente em distintos
computadores hospedeiros. Os recursos compartilhados providos pelo sistema são
gerenciados pelos processos servidores.
Os processos se comunicam através de premissas sobre a troca de mensagens
que ocorre entre os componentes em um nível considerado baixo. Um protocolo
é necessário para que todos os dispositivos e elementos de uma rede possam se
entender, independentemente do sistema, da aplicação utilizada ou, até mesmo, dos
fabricantes dos componentes. Os dispositivos precisam trocar mensagens a partir
de uma determinada linguagem, denominada “protocolo”.

3.1. Protocolos

No cenário base cliente/ servidor, existem os protocolos da camada de transporte


de redes de computadores: User Data Procol (UDP) e Transmission Control Protocol
(TCP). Os protocolos fornecem uma relação de comunicação por meio de troca de
mensagens entre processo remetente e processo destinatário.

3.1.1. Protocolo UDP

Tem como característica a falta de confiabilidade. Isso significa que, através da


utilização desse protocolo, pode-se enviar datagramas de uma máquina à outra, mas
sem garantia de que os dados enviados chegarão intactos e na ordem correta.

Fonte: adaptado de https://nordvpn.com/wp-content/uploads/2020/09/TCP_vs_UDP_02_BR.gif

FACULDADE CATÓLICA PAULISTA | 25


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

O UDP é um protocolo que não é voltado à conexão. Isso significa que o “aperto
de mão”, ou, tecnicamente, handshake, não é necessário para que se estabeleça uma
comunicação. Dessa forma, com o UDP é possível enviar, pela mesma saída, dados
para diversas máquinas diferentes sem problema algum.
Imagine uma transmissão de rádio. A transmissora (servidor) transmite o sinal sem
saber se os receptores (terminais) estão recebendo corretamente. Se houver uma perda
de sinal nesse intervalo, a transmissão não será interrompida. A falta de confiabilidade
dele fez com que as mensagens enviadas se corrompessem de diversas formas. Tais
características podem parecer contra produtivas no geral, mas elas formam um outro
atributo que dá muito poder ao protocolo: a velocidade. No geral, o protocolo UDP
permite uma comunicação bastante rápida, o que é muito vantajoso.
Altas velocidades, mas com baixa confiabilidade, ainda parecem suspeitas, porém,
o UDP tem sua grande vantagem quando se trata de serviços cuja velocidade é
fundamental e a perda mínima de dados não muito desvantajosa. Um exemplo é
com streaming de vídeos, em que é normal alguns bytes se perderem na comunicação,
mas é sempre importante que a aplicação continue rodando com rapidez (sem se
importar tanto com as perdas e falhas), para que não ocorra o lag.

3.1.2. Protocolo TCP

O protocolo TCP é, talvez, o mais utilizado na camada de transporte para aplicações


na Web. Diferente do UDP, o TCP é voltado à conexão e tem como garantia a integridade
e ordem de todos os dados. Para manter a confiabilidade dos dados, o TCP utiliza
um aperto de mãos de três vias, o three way handshake, também chamado de SYN,
SYN-ACK, ACK.
O nome SYN, SYN-ACK, ACK é uma resumida descrição de como esse handshake
funciona. A conexão entre dois hosts começa com o primeiro enviando ao segundo
um pacote de sincronização. O segundo host recebe esse pacote e responde com a
confirmação da sincronização (SYNchronize-ACKnowledgment). O primeiro host, por
fim, manda uma confirmação (ACKnowledge) para o segundo, assim estabelecendo
a conexão.
Com o TCP há uma conexão entre um ponto e outro, comumente chamados de
servidor e cliente. É interessante notar que o TCP permite o envio simultâneo de dados
de ambos os pontos ao outro, durante todo o fluxo de comunicação.

FACULDADE CATÓLICA PAULISTA | 26


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Fonte: https://upload.wikimedia.org/wikipedia/commons/f/f5/Comunica%C3%A7%C3%A3o_TCP_cliente_servidor.png

Desse modo, o TCP é ideal para casos em que a confiabilidade dos dados é essencial,
como quando se trata de mensagens de texto. Trocando o uso do UDP pelo TCP a
confiabilidade aumenta, mesmo que com uma velocidade possivelmente um pouco
menor. O importante é que a troca de dados seja efetuada com sucesso, de modo
que quem está se comunicando consiga se entender.

3.1.3. UDP ou TCP?

Não existe um protocolo certo ou errado, nem um melhor ou pior que outro. O que
existe são situações diferentes. Essa é a chave para trabalhar com aplicações que
se comunicam com diferentes máquinas. Entendemos algumas das diferenças entre
os dois principais protocolos da camada de transporte dos modelos da Internet: o
UDP e o TCP. Assim, entendemos a importância de ambos os protocolos e quando
devemos preferir um ou outro.
Podemos entender que o UDP serve melhor casos em que a integridade constante
dos dados não é essencial (é menos importante que a velocidade da comunicação),
como em livestreams de vídeos e jogos on-line. Por outro lado, o TCP funciona melhor em

FACULDADE CATÓLICA PAULISTA | 27


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

casos que a confiabilidade do transporte de dados é o foco, como quando trabalhamos


com comunicação em texto ou com documentos. O mais importante, portanto, é
entender as diferenças entre os protocolos e, assim, saber qual utilizar em cada caso.
Assim, teremos uma aplicação mais funcional.

3.2. Processos Cliente/Servidor em Sistemas Distribuídos

3.2.1. Clientes

A principal tarefa de uma máquina cliente é prover meios de interação entre usuários
e seus servidores remotos. Para isso, existem duas estratégias possíveis: para cada
serviço remoto, a máquina cliente permitir o contato com o serviço via rede. Um
exemplo típico dessa estratégia é uma agenda executando no smartphone de um
cliente, que precisa estar devidamente sincronizada com uma agenda remota. Essa
agenda está possivelmente compartilhada, portanto, a sincronização será efetivada
por um protocolo de nível de aplicação.

Fonte: Monteiro 2020

Já a segunda estratégia visa apresentar uma solução neutra, ou seja,


independentemente de aplicação, por exemplo, nas quais a máquina cliente é utilizada
apenas como um terminal, sem a necessidade de armazenamento local, que repassa
os comandos para que tudo seja executado e armazenado no servidor.

FACULDADE CATÓLICA PAULISTA | 28


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Fonte: Monteiro, 2020

Nessa estratégia é importante fornecer as informações sobre a interface do usuário,


mas que não tenha conhecimento de qual(is) servidor(es) ele está se conectando. É
de extrema relevância que a implantação do cliente oculte a comunicação que ocorre
com o servidor e mantenha um dos principais desafios de sistemas distribuídos:
a transparência de acesso. Essa abordagem, que consiste em terminais clientes
minimizados tem atenção crescente à medida que a conectividade da internet cresce
e dispositivos móveis estão cada vez potentes.
Segundo Monteiro (2020), a literatura apresenta outro modelo importante em
relação aos clientes, que considera o software como muito mais do que apenas uma
interface com o usuário. É possível ter parte do processamento em uma aplicação
sendo executada no lado do cliente. Esse modelo é chamado de software cliente/
servidor formado por dispositivos que abrangem software em cliente embarcado,
como caixas eletrônicos, leitores de código de barras e decodificadores de televisões.
Nessa modelagem, as interfaces de usuários são consideradas uma pequena parte
do software cliente, em contraste com as facilidades de processamento local e
comunicação.

3.2.2. Servidores

Em um servidor há a espera por uma requisição de um cliente. A seguir, garante-


se que a solicitação seja atendida e, depois disso, espera o próximo chamado. Um
servidor implementa um serviço específico em nome de uma coleção de clientes.
Os servidores podem ser iterativos ou concorrentes. Um servidor iterativo gerencia
as requisições e retorna o resultado ao cliente solicitante. Já um concorrente pode

FACULDADE CATÓLICA PAULISTA | 29


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ser implementado com processos filhos em que a manipulação das requisições são
papéis desempenhados separadamente pelos processos inerentes ao mesmo servidor.
Dessa forma, cada processo que gerencia as requisições é responsável por enviar a
resposta ao cliente solicitante.
Servidores concorrentes podem lidar com várias solicitações. Nesse sentido, pode-se
dizer que, uma vez considerada a implementação de um servidor com os processos,
o sistema atende às requisições separadamente. Outra questão interessante é como
os clientes entram em contato com um servidor. Em geral, eles enviam solicitações
para uma porta, na qual o servidor está executando e aguardando requisições, onde
cada servidor escuta em uma porta específica. Neste caso, os clientes precisam saber
previamente qual(is) a(s) porta(s) que o servidor está executando. Geralmente, serviços
conhecidos atenderem em portas padrão.

Fonte: Monteiro (2020)

Um cluster de servidores é um conjunto de máquinas interconectadas via rede,


em que, cada máquina pode executar um ou mais servidores simultaneamente. A
estrutura típica de um cluster é organizada em três camadas, conforme demonstrado
a seguir:

FACULDADE CATÓLICA PAULISTA | 30


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Fonte: Monteiro (2020)

Observando as camadas ilustradas acima, observamos que a primeira se refere


a um computador lógico, responsável por distribuir as requisições dos clientes entre
os servidores de aplicação, os quais realizarão as computações propriamente ditas
na segunda camada. Em qualquer arquitetura cliente/ servidor multicamadas, vários
clusters são formados de servidores dedicados aos processamentos de aplicações
específicas, ao contrário de clusters convencionais, constituídos de computadores
normais.
Em clusters corporativos, a capacidade de computação não é o foco principal, mas
a garantia do acesso ao armazenamento. A ideia lógica dos clusters de servidores
propõe a terceira camada que concentra no processamento de dados, em especial, os
de arquivos e bancos de dados. Os servidores podem rodar em máquinas especializadas
e devidamente configuradas para garantir acesso de alta velocidade aos discos.

ISSO ESTÁ NA REDE

Em muitos sistemas informatizados é necessário armazenar informações


em bancos de dados, podemos constatar isso observando que, nas últimas
décadas, o banco de dados se tornou o coração de muitos sistemas. A conexão aos
bancos de dados também faz parte da arquitetura Cliente-Servidor. Para entender
um conceito introdutório de Sistema de Banco de Dados, o link abaixo pode ajudar a
entender. https://dicasdeprogramacao.com.br/o-que-e-um-sgbd/

FACULDADE CATÓLICA PAULISTA | 31


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 4
INTRODUÇÃO À LINGUAGEM “C”

Seu nome pode parecer estranho se for comparado com as linguagens


contemporâneas, como FORTRAN, PASCAL ou COBOL, a linguagem C foi criada em
1972, nos Bell Telephone Laboratories, por Dennis Ritchie, com a finalidade de permitir
a escrita do sistema operacional Unix, utilizando uma linguagem de relativo alto nível
tentando evitar o recurso ao Assembly.
Por divulgar sistema Unix pelas universidades dos Estados Unidos, a linguagem C
se disseminou e se tornou conhecida por todos os tipos de programadores fazendo
com que diferentes organizações desenvolvessem e utilizassem diferentes versões
da linguagem C, e ela se tornou um verdadeiro fenômeno entre programadores e
organizações.
O American National Standards Institute (ANSI) formou, em 1983, um comitê para
a definição de um padrão da linguagem C, que visa o funcionamento semelhante
de todos os compiladores da linguagem, com especificações muito precisas sobre
aquilo que a linguagem deve ou não fazer, seus limites, definições (DAMAS, 2016). O
nome da linguagem resulta da evolução de uma outra linguagem de programação,
desenvolvida por Ken Thompson, também nos Laboratórios Bell, chamada B. Dessa
forma, é perfeitamente natural que a evolução da linguagem “B” originasse a linguagem
C.

Fonte: https://programadoresbrasil.com.br/wp-content/uploads/2020/05/C-programming-1024x530-1.jpg

FACULDADE CATÓLICA PAULISTA | 32


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

4.1. Por que programar em C?

Pelo fato de existirem várias linguagens de programação disponíveis no mercado,


seria necessário que uma delas se destacasse muito em relação às outras para
conseguir interessar tantos programadores. Segundo DAMAS (2016), a maior parte
das linguagens tem um objetivo a atingir:
• COBOL — Processamento de Registros
• PASCAL — Ensino das Técnicas de Programação
• FORTRAN — Cálculo Científico
• LISP e PROLOG — Vocacionadas para as áreas de Inteligência Artificial

A linguagem C não se destina a nenhuma perna em particular. É aquilo que


habitualmente se denomina general purpose. Esta é uma das suas grandes vantagens,
pois se adapta ao desenvolvimento de qualquer projeto, como sistemas operacionais,
interfaces gráficas, processamento de registros, etc. Segundo DAMAS (2016), a
linguagem C é uma linguagem extremamente potente e flexível pelos motivos a seguir:

Rapidez — Consegue obter performances semelhantes às obtidas


pelo Assembly, através de instruções de alto nível, isto é, fazendo
uso de instruções semelhantes às utilizadas por linguagens como
PASCAL ou COBOL, mesmo para usar mecanismos de mais baixo
nível, como o endereçamento de memória ou a manipulação de bits.
Simples — A sua sintaxe é extremamente simples, e o número de
palavras reservadas, de tipos de dados básicos e de operadores
é diminuto, reduzindo assim a quantidade de tempo e esforço
necessários à aprendizagem da linguagem.
Portável — Existe um padrão (ANSI) que define as características de
qualquer compilador. Desse modo, o código escrito numa máquina
pode ser transportado para outra máquina e compilado sem qualquer
alteração (ou com um número reduzido de alterações).
Popular — É internacionalmente conhecida e utilizada. Está muito
bem documentada em livros, revistas especializadas, manuais, etc.
Existem compiladores para todo tipo de arquiteturas e computadores.
Modular — C permite o desenvolvimento modular de aplicações,
facilitando a separação de projetos em módulos distintos e
independentes, recorrendo à utilização de funções específicas dentro
de cada módulo.
Alto Nível — C é considerada uma linguagem de terceira geração,
tal como PASCAL, COBOL, BASIC, etc., as quais são habitualmente
denominadas de alto nível quando comparadas com a linguagem
Assembly. C permite, ainda, o acesso à maior parte das funcionalidades
de Assembly, utilizando expressões e instruções de alto nível.

FACULDADE CATÓLICA PAULISTA | 33


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Através da linguagem C é possível manipular a memória diretamente, utilizando o


endereço de qualquer objeto, atuando diretamente na memória sem qualquer tipo de
restrição, o que aumenta a flexibilidade da linguagem. A maior parte das funcionalidades
da linguagem C é adicionada pela utilização de funções que existem em bibliotecas
adicionais e realizam todo tipo de tarefas, desde a escrita de um caractere na tela até
o processamento de strings, etc.
A linguagem C permite ao programador escrever o código como bem quiser. Um
programa pode ser todo escrito numa única linha ou dividido por inúmeras linhas. A
forma como o código é escrito depende do programador, o qual tem apenas que se
preocupar com o objetivo e a correção da aplicação.
A evolução das linguagens fez também com que a linguagem C evoluísse no sentido
das Linguagens Orientadas a Objetos, dando origem a uma nova linguagem: C++ a qual
mantém a sintaxe da linguagem C e permite um conjunto adicional de características
(encapsulamento, hereditariedade, polimorfismo, sobrecarga, etc.).

4.2. Introdução ao C#

A linguagem C# (lê-se C sharp) foi criada junto com a arquitetura .NET. Embora
existam várias outras linguagens que suportam essa tecnologia (como VB.NET, C++, J#),
C# é considerada a linguagem símbolo do .NET, devido à funcionalidade da plataforma
.NET terem sido desenvolvidas em C#. É uma linguagem orientada a objetos criada
pela Microsoft, faz parte da sua plataforma .Net baseada em C++ e Java.

4.2.1. Características do C#

A linguagem C#, na verdade, é uma junção das principais vantagens do C++ e do


Java, melhorando suas implementações e adicionando novos recursos, fazendo a
linguagem atrativa para desenvolvedores que queiram migrar para o Microsoft .NET.
Sua sintaxe é simples e de fácil aprendizagem, muito familiar com a sintaxe de
JAVA e C. Além disso, simplifica muitas complexidades do C++, fornecendo recursos
poderosos, como tipos de valor nulo, enumerações, delegações, expressões lambdas
e acesso direto à memória, suporte a métodos e tipos genéricos.
Como C# é uma linguagem orientada a objetos, ela suporta conceitos como
encapsulamento, herança e polimorfismo. Todas suas variáveis e métodos são

FACULDADE CATÓLICA PAULISTA | 34


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

encapsulados dentro das definições de uma classe. Ela é usada na maioria das classes
do .NET framework. Foi a primeira linguagem orientada a componentes da família C/
C++, segue os padrões da programação orientada a objetos, onde tudo deriva de um
ancestral comum.
Seus programas executam sobre um ambiente gerenciável, ficando a cargo do .NET
framework realizar o controle de memória. Possui a Language Integrated Query (LINQ),
que fornece recursos de consulta interna entre uma variedade de fontes de dados.
Métodos e tipos não precisam ser declarados em ordem, um arquivo C# pode conter
inúmeras classes, estruturas e interfaces.
As inovações do C# permitem escrita de aplicativos de maneira rápida e aos seus
desenvolvedores criarem uma infinidade de aplicativos compatíveis com o .NET
framework, como, por exemplo aplicações tradicionais do Windows, componentes
distribuídos, aplicativos cliente-servidor e aplicativos com integração de banco de dados.
Segundo a Microsoft (2021), vários recursos do C# ajudam a criar aplicações robustas.
A garbage collection recupera automaticamente a memória ocupada por objetos não
utilizados inacessíveis. A manipulação das exceções fornece uma abordagem para
detecção e recuperação de erros. As expressões lambda dão suporte a técnicas de
programação funcional. A sintaxe de linguagem de consulta integrada (LINQ) cria um
padrão comum para trabalhar com dados de qualquer base.

4.2.2. Execução do C# com .NET

Os programas em C# são executados no .NET, um sistema de execução virtual


chamado Common Language Runtime (CLR) e um conjunto de bibliotecas de classes.
O CLR é a implementação da Microsoft da CLI (Common Language Infrastructure),
um padrão internacional. A CLI é a base para a criação de ambientes de execução
e desenvolvimento nos quais as linguagens e bibliotecas funcionam em conjunto
diretamente. O código-fonte escrito em C# é compilado em uma linguagem intermediária
que está de acordo com a especificação da CLI.
A interoperabilidade de linguagem é um recurso fundamental do .NET. Além dos
serviços de tempo de execução, o .NET também inclui bibliotecas extensivas. Essas
bibliotecas dão suporte a várias cargas de trabalho diferentes. Elas são organizadas
em namespaces que fornecem uma ampla variedade de funcionalidades úteis para
tudo, desde entrada e saída de arquivos, a manipulação de cadeia de caracteres até

FACULDADE CATÓLICA PAULISTA | 35


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

estruturas de aplicação web para Windows Forms controles. O aplicativo C# típico


usa a biblioteca de classes .NET extensivamente para lidar com tarefas comuns.
(Microsoft 2021).

4.3. Primeiro contato com o C#

As primeiras lições explicam os conceitos de C# usando pequenos trechos de


código. Os conceitos básicos da sintaxe de C#, bem como trabalhar com tipos de
dados como cadeias de caracteres, números e valores booleanos. É tudo interativo e
você começará a gravar e executar o código em questão de minutos. As primeiras
lições não exigem conhecimento prévio de programação ou da linguagem C#.
Sua plataforma é gratuita e pode ser baixada diretamente pelo site da Microsoft,
através do link https://dotnet.microsoft.com/download. Porém, antes de baixar
e instalar de forma local no computador, vamos nos ambientar com a linguagem,
utilizando uma ferramenta online para executar o primeiro programa:
Acesse o link https://docs.microsoft.com/pt-br/dotnet/csharp/tour-of-csharp/
tutorials/hello-world?tutorial-step=1 . A página inicial é mostrada, conforme abaixo:

Após isso, clique no botão verde escrito “Entrar do modo de foco” (OBS: alguns
navegadores abrem diretamente no modo de foco). Feito isso, será mostrada a tela
a seguir:

FACULDADE CATÓLICA PAULISTA | 36


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

É bem simples. No campo do lado direito, em frente ao número 1, digite: Console.


WriteLine(“Hello World!”);
A seguir, clique em “Executar”. No campo “Saída” aparece o resultado da execução
desse código. Nesta mesma página, no canto inferior direito, há a sequência do tutorial
para ir se ambientando na linguagem. Entretanto, a ideia é deixar o computador
preparado para que possamos desenvolver as atividades práticas de programação.
Portanto, voltamos ao link https://dotnet.microsoft.com/download para instalarmos
a versão local. Ao aparecer a página a seguir, selecione “Download .NET SDK x64” da
versão 5.0:

FACULDADE CATÓLICA PAULISTA | 37


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

O arquivo será baixado. Execute e siga os passos abaixo:

Clique em “Instalar” e aguarde.

Finalizada a instalação, instalaremos o “Visual Studio Code”, que é o ambiente de


desenvolvimento. Ele pode ser baixado aqui: https://code.visualstudio.com/

FACULDADE CATÓLICA PAULISTA | 38


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Clique em Download for Windows, escolha a versão do seu Windows.

Execute o arquivo baixado da maneira padrão:

FACULDADE CATÓLICA PAULISTA | 39


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Abra o Visual Studio Code, vá em Arquivo e, em seguida, em Abrir Pasta. Crie uma
pasta chamada Teste e, em seguida, Selecionar Pasta.

Feito isso, vá em “Ver” e em “Terminal”. Abrirá uma sessão na tela, que ficará assim:

No campo abaixo, digite:

dotnet new console --framework net5.0

FACULDADE CATÓLICA PAULISTA | 40


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Feito isso, seu primeiro “Hello World” está criado:

Feito isso, vamos executar esse primeiro programa. Ainda no terminal, digite: dotnet
run Program.cs e pressione Enter.

Pronto. Fizemos o primeiro “Hello World” e estamos preparados para começar a


linguagem.

FACULDADE CATÓLICA PAULISTA | 41


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

Experimente trocar o “Hello World” para “Olá Mundo”, ou “Olá, eu sou o programador”
e execute o comando dotnet run Program.cs

FACULDADE CATÓLICA PAULISTA | 42


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 5
MANIPULAÇÃO DE
VARIÁVEIS LOCAIS,
GLOBAIS E SUPERGLOBAIS;

Toda informação processada no computador precisa, necessariamente, ser


previamente armazenada na memória. Essa ação é executada quando usamos variáveis.
Uma variável é uma região de memória, previamente identificada por um nome, cuja
finalidade é armazenar os dados de um programa temporariamente. Cada variável
armazena apenas um valor por vez, sendo esse valor um elemento qualificado a partir
de um dos tipos de dados da linguagem.

Fonte: https://www.devmedia.com.br/arquivos/Artigos/40728/variavel.png

O nome de uma variável é usado para sua identificação e manipulação no programa.


Devemos considerar algumas regras quanto aos nomes: pode ser atribuído com um
ou mais caracteres, sendo que o primeiro caractere não pode ser número. O nome
não pode ter espaços em branco e não pode ter o nome de uma palavra reservada a
uma instrução ou um identificador.
Não podem ser utilizados outros caracteres que não letras e números, com exceção
do caractere underscore “_”, que pode ser utilizado para simular a separação de duas
palavras, como Nome_Aluno, que também podem estar escritas como NomeAluno. No

FACULDADE CATÓLICA PAULISTA | 43


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

C# as variáveis são Case Sensitive, isto é, há a diferenciação de caracteres maiúsculos


e minúsculos. Por exemplo, “NomeAluno” é diferente de “nomealuno”.
A linguagem C# fornece os tipos de dados disponíveis em Java. Ela adiciona suporte
para números não assinados e um novo tipo de ponto flutuante de alta precisão de
128 bits. Por exemplo, a classe Int32 envolve o tipo de dados int. Já a classe Double
envolve o tipo de dados double. Por outro lado, todos os tipos de dados primitivos em
C# são objetos no namespace do sistema. Para cada tipo de dados, é fornecido um
nome curto ou alias. Por exemplo, int é o nome curto para System.Int32, e o double é
a forma curta do System.Double.
A lista de tipos de dados C# pode ser conferida abaixo:

Fonte: Ledur (2018)

FACULDADE CATÓLICA PAULISTA | 44


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

5.1. Variáveis Locais

São aquelas que só têm validade dentro do bloco no qual são declaradas. A
declaração de variáveis locais é a primeira coisa que devemos colocar num bloco. A
característica que torna as variáveis locais tão importantes é justamente a de serem
exclusivas do bloco. Podemos ter quantos blocos de código quisermos com uma
variável local chamada x, por exemplo, e elas não apresentarão conflito entre elas.
Vamos à prática: abra o Visual Studio Code. Ele estará conforme vimos na aula
anterior:

Note que temos a classe Program, declarada em “class Program”. Logo abaixo,
temos a primeira função “main”, onde está o código para demonstrar a expressão
“Hello World”. Tanto a classe Program quanto a função Main são blocos de código.
Como vimos, os tipos acima, para poderem testar as variáveis de forma local, temos
que declarar uma variável chamada “NomeAluno” do tipo string, dentro do bloco “main”:

FACULDADE CATÓLICA PAULISTA | 45


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

string NomeAluno;

A seguir, atribuiremos o valor “Fulano de Tal” para a variável NomeAluno:

NomeAluno = “Fulano de Tal”;

Finalmente, faremos o comando para escrever na tela o conteúdo da variável. Abaixo,


como vai ficar o bloco:

Console.WriteLine(NomeAluno);

Ao executarmos o programa1 teremos o resultado:

Note que foi mostrado o conteúdo da variável “NomeAluno”.

1 A partir de agora, quando for mencionado “Executarmos o programa”, usaremos o comando dotnet run Program.cs

FACULDADE CATÓLICA PAULISTA | 46


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

Faça o teste do bloco acima, colocando o seu nome na variável NomeAluno, entre
Aspas duplas “ ” e execute o programa. O resultado será o conteúdo da variável.

A variável NomeAluno está declarada dentro do código “Main”. Isto é, ela é uma
variável LOCAL do bloco MAIN. Para conseguirmos entender, vamos ao Visual Studio
criar uma nova função para podermos testar:

No exemplo do código acima, foi criada a função Serie(). Dentro desta função foi
declarada apenas a variável SerieAluno. Porém, dentro deste bloco, foi solicitada a
utilização da variável NomeAluno. No caso, ela apareceu com erro, pois está declarada
apenas no bloco de código Main. No caso, podemos dizer que as variáveis SerieAluno
e NomeAluno são variáveis locais para cada um dos seus blocos de código.

5.2. Variáveis Globais

São declaradas fora de todas as funções do programa. Elas são conhecidas e


podem ser alteradas por todas as funções do programa. Quando uma função tem uma
variável local com o mesmo nome de uma variável global a função dará preferência
à variável local. Vamos ao exemplo:

FACULDADE CATÓLICA PAULISTA | 47


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

O termo “static” na frente da variável é para “avisar” o compilador que é uma variável
estática e não precisará ser instanciada. Na Programação Orientada a Objetos, ao
utilizar a classe, precisa-se inicialmente instanciá-la. As variáveis declaradas como
“static” não precisam ser instanciadas, já tendo sua posição de memória definida.

FACULDADE CATÓLICA PAULISTA | 48


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

No bloco acima declaramos a variável global DisciplinaAluno do tipo String. Ela foi
declarada fora do bloco de funções e foi utilizada nos dois blocos. Tanto no Main()
quanto no Serie(). Ao executar a o bloco acima, temos o seguinte resultado:

A resposta da execução escreve os dois conteúdos apresentados na variável


DisciplinaAluno, pois ela é uma variável global e é utilizada nos dois blocos.

ANOTE ISSO

Note que na função Main() colocamos uma chamada da função Serie(). Esse
exemplo significa que pedimos que o sistema execute o conteúdo da função Serie()
dentro do programa principal Main().

ISSO ACONTECE NA PRÁTICA

Segundo UEHARA (2021), em um artigo publicado em 1973, por Wulf e Shaw, foi
descrito que o uso indiscriminado de variáveis globais é prejudicial. O problema
independe da linguagem de programação: as variáveis globais são danosas desde
a linguagem de baixo nível até as mais altas. Os mais jovens acabam aprendendo
sobre isso quando entram em contato com comunidades de programação, o livro
de Jack Ganslee ou errando nos projetos da empresa. Em 2011, houve problemas
com a Toyota Camry, e foi apontado que uma das causas era o uso de 11.000
variáveis globais. Qual é exatamente o problema das variáveis globais? Para quem
já trabalhou em algum projeto sabe que é fácil chegar a mil ou duas mil linhas
de código, ficando, pouco a pouco, mais difícil de cumprir o fluxograma inicial
ou diagrama de estados planejados. Uma das razões é devido ao fato de várias
funções e interrupções terem livre acesso às variáveis globais, gerando estados não
existentes ao inicialmente planejado.

FACULDADE CATÓLICA PAULISTA | 49


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

5.3. Variáveis Superglobais

Alguns ambientes de desenvolvimento web apresentam o conceito de variáveis


superglobais, as quais estão disponíveis em qualquer lugar do script, sem que seja
necessário as declarar globais. A principal finalidade dessas variáveis é facilitar o
acesso a dados enviados pelo servidor web (como, por exemplo, campos de um
formulário). Segundo SOARES (2013), na linguagem para web PHP, as seguintes
variáveis superglobais estão disponíveis:

$GLOBALS: retorna um array associativo com referência para toda e


qualquer variável atualmente disponível no escopo global do script.
A chave desse array é o nome das variáveis.
$_SERVER: contém as variáveis com informações relativas ao servidor
web e ao ambiente de execução do script, por exemplo:
$_GET:contém as variáveis enviadas pelo método GET. Por exemplo,
se chamarmos um script da seguinte forma: http://localhost/scriptx.
php5?codigo=10& nome=Walace, temos que $_GET conterá dois
elementos («codigo” = 10, nome= “Walace”).
$_POST: contém as variáveis enviadas pelo método HTTP POST, por
exemplo, no envio de um formulário web.
$_COOKIE: contém as variáveis disponíveis como cookies, as quais
são especiais, gravadas nas máquinas do usuário e recuperadas
pelo browser.
$_FILES: esse array contém informações de arquivos enviados pelo
computador cliente para o servidor web. Por exemplo, quando no
formulário web anexar uma foto ou um documento qualquer.
$_ENV: contém as variáveis de ambiente disponíveis no momento.
$_REQUEST: este é um array com o mesmo conteúdo de $_GET,
$_POST e $_COOKIE juntos, porém não é muito confiável, uma vez
que variáveis com mesmo nome serão sobrepostas conforme o valor
do parâmetro variables_order do arquivo php.ini (o padrão é EGPCS,
ou seja, Env, Get, Post, Cookie e por último Server).
$_SESSION: contém as variáveis registradas na sessão corrente.

ISSO ESTÁ NA REDE

O VisualStudio Code tem a possibilidade de executar alguns scripts em PHP.


Você pode conferir um excelente artigo no link a seguir: https://www.ti-enxame.
com/pt/php/como-executar-ou-depurar-o-php-no-codigo-do-visual-studio-
vscode/1052106567/

FACULDADE CATÓLICA PAULISTA | 50


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

5.4. Constantes

Tudo que é estável, inalterável, de valor fixo pode ser considerado constante. Assim,
do ponto de vista computacional, uma constante é uma grandeza fixa, que usamos
em uma expressão, pela qual definimos um valor que será inalterado na expressão,
independentemente das variáveis envolvidas na operação a ser realizada. Por exemplo
prático pode-se considerar a constante matemática pi, que equivale ao valor aproximado
3,14159. Além de ser um valor fixo, usado em uma expressão, uma constante pode ser
usada como rótulo de identificação. A maneira mais comum que temos para definir
uma constante é usar a diretiva definida por meio da sintaxe:

const double Pi = 3.14159;

Sabemos que a variável ocupa espaço na memória do computador, pois, quando


é definida, segundo o tipo associado, o compilador aloca na memória espaço para
armazenar o valor associado. Já uma constante é definida de maneira diferente. Ela
não ocupa espaço na memória por se tratar apenas de um rótulo associado a um
valor que será usado pelo programa, e esse valor não é armazenado em memória,
ficando apenas vinculado ao código do programa.

FACULDADE CATÓLICA PAULISTA | 51


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 6
OPERADORES

Tanto as variáveis como as constantes podem ser usadas na elaboração de cálculos


matemáticos com operadores. Os operadores podem ser unários ou binários. São
binários quando atuam em operações de exponenciação, multiplicação, divisão, adição
e subtração, em que se utilizam dois componentes. São unários quando atuam na
inversão de um valor, atribuindo a ele o sinal positivo ou negativo, ou seja, atuam
diretamente em apenas um componente.

6.1. Operações matemáticas em C#

É comum usar em um programa expressões aritméticas quando necessitamos


efetuar cálculos matemáticos. Nessas expressões definimos o relacionamento existente
entre variáveis e constantes numéricas com a utilização dos operadores aritméticos.
Para exemplificarmos as operações a seguir, faremos voltar ao Visual Studio Code.
Iniciaremos com as operações mais simples, passando para as mais complexas.

6.1.1. Adição (+);

A operação de adição é simples. Criaremos uma função chamada Calculo, na qual


declararemos três variáveis (a, b, c). Feito isso, faremos nosso programa ler a informação
que digitarmos. O código ficará assim:

FACULDADE CATÓLICA PAULISTA | 52


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

O comandoConsole.ReadLine() é utilizado para capturar a informação


digitada. O comando Convert.ToInt32() serve para que o valor capturado pelo
teclado fosse convertido do padrão “Char” para int.

Ao executarmos o programa, irá aparece o prompt para digitarmos os valores para


a soma. Simulando uma soma simples, de 3 + 5, teremos:

FACULDADE CATÓLICA PAULISTA | 53


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

6.1.2. Subtração (-);

Utilizando o exemplo anterior, vamos mudar a operação para a subtração. Trocamos


apenas o conteúdo das seguintes linhas:

Ao executarmos o programa, aparecerá o prompt para digitarmos os valores para


a subtração. Simulando uma operação simples, de 5 - 3, teremos:

6.1.3. Multiplicação (*);

Utilizando o exemplo anterior, vamos mudar a operação para a multiplicação. Em


C# o sinal da multiplicação é representado pelo asterisco “*”. Trocamos apenas o
conteúdo das seguintes linhas:

Ao executarmos o programa, aparecerá o prompt para digitarmos os valores para


a multiplicação. Simulando uma operação simples, de 5 x 3, teremos:

FACULDADE CATÓLICA PAULISTA | 54


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

6.1.4. Divisão ( / );

Utilizando o exemplo anterior, vamos mudar a operação para a divisão. Em C#


o sinal da divisão é representado pela barra “/”. Trocamos apenas o conteúdo das
seguintes linhas:

Ao executarmos o programa, aparecerá o prompt para digitarmos os valores para


a divisão. Simulando uma operação simples, de 6 : 3, teremos:

ANOTE ISSO

Note que usamos números inteiros (6 e 3) para a divisão. O resultado (2) também
foi um número inteiro. Porém, sabemos que na grande maioria dos casos, o
resultado de uma divisão não é um número inteiro, se trocarmos a operação de 6 :
3 para 6 : 4 mantendo as variáveis declaradas como inteiras, teremos:

Note que o resultado trouxe “1”, o que não condiz com a realidade da operação. Se você
fizer essa mesma operação (6 : 4) na sua calculadora, o resultado dará 1,5. E no C#?
Como faremos? Simples. Alteramos a declaração das variáveis (a, b, c) para double:

FACULDADE CATÓLICA PAULISTA | 55


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Executando a operação 6 : 4 temos:

6.1.5. Operador de Resto ( % );

Também conhecido como “Módulo”, este operador retorna o resto de uma divisão.
Dos operadores citados acima os três primeiros trabalham da maneira que nós já
conhecemos (Adição, Subtração e Multiplicação), já o operador de Divisão ‘/’ trabalha
de maneira diferente na divisão de um inteiro, por exemplo, quando dividimos 11
por 2 usando esse operador (sendo 11 um inteiro) o resto da divisão é descartado,
pois os inteiros não aceitam números fracionários, ou seja, o resultado seria 5. Já
o operador ‘%’ tem como sua única função pegar o resto de uma divisão usando o
mesmo exemplo dividindo 11 por 2 usando o operador ‘%’ modulo o resultado seria
1, já que é o resto da divisão.
Utilizando o exemplo anterior, vamos mudar a operação para a Resto. Em C# o sinal
do resto é representado pelo símbolo percentual “%”. Trocamos apenas o conteúdo
das seguintes linhas:

FACULDADE CATÓLICA PAULISTA | 56


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executarmos o programa, aparecerá o prompt para digitarmos os valores para


a divisão. Simulando uma operação simples, de 11 : 2, teremos:

6.2. Atribuição Composta

Os operadores de atribuição composta combinam o operador de atribuição simples


com outro operador. Os operadores de atribuição composta executam a operação
especificada pelo operador adicional e, em seguida, atribuem o resultado ao valor que
está do lado esquerdo. Por exemplo, uma expressão de atribuição composta, como:

a += b;

pode ser entendida como:

a = a + b;

A expressão de atribuição composta não é equivalente à versão expandida porque


a expressão de atribuição composta avalia “a” apenas uma vez, enquanto a versão
expandida avalia “a” duas vezes: na operação de adição e na operação de atribuição.
Os operandos de um operador de atribuição composta devem ser do tipo Int ou
Double. Os operadores de atribuição de adição (+) e de subtração (-) também podem
ter um operando esquerdo do tipo de ponteiro, caso em que o operando à direita deve
ser += -= do tipo integral. O resultado de uma operação de atribuição composta tem
o valor e o tipo do operando esquerdo.
O seguinte exemplo demonstra o uso da atribuição composta com operadores
aritméticos. Para exemplo, vamos alterar nosso programa de teste. No caso, não
vamos precisar da variável “c”. Iniciaremos com a adição. Para isso, deixaremos o
programa assim:

FACULDADE CATÓLICA PAULISTA | 57


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executarmos o programa, aparecerá o prompt para digitarmos os valores para


a adição. Simulando uma operação simples, de 3 + 2, teremos:

Note que por não precisarmos da variável “c”, pois a variável “a” recebeu o valor da
soma. A seguir, faremos exemplos para os outros operadores:
• Subtração, utilizando os números 5 e 3:

FACULDADE CATÓLICA PAULISTA | 58


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executar:

• Multiplicação, utilizando os números 5 e 3:

Ao executar:

• Divisão, utilizando os números 6 e 3:

Ao executar:

• Resto, utilizando os números 11 e 4:

Ao executar:

FACULDADE CATÓLICA PAULISTA | 59


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

6.3. Operadores de Testes

Os operadores de testes servem para que sejam testadas as expressões. Eles


retornam um valor do tipo booleano (true ou false). Antes de exemplificar, temos que
entender que o sinal de “igual” ( = ), quando utilizado em uma operação, tem a função
de atribuir o valor. Por exemplo, no código: int a = 2; estamos ATRIBUINDO o
valor 2 à variável “a”. Para compararmos um valor ao outro, utilizamos os operadores
de teste. Este teste sempre vai retornar se o teste for verdadeiro ou falso.

6.3.1. Igual ( == )

Este operador retornará true quando os valores testados forem iguais. Para podermos
testar os operadores, vamos fazer algumas mudanças no nosso programa de teste.
Vamos declarar a variável “c” como do tipo Boolean ( bool ). Em seguida, vamos deixar
o programa assim:

FACULDADE CATÓLICA PAULISTA | 60


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Feitas as alterações, executaremos o programa, testando suas situações, onde o


primeiro número será 2 e o segundo número também será 2:

Agora, vamos comparar 2 com 3 executando o programa novamente:

Note que a variável “c” retornou true quando os valores são iguais e false com
valores diferentes.

ANOTE ISSO

Em C# o símbolo “exclamação” ( ! ) significa “not”. Se quisermos testar se um


número é diferente (ou não igual), trocamos o primeiro “=” por “ ! ”: Veja o exemplo:

Ao executar comparando se 5 é diferente de 5:

Agora, comparando se 5 é diferente de 4:

FACULDADE CATÓLICA PAULISTA | 61


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

6.3.2. Maior ( > ) e Maior Igual ( >= )

Este operador irá retornar true quando um valor testado é maior ou se ele for maior
ou igual ao outro. No nosso exemplo, vamos testar simultaneamente os operadores:

Testaremos com os valores 5 e 5.

Ao executarmos, o primeiro valor retornado foi false pois 5 não é maior que 5. Mas,
a segunda retornou true porque 5 é maior ou igual a 5.

6.3.3. Menor ( < ) e Menor Igual ( >= )

Este operador retornará true quando um valor testado é menor ou se ele for menor
ou igual ao outro. No nosso exemplo, vamos testar simultaneamente os operadores:

Testaremos com os valores 4 e 5.

FACULDADE CATÓLICA PAULISTA | 62


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executarmos, ambos os valores retornados foram true pois 4 é menor ou igual


que 5.

ISSO ACONTECE NA PRÁTICA

Use os exemplos acima com vários números diferentes para que você consiga
verificar cada situação específica e os resultados.

FACULDADE CATÓLICA PAULISTA | 63


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 7
ESTRUTURA DE
DESVIO CONDICIONAL

Para um programa tomar decisões é necessário criar uma condição para que ele
possa produzir uma de duas respostas: pode ser uma resposta verdadeira ou uma
resposta falsa. A condição é a definição de relação lógica entre variáveis ou entre
variáveis e constantes, definidas com o uso dos operadores relacionais vistos no
capítulo anterior. A relação lógica existente entre os elementos de uma condição é
conseguida com a utilização dos operadores relacionais.

7.1. Desvio Condicional Simples

Um desvio condicional será simples quando tivermos uma condição que desvia
a execução do programa caso o resultado lógico avaliado de certa condição seja
verdadeiro. Se o resultado lógico avaliado for falso, nada acontecerá, e o programa
simplesmente seguirá o seu fluxo de execução. Um desvio condicional simples em
C# é realizado por meio da instrução if, que possui a seguinte sintaxe:

if <(condição)>
{
<instrução 1 executada quando condição for verdadeira>;
<instrução 2 executada quando condição for verdadeira>;
<instrução N executada quando condição for verdadeira>;
}
<instrução executada após condição ser verdadeira e/ou
falsa>;

Vamos abrir o Visual Studio Code para entendermos, na prática, o conceito do


desvio condicional simples. Neste exemplo, testaremos se os dois números digitados
são iguais. A rotina vai ficar assim:

FACULDADE CATÓLICA PAULISTA | 64


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executar o programa, temos a resposta:

7.2. Desvio Condicional Composto

Agora, veremos como usar a instrução if... else. Numa instrução If... else, se a
condição for verdadeira, será executada a instrução posicionada entre as instruções
if e else. Sendo a condição falsa, será executada a instrução posicionada logo após a
else, como indicado na seguinte sintaxe:

FACULDADE CATÓLICA PAULISTA | 65


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

if <(condição)>
{
<instrução 1 executada quando condição for verdadeira>;
<instrução 2 executada quando condição for verdadeira>;
<instrução N executada quando condição for verdadeira>;
}
else
{
<instrução 1 executada quando condição for falsa>;
<instrução 2 executada quando condição for falsa>;
<instrução N executada quando condição for falsa>;
}
<instrução executada após condição ser verdadeira ou falsa>

Vamos mudar nosso exemplo. Agora, para testarmos o desvio condicional composto,
faremos um teste de idade. Então, no Visual Studio Code, prepararemos o programa
como abaixo:

FACULDADE CATÓLICA PAULISTA | 66


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Agora, o programa verifica se o valor digitado é maior que 17. Caso a expressão
seja true, o sistema executará o bloco informando que o digitador é maior de idade.
Caso o valor seja menor do que 17, ele executará o bloco que está embaixo.

7.3. Operadores lógicos

Em algumas ocasiões, é necessário trabalhar com o relacionamento de duas ou


mais condições ao mesmo tempo e na mesma instrução. Para esses casos, usamos
operadores lógicos, em que:
• && (e - operador de conjunção),
• || (pipe pipe - ou - operador de disjunção inclusiva) e
• ! (não - operador de negação).

Os operadores lógicos && e || permitem mais de uma condição para a tomada de


uma única decisão. Já o operador logico! tem por finalidade a negação do estado
lógico de uma condição.

7.3.1. Conjunção (&&)

O operador lógico de conjunção && é utilizado quando dois ou mais relacionamentos


lógicos de uma condição são verdadeiros.

Fonte: Manzano (2014)

Utilizando o exemplo anterior, modificaremos nosso programa de teste para ilustrar


esses operadores:

FACULDADE CATÓLICA PAULISTA | 67


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executarmos, temos:

Note que ao executar, ele verificou se o número digitado é MAIOR que 12 e (&&)
MENOR que 18. Se o número digitado obedeceu essas duas condições, foi executado
o código da condição. Caso contrário, executou outro código.

7.3.2. Disjunção ( || )

O operador lógico de disjunção inclusiva || é utilizado quando, pelo menos, um dos


relacionamentos lógicos de uma condição é verdadeiro.

Fonte: Manzano (2014)

FACULDADE CATÓLICA PAULISTA | 68


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Faremos uma verificação da disjunção no nosso Visual Studio Code. Suponhamos


ter 3 opções para um acesso. Então, nosso programa ficará assim:

Ao executarmos, como no exemplo abaixo, temos:

FACULDADE CATÓLICA PAULISTA | 69


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

7.3.3. Negação ( ! )

O operador lógico de negação ! é utilizado quando é necessário estabelecer que


uma condição deve ser não verdadeira ou não falsa. O operador ! inverte o estado
lógico de uma condição.

Fonte: Manzano (2014)

Utilizando o exemplo anterior, mudaremos nosso código usando a negação:

Executando o programa, temos:

FACULDADE CATÓLICA PAULISTA | 70


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

7.4. Desvio Condicional Seletivo

A grande quantidade de desvios condicionais poder ocasionar uma difícil


interpretação. Para facilitar esse tipo de necessidade temos a estrutura de controle
com múltipla escolha, denominada switch, cuja sintaxe é:

switch <variável>
{
case <opção 1>: <operação 1>; break;
case <opção 2>: <operação 2>; break;
case <opção 3>: <operação 3>; break;
default <opção 4>: <operação 4>; break;
}

Para podermos testar, faremos um programa para retornar o mês por extenso quando
digitarmos o número referente. Apenas uma observação: para facilitar o entendimento,
foi colocado abaixo apenas a rotina da função Calculo(), mas o restante do programa
não foi alterado, como foram vistos em exemplos anteriores.

FACULDADE CATÓLICA PAULISTA | 71


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executarmos o programa acima, temos:

ANOTE ISSO

As instruções do Case podem ter mais de uma linha dentro do bloco. Para isso,
temos que utilizar as chaves ( {} ) para delimitar o código, como podemos ver
abaixo:

Executando o programa acima e selecionando o mês 12, temos:

FACULDADE CATÓLICA PAULISTA | 72


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ISSO ESTÁ NA REDE

O site da Microsoft listado aqui https://docs.microsoft.com/pt-br/dotnet/csharp/


language-reference/statements/selection-statements disponibiliza mais exemplos
para serem testados sobre desvios condicionais. Tudo bem explicado e poderá
ajudar bastante no desenvolvimento do assunto.

FACULDADE CATÓLICA PAULISTA | 73


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 8
ESTRUTURA DE LAÇO
DE REPETIÇÃO

Até agora, vimos como proceder com o uso de uma programação sequencial e com
o uso de tomada de decisões. Ainda não tivemos a necessidade de ter que repetir mais
de uma vez determinado trecho de programa. Neste capítulo, executaremos estruturas
que repetem partes códigos até que seja atingida uma determinada instrução.

Fonte: https://www.researchgate.net/profile/Ulisses-Correa/publication/320237195/figure/fig7/AS:556732465074176@1509746771080/Figura-310-Exemplo-de-
laco-de-repeticao-com-validacao-final-em-um-grafo-de-fluxo-de.png

A capacidade operacional de um computador é executar programas que são


sequências de instruções. Por vezes, algumas dessas ordens devem ser repetidas, e
para fazer esse tipo de ação temos a técnica de uso dos laços de repetição.
Existem três tipos de laços no C#: um laço de ação condicional pré-teste (com a
condição de controle no início do laço), um laço de ação condicional pós teste (com a
condição de controle no fim do laço) e um laço de ação incondicional operacionalizado
por uma variável de controle.

FACULDADE CATÓLICA PAULISTA | 74


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

8.1. Laço condicional pré teste

Para a execução de laço condicional pré-teste temos na linguagem C# a instrução


while, que permite executar um conjunto de instruções enquanto a condição verificada
permanecer válida. No momento em que essa condição não for válida, o processamento
da rotina será desviado para fora do laço. A sintaxe dessa estrutura de laço corresponde
a:

while (condição)
{
<executa instrução 1 enquanto condição for válida>;
<executa instrução 2 enquanto condição for válida>;
<executa instrução 3 enquanto condição for válida>;
<executa instrução N enquanto condição for válida>;
}

Fonte: https://www.completecsharptutorial.com/basics/images/while.jpg

No nosso programa de exemplo, faremos um teste de contagem de número inteiro.


O laço será executado até o valor da variável atingir o valor digitado. Nosso programa
vai ficar assim: (obs.: abaixo está apenas o exemplo da função “Calculo()”, mantendo
o resto do programa como vimos em exemplos anteriores).

FACULDADE CATÓLICA PAULISTA | 75


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

No bloco acima, atribuímos o valor 0 para a variável B. Ao executar o programa, foi


digitado um valor para a variável A. Ao executar o laço, note que ele incrementou o
valor 1 a cada passagem, fazendo com que a variável B tivesse o valor 1 adicionado
em cada passagem. O código acima ficou “Enquanto o valor de B for menor ou igual
ao valor de A (digitado), incremente a variável B. Quando o valor de B ficar maior que
A, o laço é encerrado. Ao executar, temos:

FACULDADE CATÓLICA PAULISTA | 76


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO
O comando while é considerado como pré-teste porque ele executa o teste antes de
iniciar o laço. Como exemplo, atribuiremos o valor de 10 na variável B e digitaremos
um valor menor que 10. Neste caso, o laço não será executado, justamente porque
o teste é anterior:

Ao executar:

O número 5 digitado na variável A já é menor que o início do laço, onde o valor se


inicia com 10. Ao digitarmos o valor 15 na variável A, temos:

ISSO ACONTECE NA PRÁTICA

A linguagem C# permite não utilizar como contador a forma b = b + 1, apresentada


no exemplo anterior. Eles preferem as formas b += 1 ou b++. A forma b++ é
normalmente usada quando a contagem é efetuada de unidade em unidade;
A forma b += 1, quando o passo de contagem tem algum valor diferente de 1.
Vale ressaltar, também, que podem ser utilizados, além de +=, os operadores -=, *=
e /= para realizar outras operações de incremento ou decremento de valores em
determinada variável.

FACULDADE CATÓLICA PAULISTA | 77


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

8.2. Laço condicional pós teste

Para a execução de laço condicional pós teste temos a instrução do ... while, que
faz um teste lógico no final do laço. Esse laço tem como característica operacional
sempre executar o bloco subordinado ao laço no mínimo uma vez. A estrutura de laço
do ... while tem seu funcionamento controlado por condição, mas esse tipo de laço,
como dito, executa o bloco de instruções subordinadas ao laço pelo menos uma vez
antes de verificar a validade da condição estabelecida. Diferentemente do laço pré
teste while, que executa somente um conjunto de instruções quando a condição for
favorável.

Fonte: https://www.completecsharptutorial.com/basics/images/dowhile.jpg

Dessa forma, do ... while funciona em sentido contrário ao while, pois sempre processa
um conjunto de instruções no mínimo uma vez, mesmo que a condição não seja
válida. A instrução do ... while pode ser escrita com a sintaxe:
do
{
<faz a execução da instrução 1 enquanto condição válida>;
<faz a execução da instrução 2 enquanto condição válida>;
<faz a execução da instrução 3 enquanto condição válida>;
<faz a execução da instrução N enquanto condição válida>;
} while (condição);

FACULDADE CATÓLICA PAULISTA | 78


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Como exemplo, simularemos um menu, onde, enquanto o usuário não digitar o


número 9, o laço se repetirá. A sintaxe ficará assim:

No bloco acima o que está dentro de do será executado ao menos uma vez. Após a
digitação do número será verificado se o número digitado é diferente (ou não igual “!=”
a 9) . Quando o usuário digitar o 9, o laço é encerrado, conforme a execução a seguir:

FACULDADE CATÓLICA PAULISTA | 79


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

Os programadores têm que ter muito cuidado com os chamados “laços infinitos”,
quando é definida uma condição que não será executada no bloco dentro do laço,
fazendo com que o programa execute aquele laço de maneira infinita, podendo
causar travamento do sistema até que o usuário intervenha. Os laços infinitos são
derivados de erro e falta de atenção ao programar. Temos exemplo de laço infinito:

Note que a digitação do valor da variável A é antes do laço. Se o usuário digitar


qualquer número diferente de 9, o laço será executado infinitamente, pois o valor
nunca será 9:

FACULDADE CATÓLICA PAULISTA | 80


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

8.3. Laço incondicional

Já vimos os conceitos de laços com while e do ... while. Nesses dois exemplos
vimos que se podem elaborar trechos que executem uma parte do programa um
determinado número de vezes com a utilização de uma variável contador. Além das
formas já vistas, há outra forma de facilitar o uso de contadores por meio do laço for,
que possui a sintaxe:
for (<início>; <fim>; <incremento>)
{
<executa instrução 1>
<executa instrução 2>
<executa instrução 3>
<executa instrução N>
}

O laço for é executado por uma instrução que recebe três parâmetros de trabalho,
separados por ponto e vírgula. O primeiro parâmetro é representado por uma variável
e seu valor inicial; o segundo parâmetro, pela condição de finalização da execução do
laço; o terceiro e último parâmetro, pelo contador de incremento que ocorre entre os
valores inicial e final da contagem.
Por ser incondicional, não precisamos colocar uma condição para que seja encerrado
o laço e, sim, um limite. Como exemplo, faremos um contador de 1 a 10 onde o valor
será incrementado de um em um, e o programa demonstrará o valor:

No bloco de código acima não há nenhuma intervenção do usuário (condição). O


bloco será executado automaticamente do 0 até o 10, somando 1 em 1:

FACULDADE CATÓLICA PAULISTA | 81


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

Os parâmetros passados dentro do comando for vão definir o início e o final. Porém,
no incremento, podemos utilizar qualquer tipo de razão. Se quisermos, por exemplo,
incrementar de 2 em 2 e fazer um contador, a sintaxe ficaria a seguinte:

E como resultado:

FACULDADE CATÓLICA PAULISTA | 82


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ISSO ACONTECE NA PRÁTICA

Nós aprenderemos sobre listas e vetores mais adiante. Porém, para mostrar o
funcionamento do loop “foreach” é preciso usar um vetor. O loop “foreach” é usado
para interagir (percorrer) listas. Ele opera sobre vetores ou listas:

foreach(<tipo de dado> <nome> in <lista>)


{
//instruções
}
Vamos a um exemplo prático, criando uma lista de nomes:

Criamos uma lista do tipo string e colocamos alguns elementos dentro. No nosso
laço “foreach” serão exibidos todos os elementos dentro da lista. Ao executar, temos:

FACULDADE CATÓLICA PAULISTA | 83


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 9
ESTRUTURA DE MÉTODOS/
FUNÇÕES

A linguagem C#, por operar no paradigma da orientação a objetos, segue uma


estrutura operacional, de certa forma parecida em alguns pontos, não em todos, com
a programação estruturada.
As linguagens orientadas a objetos usam rotinas de ação denominadas funções (ou
métodos, dependendo da linguagem em uso) que nada mais são do que similares em
programação estruturada denominados sub-rotinas (funções, procedimentos, módulos
ou subprogramas).
Uma função ou método é um trecho de código de programa independente de qualquer
parte do programa, mas relacionado ao programa com atribuições bem definidas.

Fonte: https://miro.medium.com/max/13288/1*dR2xNH0uBPrVuV4S5x9KFg.jpeg

FACULDADE CATÓLICA PAULISTA | 84


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Os métodos são um conjunto de instruções que efetuam uma tarefa específica. De


forma geral, os métodos podem receber valores de entrada (parâmetros opcionais) e
gerar opcionalmente um valor de saída (retornar apenas um valor), denominado valor
de retorno.
No geral, problemas complexos exigem algoritmos complexos, mas sempre é
possível dividir um problema grande em problemas menores. Dessa forma, cada parte
menor tem um algoritmo mais simples, e é esse trecho menor que na linguagem C#
pode se tornar um método (MANZANO, 2014).
Quando um método é chamado, ele é executado; e, ao seu término, o controle
de processamento do programa retorna automaticamente para a primeira linha de
instrução após a linha que efetuou a chamada do método em questão.
Em C# é possível desenvolver três formas de comportamento para um método.
O primeiro, quando o método é executado e não retorna nenhum valor para a rotina
chamadora; o segundo, quando um método tem a capacidade de retornar apenas um
valor à função chamadora; e, por último, quando um método trabalha com passagem
de parâmetros por valor e por referência. Esta última será vista na próxima aula. Vamos
preparar nosso Visual Studio para exemplificarmos os conceitos vistos acima.

9.1. Método sem retorno de valor

Primeiramente, verificaremos um método no qual não retornará nenhum valor. Deixe


a tela do seu Visual Studio como está abaixo:

FACULDADE CATÓLICA PAULISTA | 85


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Note que temos a instrução static void Main(string[] args). Este é um


método padrão do C# como instrução principal “main”. A partir daí, exemplificaremos
a criação de outros métodos.
De início, faremos um menu onde o usuário escolherá uma operação:

Note que temos um programa onde o Menu aparece dentro da execução do método
principal, já devidamente programado para receber apenas números válidos digitados.

FACULDADE CATÓLICA PAULISTA | 86


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Só que o programa principal poderia ficar sobrecarregado se colocássemos todos


os códigos dentro dele. Para isso, faremos um método Menu() onde ele não retorna
nada:

Note que foi separado o bloco de código na função principal Main(), onde, nela
temos um chamado para a função Menu():

Ao executar:

FACULDADE CATÓLICA PAULISTA | 87


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

Para que uma mesma variável tenha acesso a vários métodos, vimos na aula 5, o
conceito de variável local e global. Neste caso, a variável opcao está declarada como
global, pois vários métodos poderão acessar:

Ao ser chamada a função Menu(), será mostrado o conteúdo implementado na


função. Isso facilita, pois em qualquer parte do código é possível que se execute
o método Menu(). O programa só executou a instrução Console.WriteLine(“A
opção escolhida foi “+opcao); quando terminou a execução do menu, isto
é, digitando o número 9.

9.2. Método com retorno de valor

Ainda temos como simplificar a rotina acima? A resposta é SIM! Note que precisamos
declarar uma variável global opcao para que consigamos acessar o que foi digitada
nela. Agora, vamos fazer com que a própria função Menu() retorne para nós o valor
digitado, para que não precisemos declarar a variável global:

FACULDADE CATÓLICA PAULISTA | 88


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Note que a função Menu() está declarada como int e no final do bloco temos o
comando return que será o valor que a função Menu() irá retornar. Dentro da função
temos apenas a demonstração dos itens do menu e a coleta do valor digitado. Todas
as verificações e validações do que foi digitado ficará FORA da função Menu(), sendo
feita onde ela é chamada, como no exemplo, em Main():

No código acima foi declarada uma variável opcao que receberá o conteúdo retornado
pela função Menu() e todo tratamento será da variável opcao sem precisar codificar
nada na função Menu(). Ao executarmos temos:

9.3. Exemplo prático

Agora, vamos implementar as funções da nossa calculadora. Vamos fazer uma função
para cada operação determinada no Menu() e trazer o resultado na tela. Primeiramente,
declararemos uma variável chamada resultado no programa principal Main(). Esta
variável irá receber o resultado das operações. A partir de agora colocaremos em
prática diversos comandos vistos anteriormente. Agora, implementaremos cada uma
das funções:

FACULDADE CATÓLICA PAULISTA | 89


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

FACULDADE CATÓLICA PAULISTA | 90


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Nosso programa Main() ficará conforme abaixo:

Foi criada uma função para cada operação, onde a variável resultado receberá o
conteúdo retornado pela sua respectiva função. Trocamos o if para a validação da
opção digitada por switch, pois o switch nos permite limitar o escopo de digitação.
Cada um dos valores possíveis (1, 2, 3, 4 ou 9) tem sua linha de código de execução.
Qualquer valor diferente destes descritos o programa apresentará a mensagem de
“Valor inválido”.

FACULDADE CATÓLICA PAULISTA | 91


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO
Uma função pode retornar qualquer tipo de valor. Como teste, vamos simular uma
função que retorne um valor String e outro que retorne um valor booleano, a ser
implementado na função Main():

As variáveis nome e cidade recebem valores da mesma FuncaoString(), bem como a


verificação da idade é feita toda na FuncaoBoolean() as quais estão descritas abaixo:

Ao executarmos:

FACULDADE CATÓLICA PAULISTA | 92


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 10
PASSAGEM DE ARGUMENTOS
POR VALORES E REFERÊNCIAS

O uso de passagem de parâmetros em um método proporciona uma comunicação


bidirecional entre as rotinas do programa, principalmente quando se declaram variáveis
locais. No caso de variáveis globais, esta ação fica desnecessária.

http://www.andrealveslima.com.br/blog/wp-content/uploads/2016/02/020516_0509_Passandopar1.png

Quando se trabalha com funções, é possível passar valores de uma sub-rotina para
outra. A passagem de parâmetro entre funções poderá ser definida sob a ótica de
dois comportamentos: passagem de parâmetro por valor e passagem de parâmetro
por referência.

10.1. Passagem de parâmetro por valor

Ocorre quando uma sub-rotina envia um conteúdo para outra sub-rotina e essa
segunda não passa à primeira nenhum valor por parâmetro. Vamos ao nosso Visual

FACULDADE CATÓLICA PAULISTA | 93


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Studio Code, onde temos nosso programa de cálculos prontos. Ainda podemos otimizá-
lo utilizando parâmetros nas funções e diminuindo significativamente a quantidade
de código. Usamos a passagem de parâmetro por valor quando há necessidade de
passar algum conteúdo à sub-rotina chamada.
O conteúdo passado pelo parâmetro na chamada da sub-rotina é copiado a partir
da chamada para a sub-rotina chamada. Qualquer modificação na variável local da
sub-rotina não afetará o valor do parâmetro passado, ficando assim o resultado fixado
na área de abrangência da sub-rotina chamada (MANZANO, 2014). Modificaremos as
funções das operações para que elas estejam preparadas para receber os valores do
parâmetro:

FACULDADE CATÓLICA PAULISTA | 94


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Como pode ser visto, a quantidade de código das funções reduziu drasticamente.
No exemplo do capítulo anterior, dentro de cada função havia os códigos de entrada
de dados para as variáveis A e B. Agora, note que essas variáveis estão declaradas
nas funções: static double Adicao(double a, double b) onde as variáveis
double a e double b os parâmetros que serão passados pela função Main() conforme
a seguir:

Note as mudanças na função Main(): Agora, após a execução do Menu(), o usuário


vai digitar os números que ele quer na operação ANTES de chamar as funções, e não
DENTRO das funções como vimos no capítulo anterior. Os valores serão armazenados
nas variáveis A e B, declaradas LOCAIS na função Main() e enviadas via parâmetro
nas funções das operações, dentro dos parêntesis: Adicao(a,b).
Ao executarmos o código acima, temos:

FACULDADE CATÓLICA PAULISTA | 95


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

12.2. Passagem de parâmetro por referência

A passagem de parâmetro por referência ocorre quando uma sub-rotina envia


um conteúdo para outra sub-rotina e aguarda um retorno nesse parâmetro com um
conteúdo processado. São parâmetros de entrada e saída, o que significa que eles
podem ser usados tanto para passar um valor para uma função ou receber de volta
esse valor de uma função.
Parâmetros por referência são criados precedendo um tipo de dado com o modificador
ref. Sempre que um parâmetro ref é passado é uma referência da variável que é passada
para a função. Ao passar o parâmetro por referência, se o valor deste parâmetro for
alterado dentro da subfunção que foi chamada, o valor dele também será alterado na
subfunção que chamou. Temos como exemplo:

static void Metodo(ref int Param1)


{
Param1 = Param1 + 100;
}

static void Main()


{
int valor = 5;
Metodo(ref valor);
Console.WriteLine(“Valor na Main = “ + valor);
}

No exemplo acima nota-se que a função Main() atribuiu 5 para a variável valor. Feito
isso, chamando-se a função, passando a variável valor como referência Metodo(ref

FACULDADE CATÓLICA PAULISTA | 96


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

valor), dentro da função Metodo, o valor Param1 que é recebido pela variável valor é
alterado. Ao voltar na função Main() será demonstrado o valor 105 na linha Console.
WriteLine(“Valor na Main = “ + valor); porque foi passado como
referência. Vamos preparar nosso Visual Studio Code para exemplificarmos o conceito,
otimizando nosso programa de cálculos:

ANOTE ISSO

Boas práticas de programação requerem otimização de código. No exemplo a


seguir vamos colocar em funcionamento métodos para minimizar a chance de
erros, fazendo com que tenhamos o mínimo de métodos possíveis. No caso a
seguir teremos apenas UM método de cálculo cuja operação e valores serão
passados por parâmetro, sendo que, no final, a execução será a mesma dos
exemplos anteriores.

Primeiramente, reescreveremos a função Main() que, depois de otimizada, ficará


assim:

FACULDADE CATÓLICA PAULISTA | 97


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Vamos entender as principais alterações na função Main() se compararmos aos


exemplos anteriores:
• Retiramos a variável resultado; no caso, a variável foi retirada pelo fato de agora,
passando por parâmetro, poderemos utilizar como resultado a própria variável
A, na qual veremos a seguir;
• Foi criada a variável TipoOperacao do tipo string, que servirá para informarmos
ao usuário qual foi a opção escolhida na execução do programa;
• Após executar a função Menu() é feita uma validação de valor. Se a opção não
for igual a 9 (Sair), ele nem entra no restante do código, encerrando o laço do
... while .
• Foi criada uma função do tipo bool chamada Calcular(), a qual veremos à
seguir, que recebe os parâmetros necessários para a execução das operações
selecionadas, que será explicada a seguir na sua totalidade.

A Função Calcular() é a função principal do programa. Ela foi feita para retornar o valor
bool, pois dentro dela teremos uma validação de conteúdo. Caso o conteúdo validado
esteja OK, a função irá retornar o valor True, caso contrário, False. Sua declaração
pode ser analisada a seguir:

Bem como sua chamada:

São definidos:
• O tipo bool, como foi explicado anteriormente, é para que ela retorne True caso
dê tudo certo.
• O parâmetro de referência declarado como tpOper, na sua chamada é passada
à variável TipoOperacao, que será atribuído o tipo de operação.
• O parâmetro de valor opMenu que recebe o valor da variável opcao em sua
chamada, é a opção digitada pelo usuário no Menu().
• O parâmetro A, que recebe a variável A, que agora, como é passado por referência,
servirá para que seja atribuído o resultado da operação, já que não temos mais
a variável resultado como foi visto no exemplo anterior.
• O parâmetro B recebe como valor a variável B, que é o segundo número utilizado
no exemplo de operação.

FACULDADE CATÓLICA PAULISTA | 98


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

A seguir, como ficou a função Calcular() na sua totalidade:

Vamos entender as principais atribuições na função Calcular() se compararmos


aos exemplos anteriores:
• Não precisamos mais das funções separadas Adicao(), Subtracao(), Multiplicacao(),
e Divisao(), tendo todos os cálculos unificados;
• O laço do ... while está na função principal, fazendo com que, em alguma parte
do código, possa ser chamada a função Calcular() sem que entre em um menu,
de forma direta;
• Se a estrutura de repetição switch() receber algum valor que seja diferente dos
apresentados no Menu() a função toda retornará False, que será tratada no
programa principal como

FACULDADE CATÓLICA PAULISTA | 99


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

• Não foi declarada NENHUMA variável dentro da função Calcular(). Todos os


valores manipulados vêm do parâmetro. Em um programa pequeno, como nosso
exemplo, o ganho de performance é mínimo. Porém, em grandes aplicações,
quanto mais variáveis declaradas, maior o espaço de memória utilizado na
execução do programa.
• Dentro de cada bloco do case temos apenas DUAS linhas. Uma delas atribui
a string da operação utilizada e a outra atribui ao parâmetro A o resultado da
operação desejada com o parâmetro B.
• Caso o bloco case seja executado corretamente, isto é, a opção digitada for
válida, a função calcular() terá como retorno o valor True, quel, na função Main()
apresenta o resultado da operação:

ANOTE ISSO

O parâmetro out é um parâmetro «emissor», o que significa que seu valor somente
é passado de uma função. Sempre que um parâmetro out é passado, somente a
referência da variável é passada para a função.

static void Metodo(out int Param1)


{
Param1 = 100;
Console.WriteLine(“Valor em Metodo = “ + Param1);
}

static void Main()
{
int valor = 5;
Metodo(out valor);
Console.WriteLine(“Valor na Main = “ + valor);
Console.Read();
}
}
A saída no exemplo acima na função Main() será 100, uma vez que o valor do
parâmetro out é passado de volta ao código chamador. Perceba que o modificador out
deve preceder o parâmetro que está sendo passado no código chamador do método.

FACULDADE CATÓLICA PAULISTA | 100


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Um dos motivos para a otimização do código é que sabemos que os programas


são dinâmicos. Vamos supor que nosso programa de exemplo de cálculo foi um pedido
de um cliente. Fizemos o programa como ele pediu, com as quatro operações básicas.
Porém, passado um tempo, ele solicitou que fossem colocadas mais duas operações:
Exponenciação e Porcentagem. Se nós estivéssemos no código antigo, teríamos que
desenvolver mais duas novas funções Exponenciacao() e Porcentagem(), declarar as
variáveis res, a e b em cada uma das funções, alterar os métodos Menu() e Main().
Normalmente o método Main() é o que deve ser menos alterado, pois é o método
principal do programa. Com essa otimização, teremos poucas alterações apenas no
Menu() com as novas opções e no Calcular() com as novas operações, ficando assim:

Foram inseridas apenas duas linhas na função Menu() demonstrando novas opções
a serem adicionadas.

FACULDADE CATÓLICA PAULISTA | 101


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Agora, vamos adicionar a programação à função Calcular():

FACULDADE CATÓLICA PAULISTA | 102


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

E a função Main()? Não precisamos alterar sequer uma linha nela. Com algumas
poucas linhas, sem precisar alterar a função principal, temos nosso programa rodando:

ANOTE ISSO

Apareceram duas novidades no exemplo acima:

O código em verde, iniciado com “//” significa “Comentário” no nosso ambiente de


programação. Quando há alguma explicação feita pelo programador para que o
código seja entendido, ele utiliza o comentário para ilustrar. O comentário não é
interpretado pelo compilador e pode ser de livre digitação. Serve, literalmente, para
comentar o que está sendo programado. Quando o comentário foi de apenas uma
linha, como visto aqui, usa-se as duas barras. Mas, quando quiser comentar um
bloco grande, usa-se /* para iniciar e */ para encerrar:

Agora, quanto à função Math.Pow() veremos no próximo capítulo, no qual


trataremos das funções especiais do C#.

FACULDADE CATÓLICA PAULISTA | 103


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 11
PRINCIPAIS FUNÇÕES DO C#

A linguagem C# oferece, de forma nativa, acesso a algumas funções. Há também


a possibilidade de agregar componentes pré-definidos desenvolvidos por terceiros.
Essas estruturas são conhecidas por Frameworks.

Fonte: https://motc.gov.qa/sites/default/files/c-programming.png

Antes de entendermos o conceito de Framework exemplificaremos algumas funções


matemáticas e de string, que são muito utilizadas no dia a dia.

11.1. Classe Nativa Math()

Essa classe contém algumas funções matemáticas muito úteis no desenvolvimento


do sistema. Existem várias funções dentro dessa classe que retornam valores calculados
que foram apresentados em seus argumentos. Veremos alguns exemplos usuais desta
função:

• Exponenciação: vimos no final do capítulo anterior um exemplo da função Math.


Pow(double,double), em que, ao passarmos os argumentos, retorna-se o resultado
da exponenciação. Math.Pow(a,b), que apresentará como resultado ab sendo que
a e b têm que ser do tipo double.

FACULDADE CATÓLICA PAULISTA | 104


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

• Arredondamento: Round(Decimal), arredonda um valor decimal para o valor inteiro


mais próximo e arredonda os valores de ponto médio para o número mais próximo:

• A função de arredondamento possui outra assinatura. Você se lembra que vimos


a Sobrecarga na primeira aula? Então. A função é a mesma: Double(). O que muda,
é a assinatura (argumentos). Nessa função usamos a sintaxe Round(Double, Int32).
Neste caso, o segundo argumento é utilizado para especificar a quantidade de
casas decimais a serem arredondadas:

• Absoluto, onde retorna seu valor numérico sem seu sinal. A sintaxe Abs(decimal)
retorna:

• Funções trigonométricas, como Seno, Cosseno e Tangente são representadas


pelas funções Math.sin(), Math.cos() e Math.tan(), respectivamente, passando um
número entre -1 e 1 como argumento.

11.2. Funções de String

Agora, testaremos algumas das várias funções para String do C#. Por serem várias,
a ideia é utilizar as principais. Para isso, podemos apagar o conteúdo da função Main(),

FACULDADE CATÓLICA PAULISTA | 105


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

o que eu não recomendo, ou simplesmente comentar todo o código desta função,


para que não se perca o que já foi feito. Agora, vamos declarar uma variável com o
seguinte conteúdo:
string strExemplo = “ abcd EFGHIJ klmnop QRST vwxyz “;
Note que existem alguns valores em minúsculo, outros em maiúsculo e espaços
no início e no final.

11.2.1. ToUpper - Converter toda a string para maiúsculo

Criaremos uma nova variável chamada maiusculo e passaremos a nossa original


chamando a função. Depois imprimiremos este valor no console:

Ao executar, temos:

ANOTE ISSO

Há outra maneira de colocar o conteúdo da variável em uma string. Vimos em


exemplos anteriores que usando o sinal + dentro da string há a concatenação dos
conteúdos. Se fizéssemos isso no exemplo acima, ficaria:

O outro método foi como utilizamos no exemplo acima. Iniciamos a string com o
símbolo $ antes de abrir as aspas e colocamos o conteúdo das variáveis dentro das
chaves { }. O resultado prático é o mesmo e as duas maneiras estão corretas.

FACULDADE CATÓLICA PAULISTA | 106


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

11.2.2. ToLower - Converter toda a string para minúsculo

Embaixo do exemplo anterior, digite o seguinte código:

Ao executar, temos:

11.2.3. Trim - Remover espaços do início e fim da string

Pule uma linha e insira o código abaixo:

Execute seu código e você terá uma saída semelhante a essa:

11.2.4. IndexOf - Buscar a primeira ocorrência de um valor dentro da string

Neste caso buscaremos a posição da primeira ocorrência da string “bc”, poderia


ser qualquer outro valor. Mesmo que não exista este valor o retorno seria -1.

Ao executarmos, temos:

FACULDADE CATÓLICA PAULISTA | 107


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Neste caso, a string “bc” se inicia na posição 5 da variável strExemplo.

11.2.5. LastIndexOf - Buscar a última ocorrência de um valor da string

Para esta função, vamos mudar o conteúdo da variável strExemplo para:


string strExemplo = “ abcd EFGHIJ klmnop QRST vwxyz abcd “

Neste caso, faremos ao contrário da função acima e retornaremos à posição da


última ocorrência de “bc”.

Ao executarmos:

Neste caso, significa que a última ocorrência da string “bc” se inicia na posição 38
do conteúdo da variável strExemplo.

12.2.6. Substring - Recortar a string a partir de uma posição, podendo ou não


limitar o tamanho deste recorte

Sem limitar o recorte:

Limitando o recorte:

FACULDADE CATÓLICA PAULISTA | 108


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executarmos:

Note que, no primeiro caso, sem limitar o corte, foi retornada parte da string iniciando
a partir da posição 4 até o final da string. Limitando o corte, no segundo caso, é
retornada a string.

11.2.7. Replace - Substituir um caractere ou parte da string por outra

Esta função recebe dois argumentos (parâmetros) e substitui os valores apresentados.

No exemplo acima, a função substituirá na string strExemplo todas as ocorrências


de “a” para “W”, no primeiro exemplo, e no segundo exemplo todas as ocorrências de
“abc” para “wyz”. Ao executar temos:

11.2.8. Converter número para string

É muito útil a conversão de números para string. Neste caso o C# fornece uma
função para converter o número em diversos formatos diferentes. É a função ToString(),
que aceita diversos parâmetros que servirão para cada um dos formatos:

Ao executar, temos:

FACULDADE CATÓLICA PAULISTA | 109


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

No exemplo acima, definimos as variáveis str1, str2, str3 e str4 recebendo o valor
3, já convertendo para o argumento pré-definido:
• Sem argumento (): retorna o número como é digitado.
• Argumento (“C”): retorna no formato de moeda com as casas decimais padrão.
Neste caso, o padrão do Windows.
• Argumento (“C3”): retorna no formato de moeda com as casas decimais definidas.
No exemplo, 3 casas decimais.
• Argumento (“F2”): retorna no formato de um número decimal, com as casas
decimais definidas, no exemplo, com duas casas.

ISTO ESTÁ NA REDE

No site da Microsoft, demonstrado a seguir, https://docs.microsoft.com/pt-br/dotnet/


standard/base-types/standard-numeric-format-strings é possível verificar diversos
argumentos para a função ToString() com exemplos. Veja os exemplos e o teste no
Visual Studio Code, nos quais será possível ver a infinidade de recursos disponíveis.

ANOTE ISSO

Uma possibilidade é o programador se utilizar de uma biblioteca de classes. A biblioteca


de classes define tipos e métodos que são chamados por um aplicativo. Se a biblioteca
for .NET Standard 2.0, ela poderá ser chamada por qualquer implementação do .NET
(incluindo .NET Framework) que dá suporte .NET Standard 2.0.

Fonte: https://dotnet.microsoft.com/static/images/illustrations/swimlane-operating-systems.svg?v=N_fhFXVLGtIWZteO-psDLzC_ZY22DmT3-b6XfPh_PDM

Ao criar uma biblioteca de classes, é possível distribuí-la como um pacote ou como um


componente agrupado com o aplicativo que o usa.

FACULDADE CATÓLICA PAULISTA | 110


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 12
MANIPULAÇÃO DE
VETORES (ARRAY)

Um vetor, conhecido em programação como array, é um conjunto de um ou mais


valores, do mesmo tipo, armazenados em endereços adjacentes de memória. Cada
valor é chamado de “elemento do array” e, assim como para variáveis simples, damos
um nome ao array. O tamanho do array é o seu número de elementos, onde, cada
elemento do array é numerado, usando o índice, representado por um número inteiro.
Em C# os índices de listas são “zero-based”, ou seja, começam a contar do zero (0)
e não do um (1) como estamos acostumados em nosso dia-a-dia (Rodrigues, 2021).

Fonte: https://www.blogson.com.br/wp-content/uploads/2020/11/2820053-637286284193596179-16x91-1.jpg

Quando se busca tratar com listas de um determinado tipo-valor de dado, o uso


de arrays pode ser a melhor alternativa, uma vez que o acesso aos elementos é
consideravelmente rápido, pois os valores são armazenados diretamente na memória.

FACULDADE CATÓLICA PAULISTA | 111


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Vetores podem ser tanto listas simples e sequenciais, como coleções compostas,
ou seja, podem possuir tanto apenas uma como várias dimensões:
• Com uma dimensão é chamada simplesmente de vetor;

Fonte: http://www.linhadecodigo.com.br/artigos/img_artigos/Joel_Rodrigues/ArraysCsharp/ArraysEmCSharpTeoriaEPratica1.jpg

• Enquanto com várias dimensões é chamado de MATRIZ, assim como àquela


estudada na álgebra.

Fonte: http://www.linhadecodigo.com.br/artigos/img_artigos/Joel_Rodrigues/ArraysCsharp/ArraysEmCSharpTeoriaEPratica2.jpg

12.1. Acesso à memória

Quando é declarado um vetor de algum tipo determinado, uma região sequencial


na memória com capacidade bastante para comportar todos os itens da lista fica
reservada. Uma quantidade do tamanho do tipo é dedicada ao armazenamento dos
itens do vetor. Por exemplo, sabendo que uma variável do tipo int ocupa 4 bytes na
memória, se declararmos um vetor com capacidade para 3 elementos deste tipo,
serão reservados 12 bytes na memória (de forma sequencial).

FACULDADE CATÓLICA PAULISTA | 112


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Fonte: http://www.linhadecodigo.com.br/artigos/img_artigos/Joel_Rodrigues/ArraysCsharp/ArraysEmCSharpTeoriaEPratica4.jpg

Na Figura acima, há a ilustração da região da memória de 20 bytes sequenciais.


Os quadros em vermelho indicam uma possível forma de alocação de espaço para
armazenamento do vetor que foi exemplificado no parágrafo anterior, onde observam-
se os 12 bytes, do 002 ao 013. Este espaço só é liberado quando o vetor é destruído
(Rodrigues, 2021).

12.2. Matrizes denteadas (Arrays “Jagged”)

Os chamados ‘jagged arrays’ são um tipo a mais de array, onde cada elemento é
um vetor. Supõe-se um vetor que armazena as turmas de uma escola e, para cada
turma, há um número diferente de alunos dos quais é preciso armazenar o código.
Ao usar uma matriz, onde as linhas representariam a turma e as colunas
representariam os alunos, poderia haver uma limitação, onde o número de alunos
seria fixo para todas as turmas. Aqui entram as matrizes denteadas, onde pode ter
um vetor que comporte a quantidade de turmas e cada elemento é um vetor, cujo
comprimento varia e podemos definir individualmente.

12.3. Vetores em C#

12.3.1. Declaração

A declaração de vetores é muito parecida com a definição de variáveis. A única


diferença é que é necessário especificar seu tamanho (quantos elementos ele tem).
Os colchetes “[“e “]” são usados na definição do vetor.

FACULDADE CATÓLICA PAULISTA | 113


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

No exemplo acima foram declarados dois vetores: números, no qual armazenará


o tipo int e nomes, no qual terá strings como elementos.

12.3.2. Inicialização

Neste caso, teremos uma situação diferente das variáveis. Quando uma variável é
declarada, ela já está pronta para ser utilizada. No caso de vetores, primeiramente é
declarado o tipo do vetor, como foi visto acima. Feito isso, será feita a inicialização
deste vetor, onde, agora sim, serão definidos os espaços de memória:

Neste caso, foram inicializados os vetores, sendo definido, em memória, que cada
um deles terá 10 espaços.

ANOTE ISSO

A declaração e inicialização podem estar na mesma linha de código. O vetor pode


ser criado e inicializado junto com a declaração, conforme visto abaixo:

12.3.3. Exemplos práticos

Agora, vamos ao Visual Studio Code para podermos exemplificar, na prática, como
utilizamos o vetor. Vamos declarar dois vetores com 3 posições, diferente do de 10
posições declarados acima, para conseguirmos ilustrar a manipulação das posições.
Digite o código conforme abaixo no VS Code:

FACULDADE CATÓLICA PAULISTA | 114


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

O código acima representa a manipulação de vetores de 3 elementos, onde o usuário


digita o nome que ele quer na posição e o vetor numeros recebe a sequência numérica.
Note que iniciamos pela posição 0, justamente por causa do conceito, já explicado
acima, do zero-based.
Ao executarmos a rotina acima, temos:

No exemplo acima temos um pequeno problema. Para preencher um vetor de


3 posições até que foi tranquilo, pois o vetor era pequeno. E se aumentássemos o
vetor? Precisaríamos aumentar a quantidade de código? Agora, vamos exemplificar
o preenchimento utilizando o laço de repetição for() , no qual vamos aumentar para
10 o tamanho do vetor e otimizar a quantidade de código.

FACULDADE CATÓLICA PAULISTA | 115


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Com o código acima, conseguirmos preencher o mesmo vetor, porém aumentando


para 10 posições.

ISSO ACONTECE NA PRÁTICA

Insistiremos no caso do zero-based, pois ele é responsável por algumas confusões.


Note que o laço for() começa do 0 e vai até “menor que 10”, que pode ser entendido
por 9. Se fosse utilizado o código também daria certo.
Isto influenciou também o preenchimento do vetor numero, onde o valor recebe
a variável do laço “i” acrescido de 1, para que consigamos adequar à nossa rotina
onde os números começam por 1.

FACULDADE CATÓLICA PAULISTA | 116


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executarmos a rotina, temos:

(...)

Note que uma quantidade significativamente menor de código, se comparado com


o exemplo onde tínhamos 3 posições. Para finalizarmos o exemplo, calcularemos a
média de uma turma de 20 alunos, onde digitaremos as notas e no final apuraremos
a média da sala:

FACULDADE CATÓLICA PAULISTA | 117


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

O código acima faz com que sejam digitados os nomes e as notas de 20 alunos,
no qual é preenchido o vetor nomes[] e notas[]. Depois de digitados os valores, o vetor
é novamente percorrido, para que se alimente a variável media. Ao executar, temos:

(...)

Note que foram executadas 20 vezes cada código, e no final, o vetor foi percorrido
novamente, tendo as notas somadas. Feito o percurso final, a variável, já somada com
todas as notas, é apresentada com a média das notas dos alunos.

FACULDADE CATÓLICA PAULISTA | 118


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ISSO ESTÁ NA REDE

No site da Microsoft é possível encontrar vários exemplos simples e funcionais


de uso de vetores, vale a pena dar uma conferida para melhorar os estudos.
Para verificar, acesse o link https://docs.microsoft.com/pt-br/dotnet/api/system.
array?view=net-5.0

FACULDADE CATÓLICA PAULISTA | 119


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 13
MANIPULAÇÃO DE MATRIZES

Vimos no capítulo anterior a manipulação de vetores de apenas uma dimensão. Nos


nossos exemplos, fizemos o percurso em pelo menos dois vetores. Porém, podemos
utilizar uma estrutura com várias dimensões, que é chamada de Matriz. O nome deriva
da estrutura que vimos em matemática, onde ocorrem os cálculos e definições de
Matriz.

Fonte https://maiscommenosmatematica.com/wp-content/uploads/2020/06/matriz-quadrada.png

Vimos também a estrutura, que pode ser bidimensional,

Fonte: http://www.linhadecodigo.com.br/artigos/img_artigos/Joel_Rodrigues/ArraysCsharp/ArraysEmCSharpTeoriaEPratica2.jpg

FACULDADE CATÓLICA PAULISTA | 120


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ou denteada:

Fonte: https://i.stack.imgur.com/KDfnM.gif

13.1. Declaração e inicialização

Assim como no vetor, a inicialização é tão, ou mais, importante do que a declaração.


A sintaxe é muito parecida, apenas informando quantas dimensões terá a matriz. Como
vimos anteriormente, a inicialização pode ser feita junto com a declaração, conforme
a declaração do vetor de uma dimensão.

13.1.1. Matriz bidimensional

Para entendermos o conceito da matriz bidimensional, usaremos como exemplo


uma planilha em Excel, onde as células correspondem a um espaço de memória:

No exemplo acima, como podemos acessar, por exemplo, o número “14”? Podemos
ver que ele está na posição B3. Isto é, Coluna B, linha 3. Esta posição é chamada de

FACULDADE CATÓLICA PAULISTA | 121


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

“coordenada”. Na matriz de duas dimensões o procedimento é o mesmo. Acessamos


as posições via coordenada. A diferença, especificamente no C#, é que as coordenadas
são definidas por número:

Note que no exemplo acima, o número 14 se encontra na posição [1,2], sendo Coluna
1 e Linha 2, não se esquecendo o conceito zero-based onde as posições se iniciam em
zero. Vamos para o Visual Studio Code fazer uma matriz desde sua declaração até
a inserção das informações, para fazê-la ficar igual ao exemplo acima? Iniciaremos
com a declaração e inicialização:

Feito isso, vamos atribuir os valores às coordenadas e apresentar em tela o resultado


da matriz:

FACULDADE CATÓLICA PAULISTA | 122


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executarmos o código acima, temos:

Assim como nos vetores, podemos também otimizar o código para que a matriz seja
gerada através de estruturas de repetição, bem como preenchermos os valores nas
coordenadas da maneira que quisermos. Podemos também, tanto nos vetores quanto
nas matrizes, dimensionar da maneira que quisermos. Para isso, a inicialização da matriz
é feita após a declaração. Exemplificaremos, no Visual Studio Code, uma matriz na qual
o usuário vai definir sua estrutura e preencher os valores de acordo com a declaração:

FACULDADE CATÓLICA PAULISTA | 123


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

Note que ao mostrar na tela os valores da matriz, utilizamos a função Console.


Write() ao invés de Console.WriteLine() justamente por que o segundo comando
faz com que o console vá para a linha abaixo. O mesmo serve para o comando
Console.Readline() onde seu substituto é Console.Read().

Ao rodar o programa e preencher com os valores do primeiro exemplo, teremos:

FACULDADE CATÓLICA PAULISTA | 124


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

Assim como aprendemos em matemática, para facilitar o conceito de coordenadas


para a matriz, utilizamos as variáveis “i” e “j”. Isso não é obrigatório. Porém, serve
como padronização do conteúdo de linhas e coordenadas.

Fonte: http://s3-sa-east-1.amazonaws.com/descomplica-blog/wp-content/uploads/2015/08/matriz.png

Ao analisar o código acima, nota-se que ele é praticamente do mesmo tamanho do


primeiro exemplo, e, no caso, retornou a mesma matriz. Porém, porque ao utilizar o
segundo exemplo temos a facilidade de dimensionar o tamanho da matriz. No primeiro
exemplo estávamos limitados à matriz[4,3].

13.1.2. Matriz Denteadas (Array “Jagged”)

Como vimos no capítulo passado, podemos ter as matrizes denteadas, onde cada
elemento é um vetor. Vamos ao exemplo no Visual Studio Code, onde utilizaremos
um Array Jagged para armazenar turmas com vários alunos cada uma.

FACULDADE CATÓLICA PAULISTA | 125


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Note que foram usados, novamente, os laços i e j para a manipulação. Neste


caso, com a declaração da Matriz Denteada, temos “vetores dentro de vetores”. Ao
executarmos a rotina acima, considerando turmas com 3 alunos temos:

FACULDADE CATÓLICA PAULISTA | 126


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Ao executarmos a rotina, notamos acima que foram criados vetores dentro de


vetores. Neste caso, tivemos a matriz denteada.

ISSO ESTÁ NA REDE

A plataforma da Microsoft que tem vários tutoriais e exemplos sobre o C#


desenvolveu um artigo interessante sobre Matrizes Denteadas, que pode ser
conferido aqui: https://docs.microsoft.com/pt-br/dotnet/csharp/programming-guide/
arrays/jagged-arrays

13.2. Ordenação e Pesquisa

Ordenação e pesquisa de elementos em matrizes são atividades requisitadas no


trabalho de programação. Existem algumas técnicas para realizarmos esse tipo de
trabalho. No entanto, a linguagem C# possui métodos internos que efetuam facilmente
essas operações sem que precisemos nos preocupar com suas questões lógicas.
Abaixo, vamos fazer um exemplo no Visual Studio Code para ordenar uma matriz:

FACULDADE CATÓLICA PAULISTA | 127


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

A operação de ordenação é executada pela instrução Array.Sort<int>(A), em


que o método Array.Sort do tipo int efetua a ordenação crescente na variável indicada.
No caso de uma ordenação decrescente, basta colocar imediatamente após a instrução
Array.Sort<int>(A) a instrução Array.Reverse(A). Ao executarmos o código
acima, temos:

FACULDADE CATÓLICA PAULISTA | 128


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 14
RECURSIVIDADE,
TRATAMENTO DE EXCEÇÕES
E PERSISTÊNCIA DE DADOS

14.1. Recursividade

Capacidade que uma linguagem tem de permitir que uma função possa invocar a
si mesma. A recursividade pode ser direta, onde uma função invoca a si mesma no
seu corpo de função, ou indireta, onde a função f invoca uma outra função g que, por
sua vez, volta a invocar a função f.

Fonte: Adaptado de https://blog.da2k.com.br/uploads/2015/02/recursion.jpg

FACULDADE CATÓLICA PAULISTA | 129


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Qualquer função em um programa C# pode ser chamada recursivamente, ou seja,


pode chamar a si mesma. Os parâmetros só são diretamente acessíveis para a instância
da função na qual são criados. Os parâmetros anteriores não são diretamente acessíveis
para instâncias resultantes da função.
Como exemplo, faremos duas funções, uma sem a recursividade e outra utilizando a
recursividade. No Visual Studio Code, faremos a função para calcular um valor fatorial
( ! ), onde n! = n * (n-1) * (n-2) * ..... * 2 * 1, sabendo que 0! = 1.
Sem recursividade, o código fica:

Até que não é um código tão complexo. Mas, no caso, precisamos executar um laço
para que o resultado seja apresentado. Como já vimos anteriormente, poupar recursos
é imprescindível para um bom sistema. No caso, o laço pode ocupar processamento e
memória, dependendo do tamanho do valor a ser calculado. Porém, vamos exemplificar
o mesmo código, utilizando a função recursiva:

FACULDADE CATÓLICA PAULISTA | 130


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Note que o programa principal possui apenas 3 linhas e não possui laço de repetição.
A função fat() será chamada dentro dela mesma quantas vezes forem necessárias,
de acordo com o parâmetro passado. Ao executarmos, temos:

Como segundo exemplo, vamos calcular a média de um vetor de inteiros, também


utilizando a recursividade:

Podemos ver que a função Media() foi executada dentro da própria função,
caracterizando-se a recursividade. Ao executarmos o código, temos:

FACULDADE CATÓLICA PAULISTA | 131


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

14.2. Exceções

Os sistemas devem ser capazes de tratar os erros que ocorrem em sua execução
de maneira consistente. Uma exceção é qualquer condição de erro ou comportamento
inesperado encontrado por um programa em execução. Exceções podem ser geradas
devido a uma falha no código ou no código que chamado, como uma função, recursos
do sistema operacional não disponíveis, condições inesperadas encontradas pelo
compilador.

Fonte: https://static.imasters.com.br/wp-content/uploads/2016/06/exce%C3%A7%C3%A3o-1.jpg

FACULDADE CATÓLICA PAULISTA | 132


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

O sistema pode se recuperar de algumas dessas condições, mas não de outras.


Embora você possa se recuperar da maioria das exceções de aplicativo, não é possível
recuperar-se da maioria das exceções em execução. No C#, uma exceção é um objeto
herdado da classe System.Exception. Uma exceção ocorre em uma área do código em
que ocorreu um problema.
Para entendermos, na prática, o que é uma exceção, tomaremos como exemplo o
código acima, em que apuramos a média de valores digitados em vetores. E se, ao
invés de digitarmos um número, digitássemos uma letra no lugar dos valores? Neste
caso, não tem como o compilador entender que o usuário vai digitar um valor errado
de uma variável. Por isso, o erro acontece durante a execução e, não, ao compilar o
código. Vejamos:

Note que a plataforma, no caso o Visual Studio Code, lançou uma exceção assim
que digitamos a letra “A” onde deveria ser digitado um número. A maneira como o
C# implementa o tratamento de exceção oferece as seguintes vantagens, Segundo
a Microsoft (2021):
O lançamento e tratamento de exceção funciona da mesma maneira
para linguagens de programação .NET.
Não requer nenhuma sintaxe de linguagem específica para tratamento
de exceção, mas permite que cada linguagem defina sua própria sintaxe.
Exceções podem ser geradas pelos limites de processo e até mesmo
de computador.
O código de tratamento de exceção pode ser adicionado a um
aplicativo para aumentar a confiabilidade do programa.
As exceções oferecem vantagens sobre outros métodos de notificação
de erro, como códigos de retorno. Falhas não passam despercebidas
porque se uma exceção for lançada e você não tratar dela, o runtime
encerra o aplicativo. Valores inválidos não continuam a se propagar
através do sistema como resultado do código que não consegue
verificar se há um código de retorno de falha.

FACULDADE CATÓLICA PAULISTA | 133


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Segundo MICROSOFT (2021), algumas das exceções comuns na plataforma C#:

Fonte: Microsoft (2021)

14.2.1. Tratamento de Exceções

A linguagem C# nos permite tratar as exceções. No caso, conseguiríamos, através


da programação, “prever” alguns erros que o sistema poderia causar em tempo de
execução. Para isso, existe a possibilidade de tentar executar um bloco de comando.
Caso não consiga, o sistema “joga” uma exceção personalizada na tela e, não mais,
um emaranhado de erros de sistema. A função a ser executada é a try catch() na
qual podemos tratar a informação que o usuário irá receber. Utilizaremos o mesmo
exemplo da recursividade, porém, agora, se o usuário digitar uma letra, o programa
avisará corretamente:

FACULDADE CATÓLICA PAULISTA | 134


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

No exemplo da exceção pudemos ver que o erro apresentado foi o


“FormatException”.

Por isso, ao tratarmos a exceção abaixo, no exemplo, utilizaremos este erro para
informar.

Note que a coleta dos números agora pertence toda ao bloco try catch(). Se ocorrer
alguma exceção relacionada ao formato, o sistema irá retornar uma mensagem tratada,
facilitando o entendimento do usuário:

FACULDADE CATÓLICA PAULISTA | 135


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ANOTE ISSO

Podemos colocar dentro do mesmo bloco try catch() vários catch() para tratarmos
as exceções do jeito que quisermos. Caso não tenha alguma exceção específica,
deixamos apenas o catch sem parâmetros:

ISSO ESTÁ NA REDE

Para verificar diversas variações das exceções, a plataforma do C$ da Microsoft


disponibiliza vários exemplos para serem testados, nos quais podem ser acessados
a seguir: https://docs.microsoft.com/pt-br/dotnet/csharp/language-reference/
keywords/try-catch

14.3. Persistência de Dados

Alguns anos atrás, durante a criação de sistemas, havia a necessidade de aplicar um


esforço muito grande em utilizar linguagens, como SQL, para inserir, alterar e excluir
informações em bancos de dados. Atualmente, após anos de desenvolvimento, há
mecanismos que facilitam essas operações e aliviam a carga dos desenvolvedores
de software. Assim, eles podem focar mais nas regras de negócio e no problema que
FACULDADE CATÓLICA PAULISTA | 136
PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

está sendo resolvido. Um desses mecanismos é o mapeamento objeto-relacional,


ORM (LEDUR, 2018). LEDUR (2018, p. 82 e 83) também cita:

O ORM, ou mapeamento objeto-relacional, é uma ferramenta/técnica


de programação usada para converter dados entre sistemas de
tipos incompatíveis usando linguagens de programação orientadas
a objetos. Isso cria, de fato, um banco de dados de objetos virtuais
que pode ser usado dentro da linguagem de programação.
Existem pacotes gratuitos e comerciais disponíveis que realizam o
mapeamento objeto-relacional, embora alguns programadores optem
por construir suas próprias ferramentas ORM.
Na programação orientada a objetos, as tarefas de gerenciamento
de dados atuam em objetos orientados a objetos (OO) que são quase
sempre valores não escalares. Por exemplo, considere uma entrada
do catálogo de endereços que representa uma pessoa única, com
zero ou mais números de telefone e zero ou mais endereços.
Isso pode ser modelado em uma implementação orientada a objeto
por um objeto Pessoa com atributos/campos para manter cada
item de dados que a entrada inclui: o nome da pessoa, uma lista de
números de telefone e uma lista de endereços.
A lista de números de telefone em si própria contém Objetos
PhoneNumber e assim por diante. A entrada do livro de endereços
é tratada como um único objeto pela linguagem de programação
(pode ser referenciada por uma única variável contendo um ponteiro
para o objeto, por exemplo). Vários métodos podem ser associados
ao objeto, como um método para retornar o número de telefone
preferido, o endereço residencial e assim por diante. No entanto,
muitos produtos de banco de dados populares, como sistemas de
gerenciamento de banco de dados SQL (DBMS), só podem armazenar
e manipular valores escalares, como números inteiros e cadeias
organizadas em tabelas.
O programador deve converter os valores dos objetos em grupos
de valores mais simples para armazenamento no banco de dados
(e convertê-los novamente após a recuperação), ou usar apenas
valores escalares simples dentro do programa. O mapeamento objeto-
relacional implementa a primeira abordagem.
O coração do problema envolve traduzir a representação lógica dos
objetos em uma forma atomizada capaz de ser armazenada no
banco de dados, preservando as propriedades dos objetos e seus
relacionamentos para que possam ser recarregados como objetos
quando necessário. Se essa funcionalidade de armazenamento
e recuperação for implementada, os objetos serão considerados
persistentes.

FACULDADE CATÓLICA PAULISTA | 137


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Fonte: Carson apud Ledur (2018)

ISSO ACONTECE NA PRÁTICA

Existem diversos Frameworks para acessar dados em C#, dentre elas o Entity
Framework, que pode ser baixado diretamente no Visual Studio e Visual Studio
Code. Mais informações e instruções de como utilizá-lo podem ser encontradas no
link abaixo: https://www.alura.com.br/conteudo/entity-framework-core-banco-pre-
existente-parte1?gclid=Cj0KCQjww4OMBhCUARIsAILndv79-MlQdkndoKhQ5ktco6dG
2besyLW6tDlel7OlHt6pQKTpfdxF6AAaAsUyEALw_wcB

FACULDADE CATÓLICA PAULISTA | 138


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

AULA 15
INTERFACES GRÁFICAS
E EVENTOS

Sistemas com interfaces gráficas foram grandes desafios da computação. Com a


evolução de ambientes de desenvolvimento, hoje, há um grande número de possibilidades
para a criação de aplicações. O Windows Forms é uma dessas possibilidades que
facilitam e aceleram a criação de sistemas de informação. Uma aplicação Windows
Forms é uma aplicação baseada em eventos suportada pelo .NET Framework da
Microsoft (LEDUR, 2018).

15.1. Aplicações Windows Forms

Fonte: http://videcursos.com.br/wp-content/uploads/2016/11/c-windows-form.png

O Windows Forms é uma biblioteca parte do Microsoft .NET Framework. Ele fornece
uma plataforma para escrever aplicativos para computadores de mesa, laptops e
tablets.
É uma aplicação baseada em eventos suportada pelo .NET Framework da Microsoft.
Ao contrário de um programa em lote, ele passa a maior parte do tempo simplesmente
esperando que o usuário faça algo, como preencher uma caixa de texto ou clicar
em um botão. O Windows Forms fornece acesso aos controles comuns nativos da
interface do usuário do Windows, envolvendo a API do Windows existente no código
gerenciado (FREEMAN, 2017 apud LEDUR, 2018).

FACULDADE CATÓLICA PAULISTA | 139


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ISSO ESTÁ NA REDE

O ambiente de desenvolvimento integrado (IDE – Integrated Development


Environment) utilizado para o C# voltado a Windows Form também pode ser o
Visual Studio. No caso, como vimos durante nossos exemplos anteriores, utilizamos
o Visual Studio Code. Agora, é apenas Visual Studio, que pode ser baixado
gratuitamente, em sua versão para estudante, no link a seguir:
https://visualstudio.microsoft.com/pt-br/downloads/

Fonte: https://visualstudio.microsoft.com/pt-br/downloads/

15.2. Criando uma aplicação Windows Forms

Já com o Visual Studio instalado, para darmos início a uma aplicação, seguimos
a sequência a seguir:

Arquivo > Novo > Projeto

Ao abrir a tela seguinte, vá para a opção a seguir:

FACULDADE CATÓLICA PAULISTA | 140


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Clique em “Próximo”, que estará na parte de baixo da tela. Feito isso, temos o
primeiro formulário (Form) no Visual Studio.

Após esse procedimento, mostraremos a Caixa de Ferramentas para que possamos


escolher os objetos que farão parte do nosso projeto, através do menu Exibir > Caixa
de Ferramentas.

FACULDADE CATÓLICA PAULISTA | 141


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Os elementos que estão dentro da caixa de ferramentas podem ser arrastados para
um modo de exibição. Qualquer ação adiciona o código fundamental para criar uma
instância do item no arquivo de projeto ativo. A caixa de ferramentas exibe apenas
os itens que são apropriados para o tipo de arquivo em que se está trabalhando. Se
o projeto requer um controle que não é compatível com o perfil de cliente, você pode
definir seu projeto para a estrutura inteira, editando as propriedades dele.
A seguir, você pode simplesmente arrastar um item da caixa de ferramentas para
o form. Faça um teste utilizando um button (que cria um botão no form):

Você pode simplesmente dar dois cliques na Caixa de Ferramentas, ou clicar em


Button na Caixa de Ferramentas e arrastar para o formulário.
Trabalhando com Windows Forms, além de mexer na caixa de ferramentas,
constantemente, tem de utilizar e alterar as propriedades dos elementos. Para isso, você
deve utilizar o componente Propriedades. Nele, pode modificar as características visuais,
comportamentais e estruturais dos seus elementos. Caso o acesso às propriedades não
esteja disponível na IDE, clique com o botão direito em cima do objeto e vá em Propriedades:

FACULDADE CATÓLICA PAULISTA | 142


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Feito isso, aparecerão as propriedades no Visual Studio:

Vamos mudar a propriedade “Text” para “OK”:

15.3. Eventos

Um evento é uma ação a que você pode responder ou que pode manipular no
código. Os eventos podem ser gerados por uma ação do usuário, como clicar no mouse
ou pressionar uma tecla. Eles também podem ser criados pelo código do programa
ou pelo sistema. Aplicações dirigidas por eventos executam o código em resposta
a um evento. Cada formulário e controle expõe um conjunto predefinido de eventos
programáveis. Se um desses eventos ocorre e existe um código no manipulador de
eventos associado, esse código é invocado (MICROSOFT, 2021).
Um manipulador de eventos é um método vinculado a um evento. Quando o evento
é gerado, o código dentro do manipulador de eventos é executado. Cada manipulador
de eventos fornece dois parâmetros que permitem manipular o evento corretamente.

FACULDADE CATÓLICA PAULISTA | 143


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

No código abaixo, você pode ver um manipulador de eventos para um evento de clique
do controle de botão.

Para aparecer o código acima, basta clicar duas vezes no botão inserido no Form.
Vamos colocar no evento “button1_Click()” um comando que será executado quando
for clicado o botão:

Depois de digitado o código, clique no botão para executar o código acima.


Com o programa executando, ao clicar no botão, será executado o código informado:

FACULDADE CATÓLICA PAULISTA | 144


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

O código que é invocado no evento tem a mesma sintaxe do que vimos nos exemplos
anteriores, o C#. Para isso, vamos exemplificar a manipulação de vetores, porém,
utilizando um evento de botão.
Vamos colocar um botão Button, um Label, um TextBox e um Rich Text Box. Mudamos
a propriedade Text do Label para “Digite a quantidade de elementos” e “Gerar Vetor”
na mesma propriedade Text do Button.

A seguir, vamos ao evento Leave da TextBox e implementaremos o código para


evitar que seja digitado um valor inválido para a quantidade de elementos da matriz.
Para acessar os eventos, basta selecionar o objeto e clicar em que fica na caixa
de propriedades:

FACULDADE CATÓLICA PAULISTA | 145


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Com 2 cliques no quadro a frente de onde está selecionado o evento Leave, deverá
aparecer o código abaixo:

Agora, dentro da função, vamos codificar a rotina para evitar que seja digitado um
valor inválido:

Ao executar o código acima e colocar um valor inválido no TextBox, aparecerá a


mensagem abaixo:

Note que:

FACULDADE CATÓLICA PAULISTA | 146


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

• foi criada uma variável pública chamada qtdeElementos, que foi utilizada para
receber o valor do textbox, convertido para inteiro:

• Foi colocado o comando que faz com que o foco do


TextBox não seja “liberado” enquanto não for digitado o valor correto, número.
Agora, vamos codificar o evento do Button que, ao ser clicado, gerará uma matriz
de números aleatórios na quantidade de elementos que for definida no TextBox:

O código acima vai gerar um vetor com valores aleatórios, gerados pela função
Random(), e irá preencher o vetor com os valores definidos. Não sem antes efetuar
a verificação se o valor foi digitado corretamente na quantidade de elementos. Caso
o botão seja clicado sem que seja informada a quantidade, o sistema retornará a
mensagem de que não pode ser vazio:

FACULDADE CATÓLICA PAULISTA | 147


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Caso seja digitado um valor na quantidade de elementos, o RichTextBox será


preenchido com o valor da matriz gerada:

A rotina de programação em interfaces gráficas e eventos é bem ampla. Vimos


apenas um pequeno exemplo de como podemos executar eventos em um sistema.
Toda a codificação é C#, assim como usamos no Visual Studio Code. O que diferencia
é justamente a saída dos dados, que, no caso da interface gráfica, podemos direcionar,
enquanto no Code é sempre via console. Fica a dica, ao mesmo tempo, a sugestão, para
que ambas interfaces sejam bem exploradas tendo como objetivo o aperfeiçoamento
da linguagem.

FACULDADE CATÓLICA PAULISTA | 148


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

CONCLUSÃO

A programação, quando explorada a fundo, oferece milhares de maneiras de se chegar


a um objetivo. Durante esse conteúdo você conseguiu verificar alguns métodos para
se iniciar no mundo da programação. São diversas opções de linguagens disponíveis
no mercado. Porém, a linguagem C# oferece várias funções e métodos fáceis e ágeis
para facilitar a vida, tanto na programação desktop, aquelas que são executadas no
computador, quanto na programação para internet.

Fonte: https://suporteninja.com/wp-content/uploads/2015/11/1431583113431.jpg

Sabemos que, mesmo com o final desta etapa, estamos apenas iniciando um
processo que, certamente, será de muito estudo e muitos desafios. Por isso, há muitos
materiais a serem pesquisados e desenvolvidos. A rotina e sequência de estudos trará
perspectivas de sucesso na profissão.

FACULDADE CATÓLICA PAULISTA | 149


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

ELEMENTOS COMPLEMENTARES

LIVRO

Título: Use a cabeça!: C#


Autor: Andrew Stellman, Jennifer Greene
Editora: Alta Books; 2ª edição (11 fevereiro 2013)
ISBN: 978-8576085591
Comentário: 2ª Edição é uma experiência completa
de aprendizagem para a programação com C#,
.NET Framework e IDE Visual Studio. Construído
para ser assimilado rapidamente pela sua mente,
este livro cobre o C# & .NET 4.0 e o Visual Studio
2010, e ensina tudo, desde a herança até a
serialização. Por que este livro parece ser tão
diferente? Acreditamos que seu tempo é muito
valioso para ser desperdiçado tendo dificuldades
com novos conceitos. Usando a última pesquisa
em ciência cognitiva e teoria do aprendizado para criar uma experiência de aprendizado
multissetorial, o Use a Cabeça! C# tem um formato visualmente rico, projetado para
a forma como seu cérebro funciona, não uma abordagem pesada que faz com que
você caia em sono profundo.

FACULDADE CATÓLICA PAULISTA | 150


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

Título: Código limpo: Habilidades práticas do Agile


Software
Autor: Robert C. Martin
Editora: Alta Books; 1ª edição (8 setembro 2009)
ISBN: 978-8576082675
Comentário: Mesmo um código ruim pode
funcionar. Mas, se ele não for limpo, pode acabar
com uma empresa de desenvolvimento. Perdem-
se a cada ano horas incontáveis e recursos
importantes devido a um código mal escrito. Mas
não precisa ser assim. O renomado especialista
em software, Robert C. Martin, apresenta um
paradigma revolucionário com Código limpo:
Habilidades Práticas do Agile Software. Martin se
reuniu com seus colegas do Mentor Object para destilar suas melhores e mais ágeis
práticas de limpar códigos “dinamicamente” em um livro que introduzirá gradualmente
dentro de você os valores da habilidade de um profissional de softwares e lhe tornar
um programador melhor –mas só se você praticar. Que tipo de trabalho você fará?
Você lerá códigos aqui, muitos códigos. E você deverá descobrir o que está correto e
errado nos códigos. O resultado será um conhecimento base que descreve a forma
como pensamos quando criamos, lemos e limpamos um código.

FACULDADE CATÓLICA PAULISTA | 151


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

REFERÊNCIAS

DAMAS, Luís; Linguagem C, 10ª edição. Rio de Janeiro: LTC, 2016.

LEDUR, Cleverson L. Desenvolvimento de sistemas com c#. Disponível em: Minha


Biblioteca, Grupo A, 2018.

MANZANO, José Augusto N. G. Programação de Computadores com C#. Disponível


em: Minha Biblioteca, Editora Saraiva, 2014.

MONTEIRO, E. R.; Junior, R.C. M.; Lima, B.S. D.; al., E. Sistemas Distribuídos. Porto
Alegre, SAGAH, 2020

MICROSOFT, Um Tour pela linguagem C#, Disponível em [https://docs.microsoft.


com/pt-br/dotnet/csharp/tour-of-csharp/], acesso em 14/10/2021
___________, Tratando e gerando exceções em .Net, Disponível em
[https://docs.microsoft.com/pt-br/dotnet/standard/exceptions/], acesso em
22/10/2021.

RODRIGUES, Joel; Arrays em C#, Teoria e Prática, disponível em [http://www.


linhadecodigo.com.br/artigo/3444/arrays-em-csharp-teoria-e-pratica.aspx] acesso
em 26/10/2021

SANTOS, M.G. D.; Saraiva, M.O. D.; Fátima, P.G. D. Linguagem de programação. Porto
Alegre, SAGAH, 2018

SOARES, Walace. PHP 5 - Conceitos, Programação e Integração com Banco de


Dados. Disponível em: Minha Biblioteca, (7th edição). Editora Saraiva, 2013.

SOMMERVILLE, I. Engenharia de Software. 9ª Ed. São Paulo. Pearson Prentice Hall.


2011 [Pearson Virtual]

FACULDADE CATÓLICA PAULISTA | 152


PROGRAMAÇÃO I
PROF. ESP. FRANCISCO
LUÍS BORGHI NASCIMENTO

UEHARA, Lincoln, Disponível em [https://www.embarcados.com.br/por-que-evitar-


variaveis-globais/], 2017, acesso em 26/09/2021

FACULDADE CATÓLICA PAULISTA | 153

Você também pode gostar