| src | Program is finished but not totally tested yet | |
| tests | First commit | |
| .gitignore | First commit | |
| CMakeLists.txt | First commit | |
| README.md | First commit | |
Exercício: Simulador de Dados
- 1. Introdução
- 2. Descrição
- 3. Especificação da Command Line Interface
- 4. Exemplos de Uso e Saída Esperada
- 5. Requisitos de Implementação
- 6. Geração de números aleatórios
1. Introdução
Neste exercício proposto, vamos trabalhar o conceito de argumentos de linha de comando (argc / argv).
A utilização desse recurso do C/C++ é fundamental para implementarmos uma command line interface (CLI).
Esse tipo de interface com usuário, é muito comum em programas Linux que são
executados em um emulador de terminal.
Important
Conexão com o projeto passgen: a estrutura de parsing que você implementar aqui — iterar sobre
argv, detectar flags com prefixo--, consumir o próximo token como valor numérico e acumular flags booleanas independentes — é exatamente a mesma que será necessária no projeto passgen. Aproveite para criar uma lógica reutilizável.
Objetivos de Aprendizagem
Ao concluir este exercício você será capaz de:
- Declarar e usar corretamente
int argc, char* argv[]na assinatura domain; - Iterar sobre
argvpara identificar flags (--flag) e seus parâmetros numéricos; - Validar entradas numéricas e emitir mensagens de erro claras;
- Combinar múltiplas flags booleanas independentes para compor o comportamento do programa — habilidade diretamente transferível ao projeto passgen.
2. Descrição
O programa dice simula o lançamento de dados poliédricos. O usuário controla
o tipo de dado, o número de lançamentos e o formato da saída exclusivamente por
argumentos de linha de comando — sem nenhuma leitura interativa (std::cin).
A saída padrão do programa é uma listagem ordenada de todos os lançamentos feitos.
É possível alterar os valores padrão de execução, bem como as informações que o programa exibe por meio da utilização e configuração de flags, conforme detalhado na próxima seção.
3. Especificação da Command Line Interface
O programa dice pode receber os seguintes argumentos.
| Flag | Parâmetro | Descrição | Padrão |
|---|---|---|---|
--sides N |
inteiro > 0 | Número de faces do dado | 6 |
--rolls N |
inteiro > 0 | Quantidade de lançamentos | 1 |
--sum |
— | Exibe a soma total dos lançamentos | off |
--stats |
— | Exibe mínimo, máximo e média | off |
--verbose |
— | Mostra cada resultado individualmente | off |
--help ou -h |
— | Exibe as instruções de uso do programa | off |
Note
O programa
dicedeve aceitar as flags acima especificadas em qualquer ordem.
4. Exemplos de Uso e Saída Esperada
4.1 Uso mínimo — um lançamento, dado padrão (6 faces)
$ ./dice
Resultado(s): 4
4.2 Solicitação de ajuda
$ ./dice -h
-- Welcome to dice simulation --
This program simulates a dice row
Usage: dice [<options>]
--sides n The number (>0) of dice faces (default is 6, max is 65535)
--rolls n Defines how many times (>0) the dice is rolled (default is 1, max is 65535)
--sum Prints the sum of all rolled faces
--stats Prints min, max and median of the values rolled
--verbose Prints extra information
-h, --help Show this help screen.
4.3 Especificando dado e número de lançamentos
$ ./dice --sides 8 --rolls 15
Resultado(s): 1 2 3 4 4 4 5 5 6 6 6 6 7 8 8
4.4 Flag --verbose
$ ./dice --sides 8 --rolls 10 --verbose
--> 🎲 Lançamento #1: 4
--> 🎲 Lançamento #2: 1
--> 🎲 Lançamento #3: 7
--> 🎲 Lançamento #4: 1
--> 🎲 Lançamento #5: 4
--> 🎲 Lançamento #6: 6
--> 🎲 Lançamento #7: 6
--> 🎲 Lançamento #8: 8
--> 🎲 Lançamento #9: 2
--> 🎲 Lançamento #10: 7
--------------------
Resultado(s): 1 1 2 4 4 6 6 7 7 8
4.5 Flag --sum
$ ./dice --sides 6 --rolls 4 --sum
Resultado(s): 1 3 5 6
Soma: 15
4.6 Flag --stats
$ ./dice --sides 6 --rolls 5 --stats
Resultado(s): 1 2 3 5 6
Mínimo: 1 | Máximo: 6 | Média: 3.40
4.7 Combinando múltiplas flags
$ ./dice --sides 8 --rolls 4 --verbose --sum --stats
--> 🎲 Lançamento #1: 2
--> 🎲 Lançamento #2: 1
--> 🎲 Lançamento #3: 7
--> 🎲 Lançamento #4: 3
--------------------
Resultado(s): 1 2 3 7
Soma: 13
Mínimo: 1 | Máximo: 7 | Média: 3
4.8 Casos de erro — validação obrigatória
Fornecer um valor fora da faixa do unsigned short, ou um valor zero.
$ ./dice --sides 0
>>> Error: Invalid or absent integer value argument provided for the --sides flag.
$ ./dice --sides 65900
>>> Error: Invalid or absent integer value argument provided for the --sides flag.
Esquecer de fornecer o valor numérico para os argumentos que requerem um valor.
$ ./dice --rolls
>>> Error: Missing number of rolls.
$ ./dice --sides
>>> Error: Missing number of faces.
Fornecer um argumento inválido.
$ ./dice --foo
>>> Error: Unrecognised argument "--foo"!
5. Requisitos de Implementação
Obrigatório:
- O programa deve usar exclusivamente
argceargv— semgetopt,argparseou bibliotecas externas; - A geração de números aleatórios deve usar
std::mt19937semeado comstd::random_device; - Erros devem ser impressos em
stderre o programa deve retornar código de saída1; - O código deve compilar sem warnings com
g++ -std=c++17 -Wall -Wextra -pedantic.
Opcional (bônus):
Implemente os seguintes flags extras:
| Flag | Parâmetro | Descrição | Padrão |
|---|---|---|---|
--seed N |
inteiro > 0 | Define a semente do gerador, tornando os resultados reprodutíveis | randômico |
--histogram |
— | Exibe um histograma ASCII dos resultados | off |
6. Geração de números aleatórios
Aqui um programa exemplo, random_demo.cpp, adaptado
desta
referência.
#include <iostream>#include <random>
constexpr short n_times{10}; // How many times to run the dice?
int main() {
std::random_device rd; // a seed source for the random number engine
#if FIXED_SEED
// NOTE:
// Fixed seed means the random generation process always produces the same
// sequence of number
std::mt19937 gen(3);
#else
// NOTE:
// Random seed created wit rd()
std::mt19937 gen(rd());
#endif // FIXED_SEED
std::uniform_int_distribution<> distrib(1, 6);
// Use distrib to transform/map the random unsigned int
// generated by gen into an int in [1, 6]
for (auto n{0}; n < n_times; ++n)
std::cout << distrib(gen) << ' ';
std::cout << '\n';
}
É possível compilar o programa random_demo.cpp de duas formas, descritas a
seguir.
A versão abaixo, com o -DFIXED_SEED, faz com que a execução do programa
produza sempre a mesma sequência, já que a semente de geração está fixa.
Esse controle é muito útil quando se deseja depurar programas, de alguma forma, utilizam valores aleatórios gerados pelo programa. Com o uso da semente fixa, é possível replicar facilmente o resultado de uma execução com geração aleatória.
$ g++ -Wall -std=c++17 random_demo.cpp -DFIXED_SEED
Já a versão abaixo, gera números diferentes a cada execução, visto que
a semente passa a ser gerada randomicamente por rd().
$ g++ -Wall -std=c++17 random_demo.cpp
Para se aprofundar na forma como o C++ trabalha com geração de números
aleatório, recomendo a leitura dessa página.
Outra boa referência, mais didática, é este capítulo
do learncpp.com.
The end