[Ajuda] Programa (simples) em C

Boa noite pessoal, precisava da vossa ajuda. Eu estou a dar os meus primeiros passos em C, estou a fazer exercícios básicos ainda, contudo tenho uma duvida neste programa:

/* Elabore um programa que gere os numeros do totoloto*/

#include <iostream>
#include <ctime>
using namespace std;
int main ()
{
int i, bola;
srand((unsigned) time (NULL));
for (i=1;i<7;i++){
bola = rand()%49+1;
cout << "O numero da bola e o " << bola<< '\n';
}
}


Ele funciona, mas tem um problema, imaginemos que a primeira bola é a bola 29, essa bola nao deveria voltar a sair, mas tal como o programa está feito isso acontece, gostava de saber o que acrescentar para que ele não repetisse a mesma bola duas vezes. Eu já tentei "inventar" algumas coisas mas não resultou. LOL. Podem-me ajudar?

Obrigado pela atenção.
 
Evil Tidus, podes-me explicar como se faz isso? Eu ainda estou a aprender e a ler sobre C. Podes exemplificar? Quem em deu o exercício disse que este erro pode ser ultrapassado com apenas duas linhas de código usando vectores ou algo do género, mas eu não estou a conseguir lá chegar..
 
Poderias fazer com um array (ou vector, é a mesma coisa) com as 6 posições, mas depois precisas de um ciclo extra para ver se a bola existia nesse array.

Outra forma pode ser, começas por declarar um vector com 50 posições a zero, uma para cada bola.
Depois no ciclo for, por exemplo sai-te a bola 12, se xpto[12] for igual a 1 é porque já te saiu essa bola e não contas essa, se for igual a 0, poes o xpto[12] a 1 e contas como uma bola que ainda não saiu.
 
Estás a fazer isso em C ou C++? É que essas bibliotecas são de C++.

Em C puro e sem grandes complicações faria assim:
Código:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main (void)
    {
    int i = 1, bola, xpto[51];
    memset( xpto, 0, 51 * sizeof(int) ); // Faz o mesmo que um ciclo que pusesse
                                         // todos os valores do array a zero
    srand((unsigned) time (NULL));
    
    while( i < 7 )
        {
        bola = rand() % 49 + 1;
        
        if( xpto[bola] == 0)
            {
            printf("O numero da bola e o %d\n", bola);
            xpto[bola] = 1;
            i++;
            }
        }
    return 0;
    }
 
Última edição:
Eu tou a tentar. Obrigado Aparicio. =)

Mas não estou a conseguir fazer a conversão, o que significa "%d\n" e a xpto[51]?

EDIT: Em principio só vou poder responder a este tópico para a semana. Depois eu digo alguma coisa, fiquem bem e obrigado aos dois por me terem ajudado. Acho que consegui o que queria. Abraço.
 
Última edição:
%d significa que o algarismo é inteiro. Por exemplo: printf("O número é %d.", a); em que 'a' é um algarismo do tipo int. xpto[51] é o valor armazenado na posição 51 do vector xpto.

Corrijam-me se estiver enganado. Também sou noob nisto. :D
 
Código:
#include <vector>
#include <iostream>
#include <ctime>

vector<bool> inicializaVector()
{
    vector<bool> numerosSaidos;
    for(int i=0; i<50; i++)
        numeros.push_back(false);

    return numerosSaidos;
}


int main()
{
	vector<bool> numerosSaidos = inicializaVector();
	srand((unsigned) time (NULL));

	for(int i=1;i<7;i++)
	{
		bola = rand()%49+1;
		if(numerosSaidos[bola] == TRUE)
			i--;
		else
		{
			cout << "O numero da bola e o " << bola<< '\n';
			numerosSaidos[bola] = TRUE;
		}
	}
	
	return 0;
}

Não testei.
 
Última edição:
porque é que inicializas 50 posições pra guardar 7

gastas menos memoria a inicializar as 7 posições e o algoritmo passar de n pra n^2 neste caso não é propriamente muito negativo
 
Mais uma implementação:

Código:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <iterator>
#include <stdlib.h>

int main() {
    std::vector<int> available_numbers;
  
    for(size_t i = 1; i < 51; i++)
        available_numbers.push_back(i);

    srand((unsigned) time(NULL));
    std::random_shuffle(available_numbers.begin(), available_numbers.end());

    std::ostream_iterator<int> output(std::cout, " ");
  
    std::cout << "Numeros sorteados: ";
    std::copy(available_numbers.begin(), available_numbers.begin() + 7, output);
    std::cout << std::endl;

    return 0;
}
 
Última edição:
porque é que inicializas 50 posições pra guardar 7

gastas menos memoria a inicializar as 7 posições e o algoritmo passar de n pra n^2 neste caso não é propriamente muito negativo

Isso depois dependo do que se quer, menos memória em mais tempo ou o contrário, mas se criares um array de 7 posições, depois para cada número que geras tens estar a percorrer o array para ver se o número já existe, não é muito elegante a meu ver.
A forma ideal seria utilizar um tipo lista, de forma a que se retirava literalmente os números da lista de forma a nunca saírem repetidos, mas para isto era preciso estar a implementar o tipo lista.
 
porque é que inicializas 50 posições pra guardar 7

gastas menos memoria a inicializar as 7 posições e o algoritmo passar de n pra n^2 neste caso não é propriamente muito negativo

Depende do que queres, maior performance ou menor gasto de recursos.
De qualquer forma um bool ocupa apenas um bit portanto o uso de memória não é nada excessivo.
 
Depende do que queres, maior performance ou menor gasto de recursos.
De qualquer forma um bool ocupa apenas um bit portanto o uso de memória não é nada excessivo.

neste caso não é algo que se tenha que preocupar, eu sou apologista de guardar apenas o essencial, discartando tudo que é redundante ou possivel de recalcular, isto na maioria dos casos

apesar de ser bool (0 ou 1) o tamanho de 1 bool não é um bit, mas sim um byte (na maioria dos compiladores), o int é 4 bytes

neste caso o array tem 50 bytes com acesso O(1)

a minha versão tinha 28 bytes (7*4 bytes) e apesar de ter que correr mais umas vezes o array (linearmente contra acesso directo do caso dos 50 bytes)

Aparicio podes sempre correr da posição inicial até apenas i
 
De qualquer forma um bool ocupa apenas um bit portanto o uso de memória não é nada excessivo.

Embora um bool deveria ocupar apenas um bit, na prática ocupa um byte, pelo menos em C.
Utilizando o stdbool.h, sizeof(bool) retorna 1 (byte).

Arranjei outra forma de resolver o problema, em que nem é preciso um array enorme nem percorrer o array várias vezes. Considerando o array como uma string e utilizando o strchr para ver se a bola já existe na string.

Código:
#include <stdio.h>

void aleat( char *xpto, int n, int min, int max )
    {   
    *xpto = rand() % max + min;
    if( n > 1 )
        do aleat( xpto+1, n-1, min, max );
            while( strchr( xpto+1, *xpto ) );
    }

int main(void)
    {    
    srand((unsigned) time (NULL));
       
    char xpto[8];
    memset( xpto, 0, 8);
    
    aleat( xpto, 7, 1, 50 );
    
    int x;
    for( x = 0; xpto[x] != 0; x++)
        printf("O numero da bola e o %d\n", xpto[x] );
    
    getchar();
    return 0;
    }
 
Embora um bool deveria ocupar apenas um bit, na prática ocupa um byte, pelo menos em C.
Utilizando o stdbool.h, sizeof(bool) retorna 1 (byte).

Arranjei outra forma de resolver o problema, em que nem é preciso um array enorme nem percorrer o array várias vezes. Considerando o array como uma string e utilizando o strchr para ver se a bola já existe na string.

Código:
#include <stdio.h>

void aleat( char *xpto, int n, int min, int max )
    {   
    *xpto = rand() % max + min;
    if( n > 1 )
        do aleat( xpto+1, n-1, min, max );
            while( strchr( xpto+1, *xpto ) );
    }

int main(void)
    {    
    srand((unsigned) time (NULL));
       
    char xpto[8];
    memset( xpto, 0, 8);
    
    aleat( xpto, 7, 1, 50 );
    
    int x;
    for( x = 0; xpto[x] != 0; x++)
        printf("O numero da bola e o %d\n", xpto[x] );
    
    getchar();
    return 0;
    }

bom exemplo de uso da recursividade e apontador
 
Back
Topo