argcv

codes and stuff

Archive for the ‘dicas’ Category

Range() em C

leave a comment »

Eis uma versão bastante simples da função range(), presente em muitas linguagens de script e que tem por finalidade gerar uma sequência de números (crescente ou decrescente), de acordo com os dados fornecidos em sua chamada.

/* Escrito por Renato R. Leme em 16/08/2012
 * e-mail: rntreisleme@gmail.com
 * site: https://argcv.wordpress.com */

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

int *range (int ini, int fim, int vari);

void main () {
    int *v, i;
    v = range (22, 102, 2);
    for (i = 0; i < (102-22)/2+1; i++) printf ("%d ", v[i]);
    printf ("\n\n");
    v = range (102, 21, -5);
    for (i = 0; i < (102-22)/5+1; i++) printf ("%d ", v[i]);
    printf ("\n\n");
}

/* A função gera uma sequência que vai de ini à, no máximo,
 * fim. Caso bem sucedida, retorna o vetor v[n], com valores
 * tais que v[a] = v[a-1] + vari. Caso contrário,
 * retorna NULL. */

int *range (int ini, int fim, int vari) {
    if ((ini > fim && vari > 0) || (ini < fim && vari < 0))
        return NULL;
    else {
        int i, j, n = (fim - ini) / vari + 1;
        int *v = malloc (n * sizeof (int));
        for (j = 0, i = ini; j < n; j++, i += vari)
            v[j] = i;
        return v;
    }
}

Written by rntreis

agosto 16, 2012 at 3:56 pm

Publicado em C, dicas, programação

Algoritmo de inserção animado com dança romena

leave a comment »

Ótimo vídeo criado na Sapientia University que ilustra o algoritmo de inserção.

 

😀

Written by rntreis

junho 7, 2012 at 7:21 pm

Publicado em dicas, programação

Fórmula resolutiva da equação do 2º grau

leave a comment »

Escrevi o seguinte algoritmo para a resolução de equações do segundo grau no domínio dos números reais (como exemplo, o programa resolve 4x²+13x+12 = 0).

/* Escrito por Renato. R. Leme, em 03/06/2012 */
/* e-mail: rntreisleme@gmail.com              */
/* site: https://argcv.wordpress.com           */

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

double *bhaskara (double a, double b, double c);

void main () {
    double *a;
    if (!(a = bhaskara (4, 13, 2)))
        printf ("A equação não pode ser resolvida no domínio dos Reais.\n");
    else
        printf ("x'  = %.2f \nx'' = %.2f\n", a[0], a[1]);
    free (a);
}

/* Esta função recebe a, b e c, de ax² + bx + c e retorna     */
/* um ponteiro para o primeiro número do conjunto de soluções */
/* da equação caso obtenha sucesso em resolvê-la no conjunto  */
/* dos números reais. Retorna NULL caso contrário. */

double *bhaskara (double a, double b, double c) {
    double delta;
    double *solucao = malloc (2 * sizeof (double));
    delta = (b * b) - (4 * a * c);
    if (delta < 0) return NULL;
    solucao[0] = (- b - sqrt (delta)) / (2 * a);
    solucao[1] = (- b + sqrt (delta)) / (2 * a);
    return solucao;
}

Até mais!

Written by rntreis

junho 3, 2012 at 1:49 pm

Publicado em C, dicas, programação

Fibonacci com apenas uma chamada recursiva

leave a comment »

Uma solução clássica para o problema de encontrar um número da sequência de Fibonacci com um algoritmo recursivo é a seguinte:

int calculaFibonacci (int n) {
    if (n < 2) return n;
    else return calculaFibonacci (n - 1) + calculaFibonacci (n - 2);
}

Entretanto, é sabido que duas chamadas recursivas podem pesar bastante.

Pensando nisso, eu escrevi uma solução que usa uma só chamada recursiva aliada a um vetor. Para isso, ao invés de começar os cálculos por n, a função começa por i, que vale 2. A lógica disso é que, sabendo v[i-2] = 0 e v[i-1] = 1, eu posso determinar v[i] (que é v[i-2] + v[i-1]), e, assim, determinar v[i+1…n], usando uma chamada recursiva para cada v[i], até que i seja igual a n e a função tenha achado o que se pede, que é sempre v[n].

Para conseguir o efeito de começar a calcular por i = 2 e usar um vetor v[n] sem que, quando quiser encontrar o número de Fibonacci preterido o usuário da função tenha que especificar esses dois dados à função sem qualquer motivo aparente, eu criei uma função chamada fibonacci(), que funciona como um pacote, simplesmente criando v[n], especificando os dois valores iniciais para v[] e chamando calculaFibonacci() com n, i = 2 e v.

Eis, então, o algoritmo.

#include <stdio.h>

int fibonacci (int n);
int calculaFibonacci (int n, int i, int v[]);

void main () {
    int a = fibonacci (40);
    printf ("%d\n", a);
}

/*  Esta função recebe n >= 0 e devolve o número  */
/*  de fibonacci presente na (n+1)-ésima posição. */

int fibonacci (int n) {
    int v[n];
    v[0] = 0; v[1] = 1;
    return calculaFibonacci (n, 2, v);
}

/*  A função abaixo recebe n >= 0, i = 2 e v[].  */
/*  Preenche o subvetor v[2...n] e retorna v[n]  */
/*  para a função chamadora.                     */

int calculaFibonacci (int n, int i, int v[]) {
    if (i >= n) return ((n == 0) ? 0 : v[i-1] + v[i-2]);
    else v[i++] = v[i-1] + v[i-2];
    calculaFibonacci (n, i, v);
}

Até mais.

Written by rntreis

junho 2, 2012 at 1:29 pm

Publicado em C, dicas, programação

A função system()

leave a comment »

Uma função bastante interessante que temos em C é system(), cujo protótipo encontra-se no arquivo-cabeçalho stdlib.h e é o que se segue:

int system (const char *string)

Com ela, você pode chamar comandos do sistema em seu programa. Por exemplo, a seguinte chamada

system ("dir");

devolve o conteúdo da pasta na qual o seu programa está.

Para exemplo simples, fiz um programinha que faz uso do pacman do Arch Linux através de system(). Confira.

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

void main() {
    char nome[100];
    char comando[200] = "sudo pacman -S ";

    printf("Digite o nome do programa: ");
    gets(nome);

    strcat(comando, nome);

    printf("\n");

    system(comando);
}

É fácil perceber que com uma simples alteração no array comando podemos adaptar o programa para funcionar em outras distribuições (em Debian e derivados, poderíamos usar “sudo apt-get install “, por exemplo).

Até mais.

Written by rntreis

maio 31, 2012 at 11:33 am

Publicado em C, dicas, programação

Strcat() “caseira”

leave a comment »

A função strcat(), cujo protótipo se encontra no arquivo de cabeçalho string.h, recebe str1 e str2 e devolve str1, com o conteúdo de str2 copiado para o seu final. str2 não é alterada. Observe seu protótipo:

char *strcat(char *str1, const char *str2);

Naturalmente, em um programa em que essa função se faz necessária, é melhor que você a use direto. Não há nenhum motivo para reinventar a roda.

Mas como exercício pode ser interessante fazer uma versão própria da função, pra ter uma ideia legal de como ela pode funcionar.

Pensando nisso é que a sua construção é proposta em um exercício da apostila do Curso de Linguagem C, da UFMG (ótima apostila, aliás). E eu resolvi fazer. E se interessar a alguém, cá está, já inserida em um programinha para que ela possa ser testada.

 
#include <stdio.h>
#include <string.h>

char *strcat_caseira(char *str1, const char *str2);

void main() {
    char str1[80] = "isto é";
    char str2[80] = " um teste!";

    strcat_caseira(str1, str2);

    printf("%s\n\n", str1);
}

char *strcat_caseira(char *str1, const char *str2) {
    int i = strlen(str1), j;

    for (j = 0, i; str2[j]; j++, i++) str1[i] = str2[j];
    str1[i] = '\0'; // coloca o terminador nulo em str1

    return str1;
}

Até mais.

Written by rntreis

abril 18, 2012 at 8:26 pm

Publicado em C, dicas, programação

Scanf e o buffer do teclado

with one comment

As vezes quando nosso programa se propõe interativo, enfrentamos alguns problemas quanto às possibilidades de erros de entrada.

Observe a função abaixo:

void main() {
    int x, y;

    printf("Digite um numero: ");
    scanf("%d", &x);
    printf("Digite outro numero: ");
    scanf("%d", &y);

    printf("\n\n%d %d\n\n", x, y);
}

Se aqui o usuário digitar “1 2” para o primeiro scanf(), o segundo scanf() atribuiria automaticamente à y o número 2. Isso porque o programa não limpa o seu buffer automaticamente.

Para evitar dores de cabeça, um dos métodos para quem programa no Linux seria utilizar a função __fpurge().

O exemplo acima ficaria assim:

void main() {
    int x, y;

    printf("Digite um numero: ");
    scanf("%d", &x);
    __fpurge(stdin); // limpa o buffer do teclado
    printf("Digite outro numero: ");
    scanf("%d", &y);

    printf("\n\n%d %d\n\n", x, y);
}

O parâmetro stdin informa à __fpurge() que o stream do buffer que deverá ser limpado é o do teclado.

Se você usa Windows, a alternativa seria usar o fflush(). Assim:

void main() {
    int x, y;

    printf("Digite um numero: ");
    scanf("%d", &x);
    fflush(stdin); // também limpa o buffer do teclado
    printf("Digite outro numero: ");
    scanf("%d", &y);

    printf("\n\n%d %d\n\n", x, y);
}

Até mais.

Written by rntreis

abril 17, 2012 at 8:54 pm

Publicado em C, dicas