quinta-feira, 20 de novembro de 2014

Linguagem Compilada e Linguagem Interpretada

Como classificar uma linguagem de programação como compilada ou interpretada? 
Bem, a resposta é simples, definindo o contexto ou ponto de vista!
E como estamos analisando linguagens de programação, nosso contexto é arquitetura de
linguagens de programação.

Na computação, a compilação é o processo que reúne o código fonte e o transforma em algo 
que faça mais sentido para o computador. Do ponto de vista do código fonte, toda linguagem 
de programação é compilada.

O produto final do processo de compilação de uma linguagem diz muito sobre seu design.
Linguagens como C e C++ são compiladas estaticamente, e seus códigos fontes são 
transformados diretamente em linguagem de máquina. Enquanto as linguagens mais 
modernas como Java, C# e Python têm seus códigos fontes transformados em uma 
linguagem intermediária (específica de cada linguagem), que será interpretada pela máquina 
virtual da linguagem quando o programa for executado.

Este processo de interpretação da linguagem intermediária durante a execução do programa, 
consiste na tradução dos comandos da linguagem intermediária para linguagem de máquina. 
Sendo assim, em tempo de execução, o código intermediário pode ser encarado como um 
“código fonte” que será compilado dinamicamente pelo interpretador da linguagem em código
de máquina.

Obviamente, ter este processo de compilação embutido na execução do programa tem um custo.
 E esse custo não é barato! Por isso, nos últimos anos muito foi investido para otimizar este 
processo, resultando em todas as técnicas de Just In Time Compiling e Ahead of Time Compiling 
que permitem as linguagens interpretadas alcançarem performance excepcionais.

Finalmente, com base nestas definições, podemos dizer que C e C++ são linguagens compiladas.
Enquanto Java, C# e Python, mesmo com as técnicas de JIT e AOT, são linguagens interpretadas,
afinal, esta é uma definição da arquitetura da linguagem de programação.


“A subtileza ainda não é inteligência. Às vezes os tolos e os loucos também são extraordinariamente subtis.” 
                                                                                                          - Пушкин, Александр Сергеевич




quinta-feira, 9 de outubro de 2014

Prova 2

Dada uma lista encadeada simples, com 5 componentes, apresente graficamente, por meio de um esboço e também descreva, por escrito, cada etapa das seguintes condições:




          1.     Retire o elemento do meio;

Testamos se a posição existe
Caminhamos até a posição
Retiramos o dado da posição
Decrementamos o tamanho



          2.     Inclua 2 novos componentes ao final da lista;

Testamos a última posição da lista e verificamos se possível alocar novo elemento
Caminhamos até a posição
Adicionamos o novo dado na posição
Incrementamos o tamanho
Repetimos toda a operação


          3.     Exclua o primeiro elemento;

Testamos se há elementos
Decrementamos o tamanho
Liberamos a memória do elemento
Devolvemos a informação




          4.     Inclua 2 novos componentes no começo da lista;

Testamos se é possível alocar novo elemento
Fazemos o próximo deste novo elemento ser o primeiro da lista
Fazemos a cabeça da lista apontar para o novo
Repetimos toda a operação



          5.     Incluir 2 novos elementos a partir do terceiro componente da lista.

Testamos se a posição existe e se é possível alocar novo elemento
Caminhamos até a posição
Adicionamos o novo dado na posição
Incrementamos o tamanho
Repetimos toda operação


terça-feira, 7 de outubro de 2014

Encadeamento de nós

Chamamos de estruturas de decisão encadeadas, quando uma estrutura de decisão está localizada dentro do lado falso da outra. Este tipo de estrutura também é conhecida como seleção “aninhada” ou seleção “encaixada”.
Qualquer que seja o termo usado para identificar a estrutura, o importante é que esse formato com uma estrutura de seleção dentro da outra permite fazer a escolha de apenas um entre vários comandos possíveis.


As estruturas de dados giram em torno do encadeamento dos nós que contém as informações armazenadas e processadas nestas estruturas. Em todas as estruturas nós temos a ocorrências de nós. E cada nó aponta para um ou vários nós de seu tipo.

Em C, o perfeito entendimento do encadeamento de nós é essencial para assimilar as estruturas de dados. Sendo assim, considero que a leitura desta dica o ajudará muito na implementação e alteração dos códigos contidos na minha seção de estruturas de dados.

Nas estruturas de dados em C, um nó é implementado como uma estrutura. Assim, a seguinte estrutura:


struct Pessoa{
int codigo;
char nome[80];
struct Pessoa *proximo;
};


representa uma pessoa, contendo um código, um nome e um ponteiro para uma estrutura do mesmo tipo, ou seja, outra pessoa. Analise o código a seguir cuidadosamente:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// estrutura Pessoa
struct Pessoa{
char nome[80];
int codigo;
// fim da estrutura Pessoa
struct Pessoa *proximo; };
// vamos criar a primeira Pessoa
int main(int argc, char *argv[]) {
sizeof(struct Pessoa));
struct Pessoa *pessoa1 = (struct Pessoa*)malloc( pessoa1->codigo = 1;
// vamos criar a segunda Pessoa
strcpy(pessoa1->nome, "Henrique da Silva"); pessoa1->proximo = NULL;
strcpy(pessoa2->nome, "Rangel Victor");
struct Pessoa *pessoa2 = (struct Pessoa*)malloc( sizeof(struct Pessoa)); pessoa2->codigo = 2;
sizeof(struct Pessoa));
pessoa2->proximo = NULL; // vamos criar a terceira Pessoa struct Pessoa *pessoa3 = (struct Pessoa*)malloc(
// vamos exibir os dados destas estruturas
pessoa3->codigo = 3; strcpy(pessoa3->nome, "Renan Leme"); pessoa3->proximo = NULL;
printf("%d - %s\n\n", pessoa3->codigo, pessoa3->nome);
printf("%d - %s\n", pessoa1->codigo, pessoa1->nome); printf("%d - %s\n", pessoa2->codigo, pessoa2->nome); system("pause"); return 0;
}


Neste código nós temos a criação de três estruturas do tipo Pessoa, cada uma contendo dados diferentes. Note que o campo proximo de cada uma recebe o valor NULL, ou seja, não aponta para lugar nenhum. Vamos concentrar nossa atenção neste campo proximo. Veja o trecho de código a seguir:


// o campo proximo da primeira pessoa aponta para a
// segunda pessoa pessoa1->proximo = pessoa2;
// terceira pessoa
// o campo proximo da segunda pessoa aponta para a pessoa2->proximo = pessoa3;
// terceira pessoa continua apontando para lugar nenhum
// só temos três pessoas, então o campo proximo da
pessoa3->proximo = NULL;


É aqui que a mágica do encadeamento acontece. Note que o campo proximo de cada estrutura aponta para a estrutura seguinte, com exceção da terceira estrutura, que continua apontando para NULL.

E, agora que o encadeamento está feito, "pular" de uma estrutura para outra é questão de seguir a ligação entre os nós. Veja, por exemplo, como exibimos os dados da terceira estrutura a partir de uma referência à primeira estrutura:


printf("%d - %s\n", pessoa1->proximo->proximo->codigo,
pessoa1->proximo->proximo->nome);


É claro que se tivermos algumas centenas de nós, o uso desta forma de encadeamento não é nada viável. Mas isso é assunto para as outras dicas. Para finalizar, veja o código completo para esta discussão:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// estrutura Pessoa
struct Pessoa{
char nome[80];
int codigo;
// fim da estrutura Pessoa
struct Pessoa *proximo; };
// vamos criar a primeira Pessoa
int main(int argc, char *argv[]) {
sizeof(struct Pessoa));
struct Pessoa *pessoa1 = (struct Pessoa*)malloc( pessoa1->codigo = 1;
// vamos criar a segunda Pessoa
strcpy(pessoa1->nome, "Henrique da Silva"); pessoa1->proximo = NULL;
strcpy(pessoa2->nome, "Rangel Victor");
struct Pessoa *pessoa2 = (struct Pessoa*)malloc( sizeof(struct Pessoa)); pessoa2->codigo = 2;
sizeof(struct Pessoa));
pessoa2->proximo = NULL; // vamos criar a terceira Pessoa struct Pessoa *pessoa3 = (struct Pessoa*)malloc(
// o campo proximo da primeira pessoa aponta para a
pessoa3->codigo = 3; strcpy(pessoa3->nome, "Renan Leme"); pessoa3->proximo = NULL; // segunda pessoa
// só temos três pessoas, então o campo proximo da
pessoa1->proximo = pessoa2; // o campo proximo da segunda pessoa aponta para a // terceira pessoa pessoa2->proximo = pessoa3;
printf("%d - %s\n", pessoa1->codigo,
// terceira pessoa continua apontando para lugar nenhum pessoa3->proximo = NULL; // exibe os dados do primeiro nó pessoa1->nome); // exibe os dados do segundo nó
pessoa1->proximo->proximo->nome);
printf("%d - %s\n", pessoa1->proximo->codigo, pessoa1->proximo->nome); // exibe os dados do terceiro nó printf("%d - %s\n", pessoa1->proximo->proximo->codigo, system("pause"); return 0;
}
Um exemplo prático:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
    int N1, N2 ;
    printf("Digite o primeiro numero: ");
    scanf("%d", &N1);
    printf("Digite o segundo numero: ");
    scanf("%d", &N2);
     
    if (N1 == N2)
       printf("Os numeros são iguais!");
    else
       if (N1 > N2)
          printf("O maior valor e = %d", N1);
       else
          printf("O maior valor e = %d", N2);
           
    printf("\n");
    system("pause");
    return (0);
}         
Tela de execução do código acima: