quarta-feira, 3 de agosto de 2011

The Most Expensive One-byte Mistake - ACM Queue

Para quem ainda não entendeu o uso do terminador NUL nas strings em C ( "demo\0' ):


The Most Expensive One-byte Mistake - ACM Queue


e outras escolhas.


Saudações.


Josimar

segunda-feira, 22 de dezembro de 2008

Uma mensagem de encerramento de mais um ano

Rodem o código e vejam a mensagem.

#include <stdio.h>
void PrintBitMap( unsigned long long int bitmap ){
    if ( bitmap > 1ULL ) PrintBitMap( bitmap / 2ULL );
    printf("%c", ( bitmap % 2ULL ) ? '*' : ' ');
}
unsigned long long int bitmap[13] = {  
    0x1000000000000000LL, 0x10000000114447CELL,
    0x100000001B444111LL, 0x1000000015444111LL,
    0x1000000011444111LL, 0x100000001138410ELL,
    0x1000000000000000LL, 0x100039E78438E78ELL,
    0x1000451444411451LL, 0x100045E7847DF451LL,
    0x1000451504451451LL, 0x100039E48439178ELL,
    0x1000000000000000LL 
};
void main(){
    for (int i=0; i<13; i++) {
        PrintBitMap( bitmap[i] );
        printf("\n");
    }
    fflush(stdin);
    getchar();
}

Até a próxima.

sábado, 22 de novembro de 2008

Matrizes e Vetores Equivalentes

O código a seguir apresenta a técnica de alocação dinâmica de vetor (matriz linha ou matriz coluna) na linguagem de programação C. Foi usado o Borland C-Builder 6.

O usuário poderá definir o tamanho de uma matriz bi-dimensional e em seguida fornecer os valores para cada elemento, que neste estudo de caso é do tipo inteiro.

A função "sizeof(int)" retorna o tamanho em bytes para cada elemento da matriz[m][n].

Com a função "malloc( m * n * sizeof( int ) )" são alocados bytes na memória RAM suficientes para armazenar a quantidade de elementos ( int ) que compõem a matriz[m][n]. Esta função retorna um ponteiro do tipo (void*) sendo necessária a conversão para ponteiro do tipo (int*).

Para a entrada de dados, o algoritmo percorre de maneira bi-dimensional a matriz[m][n], sendo necessária a conversão dos índices m e n para a posição efetiva no vetor:

posição no vetor = t * n + u

onde:

t : linha corrente na matriz[m][n]

u: coluna corrente na matriz[m][n]

n : quantidade de colunas por lina na matriz[m][n]

Na segunda parte do código, o algoritmo percorre linearmente o vetor de dados que armazena a matriz[m][n] desejada, e para informação é calculada de maneira inversa os índices correntemente sendo impressos:

v = t / n (divisão inteira)

w = t % n (resto de divisão inteira)

onde:

t : posição corrente no vetor

n : quantidade de colunas por linha na matriz[m][n]

v : linha corrente da matriz[m][n]

w : coluna corrente da matriz[m][n]

Antes de analisar o código, acompanhe o diagrama de blocos a seguir:

Diagrama1

Agora temos o código na linguagem C:

//---------------------------------------------------------------------

#pragma hdrstop

//---------------------------------------------------------------------

/*

    Alocação dinâmica de memória

    Estudo de caso: matrizes e vetores equivalentes

    malloc, free, fflush, printf, scanf

*/

#include <stdio.h>
#include <stdlib.h>

#pragma argsused
int main(int argc, char* argv[])
{
    int *A;

    int m, n, c, t, u, valor;

    printf("Matriz A[m][n]:\n");

    fflush(stdin);

    printf("Digite valor de m:");
    scanf("%d",&m);

    printf("Digite valor de n:");
    scanf("%d",&n);

    // Alocar recurso de memória RAM ----------

    c = m * n;

    A = (int*) malloc( c * sizeof( int ) );

    // ----------------------------------------

    if ( A == NULL )
    {
        printf("\n\nErro ao alocar memoria RAM!!!\n");
        printf("\n\nTecle ENTER para encerrar");
        fflush(stdin);
        getchar();
        return 1;
    }

    printf("\nDigite os elementos da matriz A[%d][%d]\n", m, n);

    for ( t=0; t<m; t++ )
    {
        for ( u=0; u<n; u++ )
        {
            printf("Digite elemento[%d][%d]:", t, u);
            scanf("%d", &valor);

            A[ t * n + u ] = valor;

        }
    }

    printf("\n\nMatriz A[%d][%d]:\n", m, n);

    for ( t=0; t<c; t++ )
    {
        printf("\nA[%d][%d]=%d", (t / n), (t % n), A[t]);
    }

    printf("\n\nTecle ENTER para encerrar");

    fflush(stdin);
    getchar();

    // Liberar recurso de memória RAM -----

    free(A);

    // ------------------------------------

    return 0;
}
//---------------------------------------------------------------------

 

Links sugeridos para outros esclarecimentos:

http://www.ime.usp.br/~pf/algoritmos/aulas/aloca.html

http://en.wikipedia.org/wiki/Malloc

http://cplus.about.com/od/learningc/ss/pointers_7.htm

http://informatica.hsw.uol.com.br/programacao-em-c29.htm

 

Cópias de tela da execução do código aqui apresentado:

teste

teste2

Para estudo, desenvolver uma aplicação para multiplicar duas matrizes bi-dimensionais:

C[m][j] = A[m][n] . B[i][j]

restrições:

  • n igual a i
  • m, n, i, j maiores que zero

Links com fundamentos matemáticos para multiplicação de matrizes:

 

Bom estudo e até a próxima.

sexta-feira, 3 de outubro de 2008

Código em C para ler código de tecla pressionada

As funções getch() e kbhit() da biblioteca CONIO proporcionam funcionalidades para monitoramento de teclas pressionadas, permitindo obter o código da tecla sem precisar aguardar que o usuário pressione ENTER, como ocorre com a getchar() padrão.

 

//---------------------------------------------------------------------------

#pragma hdrstop

#include <stdio.h>      // printf

#include <conio.h>      // kbhit, getch

//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
    int keycode, normalkey;

    while ( keycode != 27 )         // ESCAPE
    {


        // aguardar uma tecla ser pressionada
        while ( ! kbhit() ) ;

        // ler o código da tecla pressionada
        keycode = getch();

        // keycode = 0 se for tecla especial
        normalkey = keycode;

        // se tecla especial,
        // pegar o próximo código para identificar a tecla pressionada
        if ( !normalkey )
            keycode = getch();

        if      ( normalkey && keycode >= 48 && keycode <= 57 )
            printf("\nteclou digito %c = %d = valor decimal %d",
                    keycode, keycode, (keycode - 48) );

        else if ( normalkey && keycode >= 65 && keycode <= 90 )
            printf("\nteclou letra maiuscula %c = %d",
                    keycode, keycode);

        else if ( normalkey && keycode >= 97 && keycode <= 122 )
            printf("\nteclou letra minuscula %c = %d",
                    keycode, keycode);

        else if ( !normalkey && keycode >= 59 && keycode <= 68 )
            printf("\nteclou F%1d = %d",
                    (keycode - 58), keycode);

        else if ( !normalkey && keycode >= 133 && keycode <= 134 )
            printf("\nteclou F%2d = %d",
                    (keycode - 122), keycode);

        else if ( normalkey && keycode == 27 )
            printf("\nteclou ESCAPE = %d", keycode);

        else if ( normalkey && keycode == 8 )
            printf("\nteclou BACKSPACE = %d", keycode);

        else if ( normalkey && keycode == 9 )
            printf("\nteclou TAB = %d", keycode);

        else if ( normalkey && keycode == 13 )
            printf("\nteclou CARRIAGE-RETURN (ENTER) = %d", keycode);

        else if ( normalkey && keycode == 10 )
            printf("\nteclou LINE-FEED (CTRL-ENTER) = %d", keycode);

        else if ( !normalkey && keycode == 75 )
            printf("\nteclou SETA A ESQUERDA = %d", keycode);

        else if ( !normalkey && keycode == 77 )
            printf("\nteclou SETA A DIREITA = %d", keycode);

        else if ( !normalkey && keycode == 72 )
            printf("\nteclou SETA PARA CIMA = %d", keycode);

        else if ( !normalkey && keycode == 80 )
            printf("\nteclou SETA PARA BAIXO = %d", keycode);

        else if ( !normalkey && keycode >= 82 && keycode <= 83 )
            printf("\nteclou %s = %d",
                    (keycode == 82 ? "INSERT\0" : "DELETE\0"), keycode);

        else if ( !normalkey && keycode == 71 )
            printf("\nteclou HOME = %d", keycode);

        else if ( !normalkey && keycode == 79 )
            printf("\nteclou END = %d", keycode);

        else if ( !normalkey && keycode == 73 )
            printf("\nteclou PAGE-UP = %d", keycode);

        else if ( !normalkey && keycode == 81 )
            printf("\nteclou PAGE-DOWN = %d", keycode);

        else
            printf("\nteclou %c = %d (%s)",
                    keycode, keycode, (normalkey ? "normal\0" : "especial\0") );
    }

    return 0;
}
//---------------------------------------------------------------------------

 

Com o código acima, espero ter apresentado dicas para os exercícios propostos em sala de aula.

 

Bom estudo e até a próxima.

quarta-feira, 1 de outubro de 2008

Trabalhando com cadeias de caracteres (strings)

O código apresentado a seguir foi escrito em C e se propõe a demonstrar o uso de cadeias de caracteres.
A aplicação é bastante simples, envolvendo uma lista de nomes de frutas previamente estabelecida e a interação com o usuário para que este faça uma consulta.
Dado um nome de fruta, o algoritmo fará uma busca seqüencial na lista a partir do primeiro elemento.
Se o nome for localizado, será indicado em qual posição da lista e o nome apresentado com efeito especial: letra por letra pausadamente e com barulho de máquina de datilografia.

O programa foi testado na plataforma MS Windows XP e Borland C Builder.

//---------------------------------------------------------------------------
#pragma hdrstop
//---------------------------------------------------------------------------

#include <stdio.h>      // printf, scanf, fflush
#include <windows.h>    // Sleep, Beep

#define MAX_FRUTAS 5
#define MAX_COMPR 12

#pragma argsused
int main(int argc, char* argv[])
{

        char frutas[MAX_FRUTAS][MAX_COMPR] =
                {
                        { 'a', 'b', 'a', 'c', 'a', 'x', 'i' },
                        { "mamao" },
                        { "laranja" },
                          "banana",
                          "kiwi"
                };


        char nome[MAX_COMPR];

        int i, j;

        printf("\nDigite um nome de fruta: ");

        scanf("%s", nome);

        printf("\nVoce digitou %s", nome);

        // Pesquisa do nome na lista

        for (i=0; i<MAX_FRUTAS && strcmp( frutas[i], nome ) ; i++) ;

        if ( i == MAX_FRUTAS )
        {
                printf("\nNome nao catalogado");
        }
        else
        {
                printf("\nLocalizada em %d", i);
                printf("\n\n");

//              for (j=0; j<MAX_COMPR && frutas[i][j] != '\0'; j++)
                for (j=0; j<MAX_COMPR && nome[j] != '\0'; j++)
                {

//                      putchar( frutas[i][j] );
                        putchar( nome[j] );

                        Beep(3700, 5);  // frequencia (Hz), duracao (s)
                        Beep(300,2);
                        Beep(80,8);

                        Sleep(500);     // hibernar (ms)

                }
        }

        fflush( stdin );        // limpar buffer da entrada padrão
        getchar();

        return 0;

}
//---------------------------------------------------------------------------

 

Bom estudo e até a próxima.

segunda-feira, 22 de setembro de 2008

Código C do Programa de Estatística

 

O programa aqui apresentado foi escrito com base nos diagramas de blocos comentados em sala de aula. Este código foi testado nas plataformas Borland C Builder e Linux GCC.

//---------------------------------------------------------------------------
//    Estatistica.c
//    Josimar Nunes de Oliveira
//    20/Set/2008
//---------------------------------------------------------------------------

#pragma hdrstop

// bibliotecas referenciadas

#include <stdio.h>   // printf, scanf, getchar
#include <math.h>    // pow, sqrt
#include <string.h>  // strcmp

// constantes figurativas

#define MAX     5000        // capacidade máxima de dados
                            // para o array de termos da amostra

#define BATCH   "--batch"   // parâmetro de execução do programa:
                            // lote ou interativo

// criando macro definições

#define RaizQuadrada(x) sqrt(x)
#define Potencia(x,y) pow(x,y)

#pragma argsused

int main(int argc, char* argv[])
{
    // declaração de variáveis locais da função "main"

    int proc_interativo;

    int a[MAX], vmin, vmax, s, i, n, q;

    float vmed, ss, dp;

    // verificar argumentos de execução do programa

    proc_interativo = 1;
    if ( argc > 1 )
    {
        if ( strcmp(argv[1], BATCH) == 0 && argc == 2)
        {
            proc_interativo = 0;
        }
        else
        {
            printf("\n\nSintaxe:\n\n");
            printf("\t./progteste [--batch] [< arqentrada] [> arqsaida]\n\n");
            // término prematuro -- erro de sintaxe
            return 1;
        }
    }

    // entrada do parâmetro "n"

    if ( proc_interativo )
    {
        printf("\n\nInforme qual o n-ésimo termo: ");
    }
    scanf("%d", &n);

    // validar o parâmetro "n" fornecido pelo usuário

    if (n >= MAX)
    {
        if ( proc_interativo )   
        {
            printf("\n\nErro: excedeu capacidade do programa!!!\n\n");
        }
        // término prematuro do programa -- erro de capacidade
        return 2;
    }

    // quantidade de termos na amostra
    q = n + 1;

    // entrada dos termos { a0, a1, a2, ..., aN }
    // e armazenagem em array

    for (i=0; i<=n; i++)
    {
        if ( proc_interativo )
        {
            printf("\nDigite o valor[ %d ] : ", i);
        }
        scanf("%d", &a[i]);
    }

    // obtenção dos termos de valores mínimo e máximo
    // usando o primeiro elemento "a[0]" como referência

    vmin = a[0];
    vmax = a[0];

    for (i=1; i<=n; i++)
    {
        if ( a[i] < vmin )
        {
            vmin = a[i];
        }
        if ( a[i] > vmax )
        {
            vmax = a[i];
        }
    }

    // obter somatório dos termos

    s = 0;

    for (i=0; i<=n; i++)
    {
        s = s + a[i];
    }

    // cálculo da média aritmética

    vmed = (float)s / (float)q;

    // obter somatorio dos quadrados da diferença entre termos e média

    ss = 0;

    for (i=0; i<=n; i++)
    {
//      ss = ss + pow( (double)((float)a[i] - vmed), 2);
        ss = ss + Potencia( (double)((float)a[i] - vmed), 2);
    }

    // medida estatística denominada "variância"

    ss = ss / (float)q;


    // cálculo da medida estatística "desvio padrão"

//  dp = sqrt(  ss );
    dp = RaizQuadrada( ss );

    // saída dos cálculos

    printf("\n\nResumo Estatistico\n");

    printf("\nQuantidade de termos: %d", q    );
    printf("\nSomatorio dos termos: %d", s    );
    printf("\nValor minimo........: %d", vmin );
    printf("\nValor medio.........: %f", vmed );
    printf("\nValor maximo........: %d", vmax );
    printf("\nVariancia...........: %f", ss   );
    printf("\nDesvio padrao.......: %f", dp   );

    printf("\n\n\nListagem da Amostra\n");

    for ( i=0; i<=n; i++ ) 
    { 
        printf("\nTermo[ %04d ] = \t%d", i, a[i]); 
    }

    printf("\n\n");

    // aguardar usuário teclar ENTER em modo interativo

    getchar();
    getchar();

    // término normal do programa

    return 0;

}

No caso do Linux GCC, a linha de comando usada para compilação é:

gcc progteste.c -o progteste -lm

Nos próximos posts irei estender comentários de partes deste programa. Por enquanto apenas publiquei o código desenvolvido em sala de aula para servir de referência para construção de novos programas.

A seguir temos uma cópia de tela da execução no modo "batch":

proc

Até mais.

sábado, 30 de agosto de 2008

Exercício da intersecção entre duas equações de 2º grau

Diagrama de blocos construído com o software DIA:

 

Diagrama1

A ferramenta de apoio DIA pode ser obtida em:

http://downloads.sourceforge.net/dia-installer/dia-setup-0.96.1-8.exe

 

 

A seguir temos o algoritmo escrito em "portugol" nativo do software VISUALG:

 

algoritmo "intersecção"
// Função :
// Autor :
// Data : 29/08/2008
// Seção de Declarações
var
a, b, c, d, eh, f, i, j, k, delta, x, x1, x2 : real
Resp : caracter

inicio
// Seção de Comandos
escreva("Digite a primeira equação:")
leia(a, b, c)
escreva("Digite a segunda equação:")
leia(d, eh, f)
se ( a = 0 ) ou ( d = 0 ) entao
   Resp <- "Equações inválidas"
senao
   i <- ( a - d )
   j <- ( b - eh )
   k <- ( c - f )
   se ( i = 0 ) entao 
      se ( j = 0 ) entao
         se ( k = 0 ) entao
            Resp <- "Qualquer x Real"
         senao
            Resp <- "sem solução Real"
         fimse
      senao
         x <- ( - k / j )
         Resp <- "X = " + Numpcarac( x ) 
      fimse
   senao
      delta <- ( j ^2 - 4 * i * k )
      se ( delta < 0 ) entao
         Resp <- "sem solução Real"
      senao
         se ( delta = 0 ) entao
            x <- ( -j / 2 * i )
            Resp <- "X = " + Numpcarac( x )
         senao
            x1 <- ( ( -j + raizq( delta ) ) / 2 * i )
            x2 <- ( ( -j - raizq( delta ) ) / 2 * i )
            Resp <- "X1 = " + Numpcarac( x1 ) + "   X2 = " + Numpcarac( x2 )
         fimse
      fimse
   fimse
fimse
escreva( Resp )
fimalgoritmo

 

 

VisuAlg pode ser obtido em:
http://www.apoioinformatica.inf.br/

E seu manual em:

http://hermes.ucs.br/carvi/cent/dpei/haklauck/algoritmos/Linguagem_Visualg2.0.pdf

 

Bom estudo e até a próxima.