Médio C

Manipular flags de permissão

Enunciado

Defina três flags: READ (bit 0), WRITE (bit 1) e EXEC (bit 2). Leia comandos do usuário no formato +R, -W, +X até receber 0. Atualize um inteiro flags e, ao final, imprima o valor em hexadecimal e quantas flags estão ligadas.

Requisitos

  • Usar |= para ligar e &= ~ para desligar flags.
  • Contar bits ligados com um laço ou truque x &= x - 1.
  • Imprimir valor em hexadecimal com %X e a contagem.

Código inicial

#include <stdio.h>

int main(void) {
    unsigned int flags = 0;
    const unsigned int READ = 1u << 0;
    const unsigned int WRITE = 1u << 1;
    const unsigned int EXEC = 1u << 2;

    char op;
    char flag;
    // leia comandos até '0'

    return 0;
}

Saída esperada

flags = 0x5
bits ligados = 2
Ver dica

Leia a operação e a flag com scanf(" %c%c", &op, &flag). Use um switch ou if para escolher a máscara correta.

Mostrar solução
#include <stdio.h>

int count_bits(unsigned int x) {
    int count = 0;
    while (x) {
        x &= x - 1;  // remove o bit 1 mais baixo
        count++;
    }
    return count;
}

int main(void) {
    unsigned int flags = 0;
    const unsigned int READ = 1u << 0;
    const unsigned int WRITE = 1u << 1;
    const unsigned int EXEC = 1u << 2;

    char op, flag;
    while (scanf(" %c%c", &op, &flag) == 2) {
        if (op == '0') break;  // comando de parada

        unsigned int mask = 0;
        switch (flag) {
            case 'R': mask = READ; break;
            case 'W': mask = WRITE; break;
            case 'X': mask = EXEC; break;
            default: continue;  // ignora flag inválida
        }

        if (op == '+') {
            flags |= mask;      // liga flag
        } else if (op == '-') {
            flags &= ~mask;     // desliga flag
        }
    }

    printf("flags = 0x%X\n", flags);
    printf("bits ligados = %d\n", count_bits(flags));
    return 0;
}

Passo a passo

  1. Definimos as flags como potências de dois: 1u << 0, 1u << 1, 1u << 2.
  2. O laço while lê pares de caracteres (operação e flag) até o fim da entrada ou até op == '0'.
  3. Um switch mapeia a letra da flag para a máscara correspondente.
  4. Se a operação for +, usamos flags |= mask para ligar o bit; se for -, usamos flags &= ~mask para desligá-lo.
  5. A função count_bits usa x &= x - 1 para apagar o bit 1 mais baixo a cada iteração, contando quantos havia.
  6. No final, imprimimos o valor em hexadecimal e a contagem.

Por que funciona

Flags são representadas por bits independentes. O OR (|=) liga um bit sem afetar os outros; o AND com NOT (&= ~) desliga um bit específico. A contagem com x &= x - 1 é eficiente porque cada iteração remove exatamente um bit 1, independentemente da posição.

Erros comuns

  • Usar flags |= ~mask para desligar: isso ligaria todos os bits exceto o desejado. O correto é flags &= ~mask.
  • No scanf, usar "%c%c" sem espaço antes do primeiro %c, o que pode consumir o newline anterior e bagunçar a leitura. Use " %c%c".
  • Esquecer de tratar op == '0' e entrar em loop infinito se a entrada não terminar.

Outra forma de resolver

Pode-se usar uma tabela de máscaras e uma função separada para aplicar a operação, mas a solução acima já é clara e direta.

Saída esperada

flags = 0x5
bits ligados = 2