...
...
A nossa missão nesse post é criar um programa em C que permita registrar cada carta com informações detalhadas sobre as cidades, utilizando variáveis, operadores e funções de entrada e saída.
Cada carta conterá dados essenciais como: estado, código, nome da cidade, população, PIB, área e número de pontos turísticos.
Além disso, você também calculará e adicionará propriedades derivadas, como densidade populacional e PIB per capita, enriquecendo as informações estratégicas de cada carta.
O computador não tem discernimento para julgar se algo é certo ou errado.
No entanto, ele pode ser instruído a tomar decisões lógicas, baseadas em critérios objetivos, e seguir instruções ordenadas. Isso é o que chamamos de solução estruturada.
Programar é parecido com seguir uma receita.
Dividimos um problema grande em partes menores e mais gerenciáveis, o que torna a resolução mais fácil e organizada.
Voltando ao exemplo do bolo, na cozinha, isso é o que chamamos de mise em place.
Se os ingredientes e as etapas não forem organizados, o resultado pode ser um bolo malfeito.
Imagine que você tenha encontrado a receita de um bolo, mas ela esteja toda desorganizada.
Um ingrediente está listado no meio das instruções, e a temperatura do forno está no final do texto. Difícil de seguir, não é? O mesmo acontece com o código de um programa.
Um código bem organizado facilita a leitura e a manutenção não só para você, mas também para outras pessoas que possam trabalhar no seu projeto.
Para manter o código organizado e claro, podemos usar algumas práticas!
Espaço extra adicionado no início de uma linha de código para indicar que ela está dentro de um bloco de código.
Isso ajuda a visualizar blocos de código e entender a hierarquia das instruções.
A indentação facilita a leitura e a compreensão do código, pois é possível perceber visualmente quais linhas pertencem a que bloco de código.
São uma ferramenta essencial na programação, especialmente na linguagem C, pois ajudam a documentar o código, tornando-o mais legível e compreensível para outros programadores e para o próprio autor do código no futuro.
Eles são ignorados pelo compilador, o que significa que não afetam a execução do programa, mas fornecem informações valiosas sobre a lógica e a estrutura do código.
Use nomes de variáveis e funções que façam sentido. Por exemplo, em vez de x e y, use soma ou resultado. Você irá compreender melhor mais à frente.
O raciocínio lógico é a capacidade de pensar de maneira clara e ordenada.
Na programação, usamos o raciocínio lógico para resolver problemas de forma sistemática.
Já o pensamento computacional é um conjunto de habilidades que nos permite abordar problemas de maneira que um computador possa entender.
Para desenvolver essas habilidades, podemos seguir alguns passos. Acompanhe.
São procedimentos para resolver um problema, detalhando as ações a serem executadas e a ordem em que devem ocorrer.
Programar é como dar instruções para um computador fazer o que você quer, como se estivesse ensinando alguém a seguir uma receita. Isso envolve várias etapas.
Uma linguagem de programação é um conjunto de instruções que você pode usar para comunicar-se com um computador.
Uma linguagem de programação é um conjunto de instruções que você pode usar para comunicar-se com um computador.
As linguagens de programação foram desenvolvidas para facilitar a escrita de programas de computador, fornecendo uma maneira padronizada para que os programadores escrevam instruções que podem ser traduzidas em ações que um computador pode executar.
Conheça agora as características das linguagens de programação.
Quando escrevemos código em C, estamos usando uma linguagem que é mais fácil para nós, humanos, entendermos.
Mas o computador não fala C diretamente. Precisamos traduzir esse código para que o computador possa executar.
Aqui estão, de forma resumida, os passos desse processo. Confira!
Agora que você já conhece os conceitos fundamentais de programação, vamos colocar a mão na massa e criar seu primeiro programa em C.
Vamos criar um programa simples que exibe a mensagem "Olá, Mundo!" na tela.
Esse é o programa tradicional de introdução em muitas linguagens de programação.
#include <stdio.h>
int main() {
printf("Olá, Mundo!\\n");
return 0;
}
Esse código é bem simples. Ele tem apenas três partes principais:
#include
inclui a biblioteca padrão de entrada e saída, necessária para usar a função printf.int main()
é onde o programa começa a execução. Toda aplicação em C começa pela função main.printf("Olá, Mundo!\\n");
imprime a mensagem "Olá, Mundo!" na tela. O \n adiciona uma nova linha ao final da mensagem.return 0;
indica que o programa terminou com sucesso.Para que o computador entenda e execute o código, precisamos compilá-lo. Você precisará de uma IDE e um compilador instalados no seu computador.
Algumas opções populares incluem Code::Blocks, Dev-C++, e Visual Studio Code com extensões adequadas.
Vamos falar sobre variáveis e tipos de dados, dois conceitos fundamentais na programação.
Pense nas variáveis como caixas onde você pode armazenar informações.
Cada caixa tem um nome, e você pode usar esse nome para colocar algo dentro dela ou pegar o que está lá.
Em programação, essas caixas são usadas para guardar valores que podem mudar enquanto o programa está rodando.
Declarar uma variável é como criar uma caixa e dar um nome a ela.
Em C, a declaração de variáveis segue um formato específico, definindo primeiro o tipo de variável e depois o nome, isso é o que chamamos de sintaxe da declaração de variáveis.
Tipo_variável nome_variável
Vamos ver exemplos de declaração de variáveis:
int idade
— Declara uma variável inteira chamada "idade"float altura
— Declara uma variável de ponto flutuante chamada "altura"double salario
— Declara uma variável de ponto flutuante de dupla precisão chamada "salario"char opcao
— Declara uma variável de caractere chamada "opcao"Criar nomes de variáveis claros e significativos é uma prática essencial na programação. Aqui estão algumas regras e dicas para nomear variáveis em C:
Inicializar uma variável significa colocar um valor inicial dentro da caixa. Isso pode ser feito na mesma linha em que você declara a variável ou depois, no meio do seu código.
int idade = 25
— Declara "idade" e atribui o valor 25float altura
— Declara "altura" sem inicializaraltura = 1.75
— Atribui o valor 1.75 a "altura" posteriormentedouble salario = 3000.50
— Declara "salario" e atribui o valor 3000.50char opcao = 'S'
— Declara "opcao" e atribui o caractere ‘S’Aqui, estamos criando as variáveis e colocando valores iniciais nelas ao mesmo tempo.
Inicializar variáveis é importante porque, se você tentar usar uma variável que não foi inicializada, ela pode conter lixo (valores aleatórios) que podem causar erros no seu programa.
São como etiquetas que você coloca nas suas caixas (variáveis) para indicar que tipo de valor elas podem armazenar.
Diferentes tipos de dados são usados para diferentes propósitos. A Linguagem C tem 5 diferentes tipos básicos: char, int, float, void, double.
Além de armazenar caracteres individuais, podemos também trabalhar com sequências de caracteres, conhecidas como strings que são sequências de caracteres armazenadas como arrays (conjuntos) de char, terminadas por um caractere especial chamado caractere nulo (\0).
char nome[20] = "Alice"; // Declara um array de 20 caracteres e inicializa com "Alice"
No exemplo acima, nome pode armazenar até 19 caracteres mais o caractere nulo. A manipulação de strings requer cuidado para evitar buffer overflows (escrever além dos limites do array).
A função printf é usada para exibir informações na tela.
Pense em printf como uma maneira de pegar informações das suas "caixas" (variáveis) e mostrá-las ao mundo exterior.
printf("texto com formatação", variavel1, variavel2, ...);
Nesse exemplo, printf("Olá, Mundo!\\n");
imprime a mensagem "Olá, Mundo!" na tela. O \n no final adiciona uma nova linha, movendo o cursor para a linha seguinte.
Exemplo de uso com variáveis: ao utilizar o printf para imprimir variáveis, é necessário colocar o nome da variável e o especificador de formato. Veja a sintaxe a seguir.
printf(“%formato1 %formato2”, variável1, variável2);
Aqui, "%formato1 %formato2" são os especificadores de formato correspondentes aos tipos das variáveis que você deseja exibir.
Esses especificadores são elementos essenciais para controlar a formatação dos dados nas funções de entrada e saída da linguagem C, como printf e scanf.
Cada especificador de formato é precedido por um caractere % e indica o tipo de dado da variável que será exibida.
Para cada variável que você deseja imprimir, é necessário acrescentar um especificador de formato correspondente.
%d — Imprime um inteiro no formato decimal.
%i — Equivalente a %d.
%f — Imprime um número de ponto flutuante no formato padrão.
%e — Imprime um número de ponto flutuante na notação científica.
%c — Imprime um único caractere.
%s — Imprime uma cadeia (string) de caracteres.
#include <stdio.h>
int main() { int idade = 25; float altura = 1.75; double saldoBancario = 12345.67; char inicial = 'A'; char nome[20] = "Bruno";
printf("Idade: %d anos\\n", idade);
printf("Altura: %.2f metros\\n", altura);
printf("Saldo Bancário: %.2f reais\\n", saldoBancario);
printf("Inicial do Nome: %c\\n", inicial);
printf("Nome: %s\\n", nome);
return 0;
}
Essa é uma das formas mais comuns e úteis de ler dados do usuário em programas escritos em C.
scanf("formato", &variavel);
Aqui, "formato" especifica o tipo de dado que você espera que o usuário insira, e &variavel é o endereço da variável onde o dado será armazenado.
Vamos analisar um exemplo no qual solicitamos ao usuário que insira sua idade.
Lemos essa entrada e, em seguida, exibimos a idade inserida na tela. Este exemplo utiliza as funções printf e scanf.
#include <stdio.h>
int main() {
int idade;
printf("Digite sua idade: \\n");
scanf("%d", &idade);
printf("Sua idade é: %d\\n", idade);
return 0;
}
A função scanf também pode ser usada para ler strings do usuário, mas com uma importante ressalva: por padrão, ela lê apenas até o primeiro espaço em branco.
Isso significa que se o usuário digitar um nome completo (com espaços), apenas a primeira parte do nome (até o primeiro espaço) será lida.
char nome[50];
printf("Digite seu nome: ");
scanf("%s", nome);
printf("Nome digitado: %s\\n", nome);
Se o usuário digitar "João da Silva", apenas "João" será armazenado em nome. "da Silva" será deixado no buffer de entrada e poderá causar problemas em leituras subsequentes.
Para ler strings com espaços em branco, a função fgets é a melhor opção.
Ela lê uma linha inteira da entrada, incluindo espaços, até encontrar um caractere de nova linha (\n) ou atingir o tamanho máximo especificado.
char nome[50];
printf("Digite seu nome completo: ");
fgets(nome, 50, stdin); // Lê no máximo 49 caracteres da entrada padrão (stdin)
// fgets inclui o '\\n' na string, então podemos removê-lo se necessário
nome[strcspn(nome, "\\n")] = 0;
printf("Nome completo digitado: %s\\n", nome);
fgets
recebe três argumentos:
A linha nome[strcspn(nome, "\\n")] = 0;
remove o caractere de nova linha (\n) que fgets pode incluir na string.
strcspn
retorna o índice da primeira ocorrência de \n na string nome.
Continuamos a utilizar a solução estruturada, essencial para escrever programas claros e organizados.
Baseada nos conceitos de modularidade, abstração e um fluxo lógico consistente, a solução estruturada nos ajuda a resolver problemas complexos de maneira eficiente e organizada.
Dividir um problema grande em subproblemas menores é uma técnica fundamental para a solução estruturada.
Isso não só torna o problema mais manejável, mas também facilita a identificação e a correção de erros.
Imagine que você esteja desenvolvendo um sistema para calcular a média de temperaturas de uma semana.
O problema pode ser dividido nas seguintes etapas. Observe!
Ela envolve escrever funções ou módulos que realizam tarefas específicas, tornando o código mais reutilizável e fácil de entender.
Cada módulo deve ter uma única responsabilidade.
Embora o conceito de função não seja o foco deste desafio, utilizaremos funções genéricas para ilustrar a modularidade.
Vamos usar o exemplo de cálculo da média de temperaturas para ilustrar a modularidade.
#include <stdio.h>
// Função genérica para entrada de dados
void entradaDados() {
// código para a função entradaDados
}
// Função genérica para cálculo da média
float calcularMedia() {
// código para a função calcularMedia
}
Nesse exemplo, temos três funções distintas para entrada, processamento e saída de dados, cada uma com uma responsabilidade clara.
Permite focar os aspectos mais importantes de um problema, ignorando os detalhes irrelevantes.
Isso é importante para lidar com a complexidade.
Usando o exemplo do cálculo da média das temperaturas, em vez de se preocupar com os detalhes de como a entrada de dados é feita, você pode criar uma função entradaDados
que abstrai esse processo.
Assim, se precisar modificar a maneira como os dados são coletados, basta alterar essa função, mantendo o restante do código inalterado.
Para resolver problemas complexos de maneira eficiente, é essencial planejar a solução antes de começar a programar.
Duas ferramentas eficazes para esse planejamento são o pseudocódigo ****e os fluxogramas.
É uma forma de descrever a lógica do algoritmo em linguagem natural, de maneira estruturada e fácil de entender. Ele permite que você organize suas ideias e planeje a estrutura do programa.
Início
Solicitar ao usuário um número
Receber o número fornecido
Se o número for divisível por 2 então
Exibir "O número é par"
Senão
Exibir "O número é ímpar"
Fim
Benefícios do pseudocódigo:
São representações gráficas de um algoritmo, usando símbolos padronizados para ilustrar os passos e o fluxo do processo.
Veja as ações que você pode realizar no fluxograma aqui.
Benefícios dos fluxogramas:
Em C nós temos alguns operadores que vão se repetir em várias outras linguagens, os matemáticos são:
Os de atribuição são:
Os de incremento e decremento são:
Incremento (++) — quando colocado na frente é pré-incremento que incrementa a variável antes do uso.
int a = 5; int b = ++a; // a será 6, b será 6
Se posto depois ele incrementa o valor da variável em um, assim:
int i =1;
i++; // i terá o valor 2
O mesmo acontece para o decremento, (—), mas é claro, agora é subtração. Uma boa prática é essa aqui:
#include <stdio.h>
int main() {
int a = 10;
int b = 5;
// Operadores aritméticos
int soma = a + b;
int subtracao = a - b;
int multiplicacao = a * b;
int divisao = a / b;
// Operadores de atribuição
a += 2; // a será 12
b *= 3; // b será 15
// Operadores de incremento e decremento
a++; // a será 13
b--; // b será 14
// Exibição dos resultados
printf("Soma: %d\\n", soma);
printf("Subtração: %d\\n", subtracao);
printf("Multiplicação: %d\\n", multiplicacao);
printf("Divisão: %d\\n", divisao);
printf("Novo valor de a (após += 2 e ++): %d\\n", a);
printf("Novo valor de b (após *= 3 e --): %d\\n", b);
return 0;
}
São usadas para armazenar números inteiros, ou seja, números sem parte decimal. Em C, o tipo de dado inteiro mais comum é int
.
Para ilustrar a manipulação de variáveis inteiras, consideramos um programa simples no qual declaramos e inicializamos duas variáveis inteiras, a e b.
#include <stdio.h>
int main() {
int a = 10;
int b = 3;
int soma = a + b;
int diferenca = a - b;
int produto = a * b;
int quociente = a / b; // Note que a divisão de inteiros resulta em um número inteiro
printf("Soma: %d\\n", soma);
printf("Diferença: %d\\n", diferenca);
printf("Produto: %d\\n", produto);
printf("Quociente: %d\\n", quociente);
return 0;
}
A saída do programa mostra que a divisão inteira de 7 por 2 resulta em 3, pois a parte decimal é descartada.
Esse exemplo ilustra como a divisão de inteiros em C sempre retorna um valor inteiro.
Em C, os tipos de dados de ponto flutuante mais comuns são float e double.
Para demonstrar a manipulação de variáveis de ponto flutuante, consideramos um programa no qual realizamos operações aritméticas básicas com variáveis float e exibimos os resultados com duas casas decimais.
#include <stdio.h>
int main() {
float x = 5.5;
float y = 2.2;
float soma = x + y;
float diferenca = x - y;
float produto = x * y;
float quociente = x / y; // Divisão de ponto flutuante
printf("Soma: %.2f\\n", soma);
printf("Diferença: %.2f\\n", diferenca);
printf("Produto: %.2f\\n", produto);
printf("Quociente: %.2f\\n", quociente);
return 0;
}
A soma de 5.5 e 2.2 resulta em 7.70, a diferença é 3.30, o produto é 12.10 e a divisão de 5.5 por 2.2 resulta em 2.50.
Os resultados são exibidos com duas casas decimais, demonstrando a precisão das operações com ponto flutuante.
Ocorre automaticamente quando você mistura diferentes tipos de dados em uma expressão.
Para ilustrar a conversão implícita, consideramos um programa no qual uma variável inteira é somada a uma variável float, resultando em uma conversão automática para float.
#include <stdio.h>
int main() {
int a = 10;
float b = 3.5;
float resultado = a + b; // 'a' é convertido implicitamente para float
printf("Resultado: %.2f\\n", resultado); // 13.50
return 0;
}
A conversão implícita pode ser útil, mas também apresenta riscos.
Pode ocorrer perda de dados ou precisão quando tipos de dados de precisões diferentes são convertidos.
Por exemplo, ao converter float para int, a parte decimal será perdida.
A conversão explícita é feita usando operadores de casting para forçar a conversão de um tipo de dado para outro.
Veja a seguir um exemplo de conversão explícita:
#include <stdio.h>
int main() {
int a = 10;
int b = 3;
float quociente = (float) a / b; // 'a' é explicitamente convertido para float
printf("Quociente: %.2f\\n", quociente); // 3.33
return 0;
}
Para garantir que suas operações aritméticas sejam realizadas corretamente e evitar problemas de precisão e perda de dados, aqui estão algumas práticas recomendadas que você deve seguir.