Aprenda C

  • Página Inicial
  • Contato!
  • Tudo sobre C Parte 1!
  • Tudo sobre C Parte 2!
  • Tudo sobre C Parte 3!
  • Tudo sobre C Parte 4!
  • Tudo sobre C Parte 5!
  • Tudo sobre C Parte 6!
  • Tudo sobre C Parte 7!
  • Tudo sobre C Parte 8!
  • Tudo sobre C Parte 9!
  • Tudo sobre C Parte 8

    Estrutura de Dados - Pilha

    O Stack (pilha) é como um tubo fechado de um lado e aberto de outro, onde o primeiro elemento inserido é o último a sair e vice-versa. Alguns dos exemplos em que uma pilha pode ser usada é em mecanismos de desfazer/refazer de editores, navegação entre páginas web, etc.

    Veja como implementamos uma pilha em C:

    Estruturas e chamadas das funções:

    
    struct pilha {
        int topo; // Posição do elemento.
        int capa;
        float *prElem;
    };
    
    void criarPilha(struct pilha *p, int c);
    int estaVazia(struct pilha *p);
    int estaCheia(struct pilha *p);
    void empilhar(struct pilha *p, float v);
    float desempilhar(struct pilha *p);
    float retornaTopo(struct pilha *p);
    
    

    Implementações das funções:

    
    void criarPilha(struct pilha *p, int c) {
        p->topo = -1;
        p->capa = c;
        p->prElem = (float*)malloc(c * sizeof(float));
    }
    
    int estaVazia(struct pilha *p) {
        if(p->topo == -1) {
            return 1;
        }
    
        return 0;
    }
    
    int estaCheia(struct pilha *p) {
        if(p->topo == p->capa - 1) {
            return 1;
        }
    
        return 0;
    }
    
    void empilhar(struct pilha *p, float v) {
        p->topo++;
        p->prElem[p->topo] = v;
    }
    
    float desempilhar(struct pilha *p) {
        float aux = p->prElem[p->topo];
        p->topo--;
    
        return aux;
    }
    
    float retornaTopo(struct pilha *p) {
        return p->prElem[p->topo];
    }
    
    

    Código principal:

    
    struct pilha pl;
    int capac, op;
    float valor;
    
    printf("Capacidade da pilha? ");
    scanf("%d", &capac);
    
    criarPilha(&pl, capac);
    
    while(1) { // Loop infinito
        printf("\n1 - Empilhar (push)");
        printf("\n2 - Desempilhar (pop)");
        printf("\n3 - Mostrar o Topo (top)");
        printf("\n4 - Sair (exit)\n");
        printf("\nOpção? ");
        scanf("%d", &op);
    
        switch(op) {
            case 1: // push
                if(estaCheia(&pl) == 1) {
                    printf("\nPILHA CHEIA!\n");
                }
                else {
                    printf("\nValor? ");
                    scanf("%f", &valor);
                    empilhar(&pl, valor);
                }
                break;
            case 2: // pop
                if(estaVazia(&pl) == 1) {
                    printf("\nPILHA VAZIA!\n");
                }
                else {
                    valor = desempilhar(&pl);
                    printf("\n%.1f desempilhado!\n", valor);
                }
                break;
            case 3: // top
                if(estaVazia(&pl) == 1) {
                    printf("\nPILHA VAZIA!\n");
                }
                else {
                    valor = retornaTopo(&pl);
                    printf("\nTopo: %.1f\n", valor);
                }
                break;
            case 4:
                exit(0);
                break;
            default:
                printf("\nOPÇÃO INVÁLIDA!\n");
                break;
        }
    }
    
    

    PS: Podemos mudar o tipo de float para qualquer outro.

    Estrutura de Dados - Fila

    Diferente das pilhas, que funcionam como um "tubo", onde o último elemento é adicionado e somado até encher o tubo, as filas, os primeiros elementos saem à medida que entram novos, na verdade, as filas funcionam como "túneis". Em resumo, nas pilhas o último elemento é o primeiro a sair e vice-versa, nas filas o primeiro que entra é o primeiro que sai. Alguns dos exemplos em que uma fila pode ser usada é em controle de documentos (para impressão, por exemplo), troca de mensagem entre dispositivos numa rede, etc.

    Veja como implementamos uma fila em C:

    Estruturas e chamadas das funções:

    
    struct fila {
        int capac;
        float *dados;
        int prim;
        int ult;
        int itens;
    };
    
    void criarFila(struct fila *f, int c);
    void inserir(struct fila *f, int v);
    int remover(struct fila *f);
    int estaVazia(struct fila *f);
    int estaCheia(struct fila *f);
    void mostrarFila(struct fila *f);
    
    

    Implementações das funções:

    
    void criarFila(struct fila *f, int c) {
        f->capac = c;
        f->dados = (float*)malloc(f->capac * sizeof(float));
        f->prim = 0;
        f->ult = -1;
        f->itens = 0;
    }
    
    void inserir(struct fila *f, int v) {
        if(f->ult == f->capac - 1) {
            f->ult = -1;
        }
    
        f->ult++;
        f->dados[f->ult] = v;
        f->itens++; // Item inserido
    }
    
    int remover(struct fila *f) {
        int temp = f->dados[f->prim++];
    
        if(f->prim == f->capac) {
            f->prim = 0;
        }
    
        f->itens--; // Item retirado
    
        return temp;
    }
    
    int estaVazia(struct fila *f) {
        return f->itens == 0;
    }
    
    int estaCheia(struct fila *f) {
        return f->itens == f->capac;
    }
    
    void mostrarFila(struct fila *f) {
        int cont, i;
    
        for(cont = 0, i = f->prim; cont < f->itens; cont++) {
            printf("%.2f\t", f->dados[i++]);
    
            if(i == f->capac) {
                i = 0;
            }
        }
    
        printf("\n\n");
    }
    
    
    

    Código principal:

    
    int op, capa;
    float valor;
    struct fila fl;
    
    printf("Capacidade da fila? ");
    scanf("%d", &capa);
    
    criarFila(&fl, capa);
    
    while(1) { // Loop infinito
        printf("\n1 - Inserir Elemento (enqueue)");
        printf("\n2 - Remover Elemento (dequeue)");
        printf("\n3 - Mostrar Fila (peek)");
        printf("\n4 - Sair (exit)\n");
        printf("\nOpção? ");
        scanf("%d", &op);
    
        switch(op) {
            case 1: // enqueue
                if(estaCheia(&fl)) {
                    printf("\nFILA CHEIA!\n");
                }
                else {
                    printf("\nValor? ");
                    scanf("%f", &valor);
                    inserir(&fl, valor);
                }
                break;
            case 2: // dequeue
                if(estaVazia(&fl)) {
                    printf("\nFILA VAZIA!\n");
                }
                else {
                    valor = remover(&fl);
                    printf("\n%.1f removido!\n", valor);
                }
                break;
            case 3: // peek
                if(estaVazia(&fl)) {
                    printf("\nFILA VAZIA!\n");
                }
                else {
                    printf("\nConteúdo da fila: ");
                    mostrarFila(&fl);
                }
                break;
            case 4:
                exit(0);
                break;
            default:
                printf("\nOPÇÃO INVÁLIDA!\n");
                break;
        }
    }
    
    

    PS: Podemos mudar o tipo de float para qualquer outro.

    Manipulando Strings

    No C, temos a biblioteca string.h que permite manipular arrays de char (já que string mesmo não existe em C).

    Vamos supor esse código aqui:

    
    // Isso dará erro:
    char frase[20] = "Isso é uma string";
    char copia[20] = *frase;
    
    printf("%s\n", copia);
    
    

    Por serem arrays, não é possível copiar conteúdos de um array de char para outro. Nesse caso usamos o método strcpy, assim:

    
    char frase[20] = "Isso é uma string";
    char copia[20];
    
    strcpy(copia, frase); // Inclua string.h
    
    printf("%s\n", copia);
    
    

    Para concatenar, fazemos assim, usando o strcat:

    
    char frase[50] = "Isso é uma string";
    
    strcat(frase, " com mais alguma coisa!"); // Inclua string.h
    
    printf("%s\n", frase);
    
    

    E para retornar a quantidade de caracteres usamos o strlen, assim:

    
    char frase[20] = "Isso é uma string";
    
    int tam = strlen(frase);
    
    printf("Tamanho do array de char: %d\n", tam);
    
    

    Para ver se uma string está vazia, use a função strlen(), assim:

    
    char* nome = "";
    
    printf("Nome está vazio? %s\n", !strlen(nome) ? "true" : "false");
    
    

    Podemos usar o strcmp para comparar conteúdos de strings:

    
    char *f1 = "Frase 1";
    char *f2 = "Frase 2";
    
    char *resul = !strcmp(f1, f2) ? "iguais" : "diferentes";
    
    printf("As frases são %s.\n", resul);
    
    

    Se o resultado de strcmp for zero, as strings são iguais, se for menor o conteúdo é menor e se for maior que 0 o conteúdo é maior.

    Para encontrar uma palavra numa string, fazemos assim, com o método strstr:

    
    char frase[20] = "Isso é uma string";
    
    char *resul = strstr(frase, "string");
    
    if(resul != NULL) {
        printf("A palavra foi encontrada!\n");
    }
    else {
        printf("Não existe essa palavra na string!\n");
    }
    
    

    Para dividir uma string, usamos o método strtok assim:

    
    char frase[20] = "Isso é uma string";
    char *divi;
    
    divi = strtok(frase, " ");
    
    while(divi != NULL) {
        printf("%s\n", divi);
    
        divi = strtok(NULL, " ");
    }
    
    

    Para inverter, não usamos essa biblioteca, mas um algoritmo, como podemos ver:

    
    char frase[20] = "Isso é uma string";
    char invert[20];
    
    int tam = strlen(frase) - 1;
    int j = 0;
    
    for(int i = tam; i >= 0; i--) {
        invert[j] = frase[i];
        j++;
    }
    
    invert[j] = '\0'; // Finaliza string
    
    printf("%s\n", invert);
    
    

    E para eliminar espaços excessivos de uma string, implementamos essa função simples:

    
    char* trim(char *s) {
        int i;
    
        while(isspace(*s)) s++;
        for(i = strlen(s) - 1; isspace(s[i]); i--);
        s[i + 1] = '\0';
    
        return s;
    }
    
    

    E usamos assim:

    
    char frase[20] = "Isso é uma string";
    
    printf("%s\n", trim(frase));
    
    

    Podemos criar funções com o toupper() para transformar o texto em maiúscula, podemos fazer o mesmo com minúsculas usando tolower(), assim:

    
    // Inclua string.h e ctype.h
    
    char* maiuscula(char* texto);
    char* minuscula(char* texto);
    
    int main() {
        setlocale(LC_ALL, "portuguese");
        
        char *frase = "Uma Frase";
        char *maius, *minus;
        
        printf("%s\n", frase);
        
        maius = maiuscula(frase);
        
        printf("%s\n", maius);
        
        minus = minuscula(frase);
        
        printf("%s\n", minus);
        
        return 0;
    }
    
    char* maiuscula(char* texto) {
        unsigned long int tam = strlen(texto); 
    
        char aux[tam]; 
    
        for(int i = 0; i < tam; i++) {
            aux[i] = toupper(texto[i]); 
        }
        
        aux[tam] = '\0';
    
        texto = aux;
        
        return texto;
    }
    
    char* minuscula(char* texto) {
        unsigned long int tam = strlen(texto); 
    
        char aux[tam]; 
    
        for(int i = 0; i < tam; i++) {
            aux[i] = tolower(texto[i]); 
        }
        
        aux[tam] = '\0';
    
        texto = aux;
        
        return texto;
    }