domingo, 4 de setembro de 2011

Programa em C chamando scripts

Olá, hoje vamos trabalhar com programas em C em conjunto com scripts. O objetivo é construir dois scripts, um para criar um arquivo e outro para deletar um arquivo. Esses dois scripts serão chamados pelo nosso programa escrito em c, que será basicamente um MENU que irá usar o comando system para chamada dos scripts.

Primeiro passo - Criação dos scripts
Nome: ArqExiste.sh
Funcionalidade: Ele é quem vai criar o arquivo de acordo com o nome fornecido pelo usuário.
Código:

#!/bin/bash

if [ -a $1 ]
then
echo "O Arquivo ja Existe!!!"
echo "Voce deseja criar um novo? (s/n)"
read op
if [ $op == "s" ]
then
rm -f $1;
touch $1;
fi
else
touch $1
echo "Arquivo criado!!!"
fi

Nosso segundo script
Nome: DeletaArq.sh
Funcionalidade: Excluir o arquivo
Código:

#!/bin/bash
if [ -a $1 ]
then
rm -f $1
else
echo "Arquivo nao Existe!!!"
fi

Na linha de comando você deve fornecer permissão de execução para esses arquivos, então digitie
chmod +x DeletaArq.sh
chmod +x ArqExiste.sh

Bom, agora vamos ao nosso programa em c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXOP 4
int menuOpcoes()
{
    int op; //Armazena opcao seelecionada
    printf("\n\t*****************************\n");
    printf("1 - Criar Arquivo;\n");
    printf("2 - Listar Aqrquivos;\n");
    printf("3 - Remover Arquivo;\n");
    printf("Escolha sua opcao:\t");
    scanf("%d",&op);
    return op;
}

int main()
{
    int ret; //Armazena valores de retorno de comandos
    int op;
    char str[50];
    char buffer[256];

    do
    {
        op = menuOpcoes();
        switch(op)
        {
            case 1: printf("\n\tScript para criacao de arquivo\n\tNome do arquivo:\t");
                    scanf("%s",str);
                    sprintf(buffer, "./ArqExiste.sh %s",str);
                    ret = system(buffer);
                    break;
            case 2: printf("\n\t****Arquivos do diretório****\n");
                    ret = system("ls");
                    break;
            case 3: printf("\n\tScript para excluir arquivo\n\tNome do arquivo:\t");
                    scanf("%s",str);
                    sprintf(buffer, "./DeletaArq.sh %s",str);
                    ret = system(buffer);
                    break;


        }

    }while(op < MAXOP);
    return 0;
}


sexta-feira, 12 de agosto de 2011

Listas Encadeadas em C


Olá pessoal,

hoje trabalharemos com um assunto muito interessante em C, que são listas encadeadas. Faremos um pequeno programa onde vamos inserir elementos em uma lista Encadeada, excluir elementos, imprimir e contá-los.

Para isso, vamos ter em mente como ficará a configuração em nossa memória de uma lista encadeada:


Veja que a estrutura consiste de um “valor” e um ponteiro que aponta para a próxima estrutura. Para inserir um dado, veja, é muito fácil, apenas o que devemos fazer é criar um novo elemento com um valor associado que aponte para NULL.

Assim pegamos o último elemento de nossa lista, e apontamos para ele:

Para excluir, devemos fazer com que o elemento anterior ao que desejamos excluir, aponte, para o campo “proximo” do elemento que desejamos excluir. Devemos salvar, antes quem desejamos excluir, para que depois possamos usar a função para liberar memória.



As operações para imprimir e contar que são mostradas apenas percorremos a lista, tendo cuidado para não usar um elemento NULL.

Vamos ao código:

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

typedef struct listaDeDados
{
int dado;
struct listaDeDados * proximo;

}listaDeDados;
int ImprimeOpcoes()
{
/*
Funcao imprimirá na tela as opções que nosso programa realizará
A opção é retornada com o auxílio da variável op
*/
int op;
printf("\n\t1 - Insere Elemento");
printf("\n\t2 - Deleta Elemento");
printf("\n\t3 - Imprime Lista");
printf("\n\t4 - Conta Numero de elementos.");
printf("\n\t5 - Sair\n\t");
scanf("%d",&op);
return op;
}

listaDeDados * CriaElemento(int valor)
{
/*
Função cria um novo elemento e o retorna para ser acrescentado na lista
Para a criação do novo elemento você precisa informar seu valor, ou seja,
o valor do campo dado
*/
listaDeDados * novoElemento = (listaDeDados*)malloc(sizeof(listaDeDados));
novoElemento->proximo = NULL; //não esqueça que o novo elemento aponta para NULL
novoElemento->dado = valor;
return novoElemento;
}

listaDeDados * InsereNovoElemento(listaDeDados * listaAtual, int valor)
{
/*
Função que insere um elemento em uma lista.
Ele considera o caso da lista estar vazia, ou seja, NULL
Veja que devemos procurar pelo elemento que aponta para NULL, e fazer com que ele aponte para o novo elemento
Veja que criamos uma lista para ficar armazenando o primeiro endereço da lista, pois do contrário
iríamos perder a referência da lista.
*/
listaDeDados * listaComEnderecoInicial;
listaComEnderecoInicial = listaAtual;
if(listaAtual == NULL)
return CriaElemento(valor);
else
{
while(listaComEnderecoInicial->proximo != NULL)
listaComEnderecoInicial = listaComEnderecoInicial->proximo;

listaComEnderecoInicial->proximo = CriaElemento(valor);
return listaAtual;
}
}

void ImprimeLista(listaDeDados* listaAtual)
{
/*
Vamos imprimir os valores da lista. Aqui percorremos a lista até encontrarmos um valor NULL
*/
if(listaAtual!=NULL)
{
printf(" %d ", listaAtual->dado);
ImprimeLista(listaAtual->proximo);
}

else
return;


}

listaDeDados * DeletaElemento(int valor, listaDeDados * listaAtual)
{
/*
Essa função será responsável por deletar um elemento da lista
Veja que não é necessário apenas desfazer o apontamento,
precisamos liberar o espaço de memória
*/

listaDeDados * listaEnderecoInicial, * listaElementoAnterior;
listaEnderecoInicial = listaElementoAnterior = listaAtual;
if(listaAtual == NULL)
return listaAtual;
if(listaEnderecoInicial->dado == valor)
{
listaElementoAnterior = listaEnderecoInicial;
listaEnderecoInicial = listaEnderecoInicial->proximo;
free(listaElementoAnterior);
return listaEnderecoInicial;
}
else
{
listaEnderecoInicial = listaEnderecoInicial->proximo;
while(listaEnderecoInicial != NULL)
{

if (listaEnderecoInicial->dado == valor)
{
listaElementoAnterior->proximo = listaEnderecoInicial->proximo;
free(listaEnderecoInicial);
return listaAtual;
}
else
{
listaElementoAnterior = listaEnderecoInicial;
listaEnderecoInicial = listaEnderecoInicial->proximo;
}
}
}
return listaAtual;
}

int ContaElementos(listaDeDados * listaAtual)
{
/*
Função vai contar o número de elementos da lista
*/
int contador = 0;
if(listaAtual == NULL)
return 0;
else
{
while(listaAtual!=NULL)
{
contador++;
listaAtual= listaAtual->proximo;
}
}
return contador;
}
/*
Nosso programa main será bem simples pois apena iremos testar as funções criadas acima
*/
int main()
{
int op, valor;
listaDeDados * listaPrincipal = NULL;
do
{
op = ImprimeOpcoes();
switch(op)
{
case 1: printf("\n\tInforme o valor do novo elemento: ");
scanf("%d", &valor);
listaPrincipal = InsereNovoElemento(listaPrincipal,valor);
break;
case 2: printf("\n\tInforme um elemento a ser excuido:\n");
ImprimeLista(listaPrincipal);
printf("\n\tValor: ");
scanf("%d",&valor);
listaPrincipal = DeletaElemento(valor, listaPrincipal);
printf("\n\tLista Resultamte:");
ImprimeLista(listaPrincipal);
break;
case 3: printf("\n\tImprimindo lista\n\t");
ImprimeLista(listaPrincipal);
break;
case 4: printf("\n\tNumero de elementos: %d\n", ContaElementos(listaPrincipal));
break;

}
}while(op <5);
return 0;
}





sábado, 30 de julho de 2011

Compilando arquivos com a ajuda do Makefile

Olá pessoal, hoje trataremos do utilitário Makefile. Ele nos ajudará a compilar nosso programa de hoje. Nosso programa é bem simples, na verdade o objetivo principal é a utilização do Makefile quando precisamos compilar projetos com mais de um arquivo.

Os softwares que utilizamos nesse artigo:

gcc – nosso compilador, versão 4.4.5
emacs – nosso editor, você pode utilizar qualquer editor para criar seus arquivos de código.
Sistema Operacional – Debian

Nosso pequeno projeto consistirá de três arquivos:

main.c – conterá nossa aplicação principal
matematica.c – esse conterá funções matemáticas, um exemplo didático
matematica.h – nosso arquivo cabeçário

Vamos começar pelo arquivo “matemática.c”

#include "matematica.h"
//calcula fatorial de um numero
int fatorial (int n)
{
if(n==1)
return n;
else
return n * fatorial(n-1);
}
//retorna o modulo de um inteiro
int modulo(int n)
{
if(n<0)
return n * (-1);
else
return n;
}
//verifica se um número é par
//se a funcao retornar 1 - é par, 0 - é ímpar
int e_par(int n)
{
int resto;
resto = n % 2;
if (!resto)
return 1; // é par
else
return 0; //não é par
}

Agora, nós vamos criar um arquivo com a extensão .h, “matematica.h” para apenas conter as chamadas das funções.
Veja:
extern int fatorial (int n);
extern int modulo (int n);
extern int e_par (int n);

Bem simples, não concorda?

Agora vamos ao nosso programa “main.c”

#include <stdio.h>
#include "matematica.h"

int menu()
{
int op;
printf("\n\t1 - Fatorial:");
printf("\n\t2 - Modulo:");
printf("\n\t3 - Verifica se e par:");
printf("\n\tOpcao:\t");
scanf("%d",&op);
return op;
}
int main ()
{
int op,num;
do
{
op = menu();
switch(op)
{
case 1:printf("\n\tInforme um numero: ");
scanf("%d",&num);
printf("\n\tFatorial do numero: %d\n",fatorial(num));
break;
case 2:printf("\n\tInforme um numero: ");
scanf("%d",&num);
printf("\n\tO modulo do numero e: %d\n",modulo(num));
break;
case 3:printf("\n\tInforme um numero: ");
scanf("%d",&num);
num = e_par(num);
if(num)
printf("\n\tE PAR!\n");
else
printf("\n\tE IMPAR!\n");
break;
}

}while(op<4);

}

Finalizamos nossa codificação. Agora, vamos ao nosso Makefile.

programa_final: main.o matematica.o
     gcc -o programa_final main.o matematica.o
main.o: main.c matematica.h
     gcc -c main.c
matematica.o: matematica.c matematica.h
     gcc -c matematica.c
Veja que, programa_final, é o arquivo final, ou seja, aquele que vamos executar com o comando: ./programa_final. A estrutura do arquivo é bem simples. A esquerda temos o arquivo que será gerado, chamado de “target”, e a direita temos suas dependências. Abaixo vem o comando para sua compilação. Para os outros aquivos a regra é a mesma.

Assim crie um arquivo chamado Makefile, e coloque esse código em seu interior. Após isso apenas digite em sua linha de comando: “make”

Os arquivos serão compilados e você terá a seguinte saída:

gcc -c main.c
gcc -c matematica.c
gcc -o programa_final main.o matematica.o

Assim será gerado o arquivo “programa_final”. Agora o execute com o comando: ./programa_final

Outro ponto que merece atenção é que só os arquivos que foram alterados serão recompilados. Imagine que você está trabalhando com um grande número de arquivos, se você alterar apenas 1 arquivo não terá porque recompilar todos. Vamos fazer um teste, vamos alterar o arquivo main, e vamos rodar o make novamente.

A saída do comando make deveria ter sido:
gcc -c main.c
gcc -o programa_final main.o matematica.o

Sem a compilação do arquivo matematica.c, pois o mesmo não foi alterado.

Espero ter ajudado com essa pequena introdução sobre o Makefile.





sexta-feira, 22 de julho de 2011

Threads em CSharp (C#)

Pessoal hoje vamos falar sobre threads na linguagem CSharp (C#). Threads possuem várias finalidades, mas a que aqui, hoje trabalharemos, será manter uma interface que continue interagindo com o usuário, mesmo que algum processamento pesado esteja acontecendo.

Vamos ao nosso exemplo prático: Vamos criar uma função que calcula números primos e vamos mostrar o resultado em uma caixa de texto. Nossa interface será como a que segue:


Caixa de Texto, propriedades que alteramos:
Name: textBoxResult
Multiline: true
Scrolls Bars: Both

Botões:
Calc:
Name: buttonCalc
Text: Calc


CalcThread:
Name: buttonThread
Text: CalcThread

OutraTarefa:
Name: buttonOutraTarefa
Text: OutraTarefa

Nosso código

Namespaces que vamos utilizar:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;


Todos esses são default do VisualStudio, exceto um: System.Threading, ele conterá tudo que precisaremos para trabalhar com a Thread de nosso exemplo.

Código do botão Calc:

private void buttonCalc_Click(object sender, EventArgs e)
{
int maxNum = 10000;
int contador = 2;
int resto=1;
while (contador <= maxNum)
{
for (int x = 2; x < contador; x++)
{
resto = contador % x;
if ( resto == 0)
{
break;
}
}
if (resto != 0)
textBoxResult.Text = textBoxResult.Text + " " + contador.ToString();
contador++;
}

}

Código do botão CalcThread:

prime = new Thread(calculaPrimos);
prime.Start();

Bom vamos ver nossas funções auxiliares, primeiramente vamos verificar a função calculaPrimos:

public void calculaPrimos()
{
int maxNum = 10000;
int contador = 2;
int resto=1;
while (contador <= maxNum)
{
for (int x = 2; x < contador; x++)
{
resto = contador % x;
if ( resto == 0)
{
break;
}
}

if (resto != 0)
textBoxResult.Invoke(new escreveTxtDelegate(escreveTxt), new object[] { contador});
contador++;
}

}


Para escrevermos em controles que não foram criados dentro de nossa thread, precisamos fazer o uso de delegates e usamos o método invoke do textBoxResul.
Bom o delegate pode estar declarado no início, como um membro da classe, assim como nossa thread:

public delegate void escreveTxtDelegate(int contador);
Thread prime;

Nossa função para escrever no TextBox, usada pelo Delegate:

public void escreveTxt(int contador)
{
textBoxResult.Text = textBoxResult.Text + " " + contador.ToString();
}

Bom agora para finalizarmos o código de nosso botão OutraTarefa:

private void buttonOutraTarefa_Click(object sender, EventArgs e)
{
MessageBox.Show("Executando outra tarefa", "NumPrimos");
}
Para testarmos nossa aplicação, vamos fazer da seguinte maneira:

Vamos executar o programa e pressionar o botão “Calc”, se você tentar pressionar o botão OutraTarefa ele não vai mostrar a mensagem “Executando outra Tarefa”. E também se você tentar mexer a tela do programa a mesma não vai responder. Agora vamos fazer outro teste, ao invés de clicarmos no botão “Calc”, vamos clicar no botão “CalcThread” assim você poderá perceber que a mensagem será mostrada e também poderá movimentar a tela do aplicativo enquanto o processamento matemático está ocorrendo.