Ir ao conteúdo

arfneto

Membro Pleno
  • Posts

    6.526
  • Cadastrado em

  • Última visita

Tudo que arfneto postou

  1. Unicode e o bloco de expoentes e índices são o caminho. Atente para os links postados acima por @dudaskank wchar.h e locale.h estão disponíveis em windows e Linux. Mas escrever na console é sempre um pesadelo a menos que se contente com os subscritos 2 e 3, eu acho. Mudar a página de código para 65001 Em especial se você tenta gravar isso em algum lugar usando FILE* ou um Handle, ou se coloca seu comando que ia para a console em um | por exemplo para tentar classificar --- tipo programa | sort | less. Recomendo muito evitar isso. Isso já foi tratado com sucesso em outros meios, como e-mail, XML, HTML e tal. É muito mais simples gerar HTML e abrir no browser que mostra qualquer coisa... Se precisar insistir nisso, antes de qualquer coisa muda a fonte da console do windows --- se estiver usando windows --- para alguma fonte True Type. Mas entenda que se você muda de computador ou envia seu programa para alguém.. já era. Mais uma razão para usar o navegador, ou XML, ou HTML... WEBGL por exemplo é bem simples e foi feito com esse objetivo: escrever fórmulas e equações na tela. Escrevi algumas coisas com isso mas não tem nessa máquina. Escreva de novo se tiver interesse e posso postar aqui.
  2. Olá Esse não é bem um exercício de programação. Parece mais um teste de psicotécnico Repare que são 3 sequências... 1 2 3 3 6 9 5 10 15 dividindo por 3... 1 2 3 (1*3) (2*3) (3*3) (1*5) (2*5) (3*5) Então um loop externo passando por 1 3 e 5 um loop interno passando por 1 2 e 3 E você tem seu resultado... for (int i = 1; i < 7; i = i + 2) for (int j = 1; j < 4; j++) printf("%d ", (i * j)); Por exemplo... Estou postando o for porque é só uma transcrição do que está escrito acima em português... Não creio que vá contra as regras do forum
  3. Olá! Quem escreveu isso podia ter escrito mais claramente. Um vetor de 30 posições tem, imagino, 30 posições. E se você escrever além da posição 29, já que as posições no vetor começam em zero, seu programa deve cancelar por violação de acesso ou outro erro assim. Provavelmente o que era para estar escrito era algo assim: Criar um algoritmo que preencha um vetor de 30 posições com números múltiplos de 2 até o número 60. Como metade dos números é par até 60 temos 30 deles e o vetor vai ficar cheio... O segundo item também não está bem redigido: imagino que a ideia era mostrar o múltiplo de 2 e a posição do vetor que ele acabou ocupando, um par valor/posição por linha Esse também não está bom: imagino que era para imprimir os valores e não os vetores, já que vetor só tem um --- ao menos é o que diz no item 1 --- do menor para o maior, separado por vírgula e com ponto ao final Provavelmente para 5 pares seria para imprimir 2 0 4 1 6 2 8 3 10 4 E depois 2,4,6,8,10. De volta ao problema (supondo que o enunciado seja esse): O primeiro --- 2 --- estará na posição zero. O segundo --- 4-- na posição 1 e assim por diante. Então o valor do vetor na posição y é y = 2x + 2 E para y = 29, o último, teremos 60, como esperado desde o ensino fundamental De volta ao C Então temos um vetor de 30 posições a ser preenchido com múltiplos de 2. Pode ser declarado int vetor[30]; Tem claro muitas opções pra isso. Exemplos Opção: um comando for usando a funcao // 1 for (int i = 0; i<30; i = i+1) { vetor[i] = i + i + 2; } Opção: um comando for usando os limites de 2 e 60 inclusive // 2 i = 0; for (int valor = 2; valor <= 60; valor = valor + 2) { vetor[i] = valor; i = i + 1; } Opção: um comando do{}while() usando o valor e o indice //3 valor = 2; i = 0; do { vetor[i] = valor; valor += 2; } while (valor <= 60); Opção: um comando while similar //4 valor = 2; i = 0; while (i < 30) { vetor[i] = valor; valor += 2; i = i + 1; } Opção: um comando for com os valores e índices dentro do comando //5 for (valor = 2, i = 0; i < 30; i = i + 1, valor=valor+2) { vetor[i] = valor; } Opção romântica: O comando goto e um label como nos anos 60: //6 valor = 2; i = 0; de_novo: vetor[i] = valor; i++; valor += 2; if (i < 30) goto de_novo; O código para mostrar os valores pode ser algo assim printf("vetor:\n"); for (int i = 0; i < n-1; i++) printf("%d, ", vetor[i]); printf("%d.\n", vetor[n - 1]); E mostraria algo assim vetor: 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60. Escrever um par por linha é similar...
  4. E estamos escrevendo em C++ então compare struct Numero { int num; } Numero* num = new Numero[qtde]; Com o pobre num sózinho na struct e você tendo que declarar um vetor de Numero para na verdade declarar um vetor de num. E os valores de maior e menor que só tem a ver com um vetor de Numero? Por isso C++ --- ou qualquer outra linguagem com objetos --- é tão mais expressiva que C em termos de relações entre as coisas. Veja um outro exemplo em C++: struct Numeros { int maior; int menor; int* valores; Numeros(int quantos) { valores = new int[quantos]; } }; Numeros num = Numeros(qtde); Numeros outro = Numeros(30); Numeros um = Numeros(1500); Nesse caso cada struct Numero tem o que importa: o vetor do tamanho certo, mais o maior e o menor elemento. E quando você declara uma o sistema cria as variáveis menor e maior e aloca a memória necessária para o vetor valores[] E como ficaria um programa C++ usando isso? Uma possibilidade: Pense assim: primeiro você declara uma dessas estruturas. Em C++ são chamadas de classes, e já lê um primeiro valor int quantos; int v; cout << "Quantos? : "; cin >> quantos; if (quantos < 1) return 0; Numeros num = Numeros(quantos); cout << "Primeiro Valor: "; cin >> v; num.menor = v; num.maior = v; num.valores[0] = v; Claro que tem outras maneiras de resolver, mas queremos só resolver o que foi pedido e vamos fazer como se fosse em uma ficha de papel, nesse exemplo. Então agora posso ler o resto. A cada número novo, não vou perder a oportunidade de já ver se é o maior ou o menor da série até aqui. O trecho abaixo lê todos os valores e marca o menor e o maior for (int n = 0; n < quantos-1; n++) { cout << "Valor " << n + 2 << " de " << quantos << ": "; cin >> v; if (v > num.maior) num.maior = v; if (v < num.maior) num.menor = v; num.valores[n+1] = v; } // end for Esse trecho mostraria todos na tela // agora mostra os valores... cout << quantos << " valores" << endl; cout << "menor valor: " << num.menor << endl; cout << "maior valor: " << num.maior << endl; cout << "valores: " << endl; for (int n = 0; n < quantos; n++) cout << num.valores[n] << endl; Mostraria na tela algo assim depois de ler o primeiro e os outros como acima Quantos? : 5 Primeiro Valor: 5 Valor 2 de 5: 4 Valor 3 de 5: 3 Valor 4 de 5: 2 Valor 5 de 5: 1 5 valores menor valor: 1 maior valor: 5 valores: 5 4 3 2 1 E pra colocar na ordem? Seguindo o princípio de não fazer mais do que o que foi pedido e a necessidade de não fazer menos que o pedido: podemos já ir colocando os números em ordem no vetor. Já sabemos que cabem todos porque foi a primeira coisa que perguntamos pro usuário. E alocamos o espaço de acordo. Quando lemos os valores no loop já tem o primeiro lá, por simplicidade. Quando só tem um já está resolvido:o único é o menor, o maior, o mais bonito, o mais solitário e tudo mais. E o segundo loop não executaria nem uma única vez. Tudo certo. Mostraria isso para um só: Quantos? : 1 Primeiro Valor: 150 1 valores menor valor: 150 maior valor: 150 valores: 150 E como colocar em ordem sem criar um método e varrer o vetor todo de novo? Podemos pensar que com um elemento só sempre está em ordem ao colocar mais um posso ir vendo a partir dos que estão lá e arrumar o lugar pro novo deslocando todos os maiores para baixo. Simples assim. int ix; for (ix=n+1; ix>0; ix--) { // comeca do final if ( v > num.valores[ix-1] ) break; num.valores[ix] = num.valores[ix-1]; // abre espaco } // end for num.valores[ix] = v; // ix marca o lugar certo Apenas antes de colocar a gente abre um espaço para ele no lugar certo, ix.E não é que funciona? Quantos? : 4 Primeiro Valor: 4 Valor 2 de 4: 3 Valor 3 de 4: 2 Valor 4 de 4: 1 4 valores menor valor: 1 maior valor: 4 valores: 1 2 3 4 Por exemplo... Eis um programa de teste: #include <iostream> using namespace std; struct Numeros { int maior; int menor; int* valores; Numeros(int quantos) { valores = new int[quantos]; } }; int main() { int quantos; int v; cout << "Quantos? : "; cin >> quantos; if (quantos < 1) return 0; Numeros num = Numeros(quantos); cout << "Primeiro Valor: "; cin >> v; num.menor = v; num.maior = v; num.valores[0] = v; for (int n = 0; n < quantos-1; n++) { cout << "Valor " << n + 2 << " de " << quantos << ": "; cin >> v; if (v > num.maior) num.maior = v; if (v < num.maior) num.menor = v; int ix; for (ix=n+1; ix>0; ix--) { // comeca do final if ( v > num.valores[ix-1] ) break; num.valores[ix] = num.valores[ix-1]; // abre espaco } // end for num.valores[ix] = v; // ix marca o lugar certo } // end for // agora mostra os valores... cout << quantos << " valores" << endl; cout << "menor valor: " << num.menor << endl; cout << "maior valor: " << num.maior << endl; cout << "valores: " << endl; for (int n = 0; n < quantos; n++) cout << num.valores[n] << endl; return 0; } Espero que ajude a entender uma diferença entre C e C++
  5. Olá! Talvez esteja se preocupando com mais que o necessário. Métodos para ordenar e encontrar maior e menor valor e tal. Pensando de um modo ingênuo até, encontrar o menor e o maior é o mesmo serviço então não precisa fazer duas vezes. Ordenar se vai ler um por um talvez não seja preciso, já que vem um por um. Você pode simplesmente colocar cada um já no seu lugar e assim não precisa arrumar depois... E já que vem um por um porque não marcar logo o maior e o menor vistos até o momento?
  6. Que pretende com esse código? E um anexo nada a ver de um programa em C advogando o uso de phyton em um forum de discussão sobre C C++ C#?
  7. Olá Esqueci do programa de teste #define _CRT_SECURE_NO_WARNINGS #include <locale.h> #include "memory.h" #include <stdio.h> #include <stdlib.h> #include <string.h> struct Mercado { char nome[30]; char marca[30]; float valor; int estoque; }; typedef struct Mercado mercado; void imprime(mercado*); void imprime_estoque(mercado*); void Leproduto(mercado*); void Leprodutos(mercado*, int); int main() { int flag = 0; int t = 0; setlocale(LC_ALL, "Portuguese"); mercado* P; int quant, i; mercado um; mercado cem_mercados[100]; um.estoque = 2; printf("a partir de um, deve imprimir 2\n"); imprime_estoque(&um); P = &um; printf("a partir de P=&um, deve imprimir 2\n"); imprime_estoque(P); P->estoque = um.estoque + 1; printf("(P->estoque = um.estoque + 1) e a MESMA variavel. Soma 1\n"); imprime_estoque(P); cem_mercados[99].estoque = P->estoque + 1; printf("(cem_mercados[99].estoque = P->estoque + 1)\n"); printf("a partir de P copiou para o ultimo dos vetores\n"); imprime_estoque(cem_mercados + 99); printf("( &(cem_mercados[99]) ) uma outra maneira de acessar\n"); printf("usando o endereco do vetor na posicao 99\n"); imprime_estoque( &(cem_mercados[99]) ); // if (flag == 0) return 0; printf("Quantidade de cadastros: "); scanf("%d", &quant); t = quant * sizeof(mercado); P = (mercado*)malloc(t); if (P == NULL) { printf("Alocação indisponível\n"); return 1; } else { printf("Alocados %d bytes para %d estruturas \"mercado\" de %d bytes\n", t, quant, sizeof(mercado)); } puts(""); Leprodutos(P, quant); for (i = 0; i < quant; i++) { imprime( P+i ); } return 0; } void imprime(mercado* v) { printf("Nome: %s\n", v->nome); printf("Marca: %s\n", v->marca); printf("Valor: %.2f\n", v->valor); printf("Estoque: %d\n", v->estoque); } void imprime_estoque(mercado* v) { printf("Total no estoque: %d\n", v->estoque); } void Leproduto(mercado* v) { printf("Nome do Produto: "); fflush(stdin); scanf("%s", v->nome); printf("Marca do Produto: "); fflush(stdin); scanf("%s", v->marca); printf("Valor do Produto: "); scanf("%f", &(v->valor)); printf("Quantidade em Estoque: "); scanf("%d", &(v->estoque)); printf("\n\n"); } void Leprodutos(mercado* v, int n) { int i; for (i = 0; i < n; i++) { Leproduto(v + i); } }
  8. Olá Seu programa está quase certo, mas está confundindo talvez esses operadores de endereço, * & -> e tal. Talvez não tenha sido explicado muito sobre o modo como C endereça memória e o que se convenciona chamar de aritmética de ponteiros, que é provavelmente o recurso mais importante dessa linguagem e a razão para se escrever sistemas e programar chips com programas em C. Considere struct Mercado { char nome[30]; char marca[30]; float valor; int estoque; }; typedef struct Mercado mercado; mercado um; mercado* P; mercado trezentos_mercados[300]; Isso declara uma estrutura do tipo mercado em um, mais um vetor com 300 mercado em m. E P é uma variável que pode conter um endereço de uma coisa dessas, mercado. E como endereçar essas coisas? No caso do vetor, tem duas maneiras de você acessar. trezentos_mercados é um ponteiro para mercado, assim como P. É muito importante entender isso: trezentos_mercados e P são ponteiros para mercado. Só que trezentos_mercados é constante e P não. Então eu posso escrever por exemplo quant = 1; t = quant * sizeof(mercado); printf("Alocados %d bytes para %d estruturas \"mercado\" de %d bytes\n", t, quant, sizeof(mercado)); P = trezentos_mercados; P = &um; P = (mercado*)malloc(t); E ver isso na tela Alocados 68 bytes para 1 estruturas "mercado" de 68 bytes Alocados 68 bytes O operador & extrai o endereço de um, que é do tipo mercado. E P é do mesmo tipo, então está correto escrever P = &um. trezentos_mercados foi declarado como vetor de 300 mercado e então a variável em si contem o endereço da primeira ocorrência de trezentos_mercados, trezentos_mercados[0]. E então está certo escrever P = trezentos_mercados. mercado* coisa; declara coisa como um ponteiro para mercado e por isso eu acho sempre mais claro --- em especial para inciantes --- declarar os ponteiros em separado para que não se precise ficar fazendo essa operação mental no meio de uma lista assim mercado um, *P, *coisa, cem_mercados[100]; para entender que P e coisa são ponteiros. Veja a diferença mercado um, cem_mercados[100]; mercado* P; mercado* coisa Talvez concorde que é mais claro escrever assim. De volta ao seu programa. Como endereçar as coisas? Escrevi essa função a partir da sua imprime() e ela só escreve uma linha com o valor do estoque do item. Recebe um ponteiro para mercado void imprime_estoque(mercado* v) { printf("Total no estoque: %d\n", v->estoque); } E considere esse código um.estoque = 2; printf("a partir de um, deve imprimir 2\n"); imprime_estoque(&um); P = &um; printf("a partir de P=&um, deve imprimir 2\n"); imprime_estoque(P); P->estoque = um.estoque + 1; printf("(P->estoque = um.estoque + 1) e a MESMA variavel. Soma 1\n"); imprime_estoque(P); cem_mercados[99].estoque = P->estoque + 1; printf("(cem_mercados[99].estoque = P->estoque + 1)\n"); printf("a partir de P copiou para o ultimo dos vetores\n"); imprime_estoque(cem_mercados + 99); printf("( &(cem_mercados[99]) ) uma outra maneira de acessar\n"); printf("usando o endereco do vetor na posicao 99\n"); imprime_estoque( &(cem_mercados[99]) ); E mostra isso: a partir de um, deve imprimir 2 Total no estoque: 2 a partir de P=&um, deve imprimir 2 Total no estoque: 2 (P->estoque = um.estoque + 1) e a MESMA variavel. Soma 1 Total no estoque: 3 (cem_mercados[99].estoque = P->estoque + 1) a partir de P copiou para o ultimo dos vetores Total no estoque: 4 ( &(cem_mercados[99]) ) uma outra maneira de acessar usando o endereco do vetor na posicao 99 Total no estoque: 4 Assim você pode comparar as possíveis maneiras de acessar a estrutura a partir do ponteiro. Sobre seu programa: use sempre o endereço de uma ocorrência de mercado nas funções. Talvez ache favorável declarar todas as funções assim no início do programa: void imprime(mercado*); void imprime_estoque(mercado*); void Leproduto(mercado*); void Leprodutos(mercado*, int); Apenas os nomes e tipos. Não precisa colocar nomes de variáveis nem nada. Depois de main() por exemplo você declara as funções normalmente. Assim não precisa ficar se preocupando com a ordem em que estão escritas...E fica fácil de conferir os parâmetros em uso Se leu até aqui talvez já tenha entendido porque seu programa não funcionou. Mas veja essa Le_produtos() que funciona: void Leprodutos(mercado* v, int n) { int i; for (i = 0; i < n; i++) { Leproduto( v+i ); } A diferença? incrementar o endereço de v a cada chamada para não gravar um produto em cima do outro.... Eis a original void Leprodutos(mercado *v, int n) { int i; for(i=0;i<n;i++) { Leproduto(&v[i]); } }
  9. Chegou a ler o que eu expliquei? Esse lance das letras é um pesadelo, em especial se você não usa Windows 10. Esses códigos que usa são baseados na emulação de um terminal DEC VT-100 e você pode encontrar isso no manual do próprio, ou no manual do xterm. Os comandos em geral começam por ESCAPE como você deve ter visto. octal 33, decimal 27. ESC depois [ depois algo selecionam modo de video, endereçam o cursor, mudam a cor e tal. E esses caracteres são interpretados antes de ir para a tela. Isso funciona bem no Unix e derivados mas no Windows sempre foi um inferno. E também tem a questão das fontes e da página de código e dos caracteres multi-byte... Como eu disse, a partir da edição de aniversário do windows 10 e da criação do WSL --- o subsistema linux --- isso ficou muito melhor. E agora o Windows tem uma coisa chamada Pseudo-console que permite interpretar melhor esses caracteres VT-coisas Citado em https://devblogs.microsoft.com/commandline/windows-command-line-inside-the-windows-console/ em 20/Julho/2018 Veja essa imagem da mesma fonte mostrando uma mesma tela de uma aplicação de console no Windows 7 e no Windows 10 Não sei de sua familiaridade ou necessidade de tratar essas coisas, mas há grandes problemas em usar aplicativos de console feitos para rodar nesses terminais --- consoles --- usando bibliotecas como curses ou ncurses ou sei lá, mas no windows. Basta ver aquela tela acima... E ver que desde 2014 isso está sendo reescrito pela microsoft...
  10. Olá! Acho que eu já escrevi algo assim aqui: se você está aprendendo e começou hoje aproveite o fato de ter um computador, que é a coisa mais paciente do mundo, e faça a coisa aos poucos. Digite no seu próprio programa por exemplo uma "grade" com o que quer imprimir. Algo assim: /* Matriz Total da Linha 1 2 3 4 5 15 11 12 13 14 15 65 21 22 23 24 25 115 31 32 33 34 35 165 41 42 43 44 45 215 000000 000000 000000 000000 000000 1111111 * 1 * 2 * 3 * 4 * 5 * 6 colunas 123456789012345678901234567890123456789012345678901234567890 */ Em C é só um comentário mas já serve pra você alinhas as coisas e planejar tipo 6 posições para o valor de cada coluna, oito para o total da coluna, alinhar os títulos tal. As duas linhas de baixo tem as colunas marcadas de 5 em 5 posições para o caso de precisar saber. Já pode copiar o título direto pro printf() por exemplo char* titulo = " Matriz Total da Linha"; E preencher a matriz como está lá no comentário: tudo com números diferentes porque já sabe como deve imprimir... Depois você lê os valores! Porque é um porre tentar ajustar a impressão compilando e rodando o programa para cada teste e digitando uma porrada de números.... certo? int n_linhas = 3; int n_colunas = 5; int matriz[3][5]; int total[5]; char* titulo = " Matriz Total da Linha"; // preenhe a matriz com algo conhecido pra ver se esta alinhado for (int linha = 0; linha <n_linhas; linha++) { // para cada linha vai rodar isso e preencher as colunas for (int coluna = 0; coluna < n_colunas; coluna++) { matriz[linha][coluna] = 10 * linha + (1+coluna); } } // end for // calcula a soma da primeira linha total[0] = 0; for (int c = 0; c < n_colunas; c++) { total[0] = total[0] + matriz[0][c]; } // end for printf("Usando matriz[%d,%d]\n", n_linhas, n_colunas); printf("%s\n", titulo); // imprime a linha 0 pra ver printf("%6d %6d %6d %6d %6d %8d\n", matriz[0][0], matriz[0][1], matriz[0][2], matriz[0][3], matriz[0][4], total[0] ); E ia mostrar para a primeira linha Usando matriz[3,5] Matriz Total da Linha 1 2 3 4 5 15 Claro que você deve declarar um total[5] para os totais e não total1, total2 e tal.... Porque? Só porque é mais prático. Imagine se precisar mudar para 200 linhas... E se fosse imprimir a matriz inteira? igualzinho. veja a vantagem de ter um vetor para os totais: você pode escrever for (int linha = 0; linha < n_linhas; linha++) { // vai somar a linha matriz[linha][c] total[linha] = 0; // sem surpresas for (int c = 0; c < n_colunas; c++) { total[linha] = total[linha] + matriz[linha][c]; } // end for } // end for E pode zerar o contador antes de somar a respectiva linha porque total tem o total da linha i E imprimir? Como a gente usou a grade pra contar as posições fica trivial: imprime as colunas, o total e pula de linha // // e para imprimir? igualzinho // printf("\n\n\n"); // pula umas linhas printf("%s\n", titulo); for (int linha = 0; linha < n_linhas; linha++) { // agora as n_colunas na mesma linha for (int coluna = 0; coluna < n_colunas; coluna++) { printf("%6d ", matriz[linha][coluna]); // numero com 6 digitos, dois espacos } // veja na grade la em cima: 8 espacos e o total com oito posições printf(" %8d\n", total[linha]); } // end for E veria algo assim Matriz Total da Linha 1 2 3 4 5 15 11 12 13 14 15 65 21 22 23 24 25 115 31 32 33 34 35 165 41 42 43 44 45 215 Agora quando o usuário digitar os valores já se sabe que a impressão vai estar ok....
  11. arfneto

    C++ como converte para c

    Bem, como eu disse não vejo muito a ser convertido de C++ para C aí. São apenas duas funções, não tem classes, não alocam memória nem nada. Aquele primeiro loop de que falei não tem sentido em C ou C++ por exemplo O código abaixo, que é o mesmo que postou, compila em C. Mas duvido que resolva algo. long long int merge_count(int A[], int B[], int p, int q, int r) { int i, j, k; long long int c; for (i = p; i <= q; i++) B = A; for (j = q + 1; j <= r; j++) B[r + q + 1 - j] = A[j]; i = p; j = r; c = 0; for (k = p; k <= r; k++) { if (B <= B[j]) { A[k] = B; i = i + 1; } else { A[k] = B[j]; j = j - 1; c = c + (q - i + 1); } // end for } // end for return c; } // end merge_count() long long int sort_count(int A[], int B[], int i, int j) { int q; if (i >= j) return 0; q = (i + j) / 2; return sort_count(A, B, i, q) + sort_count(A, B, q + 1, j) + merge_count(A, B, i, q, j); } // end sort_count() Por outro lado... Aqui o texto mostra uma sequência de vetores (x,y) e depois um vetor com uma única dimensão E não seria i<j e S > S[j] ? O que seria S[j] em relação a S? não é só um elemento do vetor?
  12. arfneto

    C++ como converte para c

    Como eu disse não vejo nada de especial a ser "convertido". Está seguro sobre aquela linha? acho que não faz sentido nem em C nem em C++ A e B são int* declarados em long long int merge_count(int A[], int B[], int p,int q,int r)
  13. arfneto

    C++ como converte para c

    Está certo sobre essa linha ai? A e B são ponteiros para int então talvez não fosse o que quer escrever. Vai perder o acesso ao vetor B e vai repetir isso várias vezes... Em relação a C e C++ não vejo nada especial aí a ser "convertido"
  14. Não entendi o que significa Esse é o código do ESCAPE, 27. Uma referência histórica: esses códigos são baseados em emular, simular um terminal de computador, nos tempos em que os computadores passaram a ter terminais. Em geral no Unix/Linux esses são os códigos referentes a terminais da marca DIGITAL, em geral do modelo VT-100. Mas em alguns casos se pode selecionar VT-52 ou VT-220. O que acontece é que o terminal interpreta esses códigos antes de mostrar seja lá o que for na tela. O terminal Unix... Esse é um VT-100. Veja em https://pt.wikipedia.org/wiki/VT100 mais informação No caso do Windows a ideia sempre foi diferente e se usa uma uma API, chamadas de função. No entanto recentemente isso começou a mudar e o windows passou a operar com essa mesma filosofia em alguns casos. Isso é um pesadelo. Mas se você usa Windows 10 a partir da edição de aniversário eu acho, pode ter grande sucesso com essas funções e ter seu programa de "console" funcionando igualzinho no Windows e no Unix/Linux/Mac. Essa ferramenta da Microsoft por exemplo pode te interessar https://github.com/microsoft/terminal/releases/tag/1904.29002. Tem tudo a ver com o que está escrevendo. O código fonte está incluído e os caras que escrevem são muito muito bons. A ideia é que você pode criar e salvar esquemas de cores como se faz com a interface gráficas impressoras, o display e tal... Veja uma tela abaixo. Isso é de 2019! Tem um blog da Microsoft que vem divulgando a evolucão dessas coisas e tem a ver com o WSL, subsistema do windows para Linux. A bíblia disso está aqui Guia de instalação do subsistema do Windows para Linux para Windows 10 Por outro lado, essa é a referência para Windows sobre o desenvolvimento dessas coisas https://docs.microsoft.com/pt-br/windows/console/console-reference. Infelizmente ainda não está disponível em português
  15. Olá! Está certo sobre essa linha? Não pretendia iniciar essa variável com algo?
  16. Olá Em stdlib.h você pode usar int setenv(const char* variavel, const char* valor, int naoZeroSeRegrava); E a sintaxe é bem direta... Talvez eu deva lembrar que isso altera o ambiente de seu processo e de processos criados a partir dele. Só isso.
  17. Olá Meu palpite... Se você quer mudar um endereço e tem até uma função com esse nome Então apenas retorne o endereço novo a partir do endereço antigo já que é aparentemente o que quer fazer: a partir de algum critério devolver um endereço novo. Não declare tal função como void e sim algo como char * mudou_de(char* casa_antiga ); Note que em C++ em geral se pode usar a classe string ao invés de char* Sobre esse trecho void MudouPara(char *novaCasa); void MudouPara(char *novaCasa){ char *novoEndereco = "Rua Piaui, 718"; novaCasa = novoEndereco; } Não há razão em declarar o protótipo se vai logo em seguida declarar a própria função. Talvez ache mais produtivo declarar sempre os protótipos todos e iniciar o código por main(). Conforme os programas crescem isso pode ficar mais importante. Entenda que essa variável novoEndereco só existe entre esse bloco delimitado pelas chaves {}. E como sua função também não retorna nada esses valores vão sumir para sempre. Mesmo que você consiga o endereço seu programa vai cancelar assim que tentar acessar isso fora do trecho em que tal endereço é válido. Declarar o argumento como char** ou algo assim acrobático pode não fazer muita diferença: o problema aqui é que você tem que alocar memória para isso, além de devolver o endereço para quem chamou a função. Estou com tempo agora e vou mostrar 3 exemplos, espero que ajude a entender as diferenças. Se quiser fazer algo diferente desses escreva de novo... Em um conservador programa C Você poderia declarar uma função assim char* mudou_de(char* casaAntiga) { char* umEndereco = "Rua Piaui, 718"; if (casaAntiga == NULL) return NULL; if (strcmp(casaAntiga, "Rua da Mantiqueira") == 0) { char * novoEndereco = (char *) malloc( strlen(umEndereco) + 1 ); strcpy(novoEndereco, umEndereco); return novoEndereco; } // end if return casaAntiga; // entao nao vai mudar } // end mudou_de() e chamar assim int main( int argc, char** argv) { char* um_endereco = "Rua do Forum"; char* enderecoAnitta = "Rua da Mantiqueira"; printf("mudou_de(%s) retornou [%s]\n", um_endereco, mudou_de(um_endereco)); printf("mudou_de(%s) retornou [%s]\n", enderecoAnitta, mudou_de(enderecoAnitta)); return 0; } e ver isso na tela mudou_de(Rua do Forum) retornou [Rua do Forum] mudou_de(Rua da Mantiqueira) retornou [Rua Piaui, 718] Funciona porque quando você chama mudou_de("algum endereco") e a função determina que vai mudar mesmo ela aloca memória para hospedar o novo endereço e devolve o endereço a quem chamou. E se não for para mudar ela devolve o endereço original e a vida continua Em C++ usando char* Você poderia declarar uma função assim char* mudou_de(char* casaAntiga) { char umEndereco[] = "Rua Piaui, 718"; if (casaAntiga == NULL) return NULL; if (strcmp(casaAntiga, "Rua da Mantiqueira") == 0) { char* novoEndereco = new char(sizeof(umEndereco)); strcpy(novoEndereco, umEndereco); return novoEndereco; } // end if return casaAntiga; // entao nao vai mudar } // end mudou_de() Claro que é quase igual. Mas aqui você usa o operador new e sizeof(). Poderia chamar assim int main(int argc, char** argv) { char um_endereco[] = "Rua do Forum"; char enderecoAnitta[] = "Rua da Mantiqueira"; char* e = mudou_de(um_endereco); cout << "Usando ponteiro: mudou_de(" << um_endereco << ") retornou '" << e << "'" << endl; cout << "Usando variavel: mudou_de(" << um_endereco << ") retornou '" << mudou_de(um_endereco) << "'" << endl; cout << endl; e = mudou_de(enderecoAnitta); cout << "Usando ponteiro: mudou_de(" << enderecoAnitta << ") retornou '" << e << "'" << endl; cout << "Usando variavel: mudou_de(" << enderecoAnitta << ") retornou '" << mudou_de(enderecoAnitta) << "'" << endl; return 0; } e ver isso na tela Usando ponteiro: mudou_de(Rua do Forum) retornou 'Rua do Forum' Usando variavel: mudou_de(Rua do Forum) retornou 'Rua do Forum' Usando ponteiro: mudou_de(Rua da Mantiqueira) retornou 'Rua Piaui, 718' Usando variavel: mudou_de(Rua da Mantiqueira) retornou 'Rua Piaui, 718' E funciona porque aloca a memória necessária -- quando for o caso --- usando new e devolve o endereço Em C++ usando a classe string Você poderia declarar uma função assim string mudou_de(string casaAntiga) { string umEndereco = "Rua Piaui, 718"; if (casaAntiga.compare("Rua da Mantiqueira") == 0) { return umEndereco; } // end if return casaAntiga; // entao nao vai mudar } // end mudou_de() E poderia chamar assim int main(int argc, char** argv) { string um_endereco = "Rua do Forum"; string enderecoAnitta = "Rua da Mantiqueira"; cout << "mudou_de(" << um_endereco << ") retornou '" << mudou_de(um_endereco) << "'" << endl; cout << endl; cout << "mudou_de(" << enderecoAnitta << ") retornou '" << mudou_de(enderecoAnitta) << "'" << endl; return 0; } e ver isso na tela mudou_de(Rua do Forum) retornou 'Rua do Forum' mudou_de(Rua da Mantiqueira) retornou 'Rua Piaui, 718' Funciona porque a classe string cuida da alocação de memória Espero ter ajudado
  18. Olá! Vou postar uma maneira mais formal de preencher um vetor com uma letra até o tamanho total declarado porque muitas vezes gera dúvida e então pode ser útil... imagine que você tenha uma função declarada assim int completar_com(char c, char* v, int t); E os vetores de teste char vetor[10]; char* nome = "abcde"; Um retorno útil dessa função seria o número de caracteres inseridos, ou (-1) em caso de erro Então se rodar strcpy(vetor,nome); completar_com('-', vetor, 10); Ela deve retornar 4 e o vetor ficar com "abcde----" E aí se chamar de novo com a string completa deve retornar 0, já que não cabe mais nenhum. E se rodar vetor[0]=0; completar_com('*', vetor, 10); deve retornar 9 e o vetor ficar com "*********" nove asteriscos, claro. Uma possível função dessas: int completar_com(char c, char* v, int t) { // completa o vetor v de tamanho t com o caracter c // retorna -1 se deu erro // retorna o numero de caracteres inseridos int i; if (t < 1) return -1; // parametro errado if (v == NULL) return -1; for (i = 0; i < t; i++) { if (v[i] == 0) break; } // end for // aqui ou i aponta para o zero ou chegou ao fim e nao achou if (i ==(t-1)) return 0; // ou nao achou nenhum ou estava cheio for (int j = i; j < t - 1; j++) v[j] = c; // completa v[t-1] = 0; // claro, tem que ter um zero no final return (t-i-1); // desconta o zero no final } // end completar_com() Um teste com legenda mostrando o que acontece no vetor: (1) vetor com "abcde" 0 1 2 3 4 5 6 7 8 9 Posicao 097 098 099 100 101 000 -52 -52 -52 -52 a b c d e NUL ??? ??? ??? ??? "completar_com('-', vetor, 10)" retornou 4 no retorno da rotina 0 1 2 3 4 5 6 7 8 9 Posicao 097 098 099 100 101 045 045 045 045 000 a b c d e - - - - NUL (2) depois de colocar um '0' no inicio, vetor vazio 0 1 2 3 4 5 6 7 8 9 Posicao 000 098 099 100 101 045 045 045 045 000 NUL b c d e - - - - NUL "completar_com('*', vetor, 10)" retornou 9 no retorno da rotina 0 1 2 3 4 5 6 7 8 9 Posicao 042 042 042 042 042 042 042 042 042 000 * * * * * * * * * NUL (3) ja com o vetor preenchido com asteriscos ate o fim 0 1 2 3 4 5 6 7 8 9 Posicao 042 042 042 042 042 042 042 042 042 000 * * * * * * * * * NUL "completar_com('+', vetor, 10)" retornou 0 no retorno da rotina 0 1 2 3 4 5 6 7 8 9 Posicao 042 042 042 042 042 042 042 042 042 000 * * * * * * * * * NUL Eis o programa de teste --- a função bem besta void mostra_vetor(char* vetor, int t, char * msg); imprime o grid e os valores em decimal e caracter e a mensagem #define _CRT_SECURE_NO_WARNINGS #include "ctype.h" #include <stdio.h> #include <stdlib.h> #include "string.h" void mostra_vetor(char* vetor, int t, char * msg) { int i; printf("\n%s\n", msg); printf(" 0 1 2 3 4 5 6 7 8 9 Posicao\n"); for (i = 0; i < t; i++) { printf("%03d ", (int)(vetor[i])); } // end for printf("\n"); for (i = 0; i < t; i++) { if (((int)(vetor[i])>0) && ((int)(vetor[i]) < 255)) { printf("%3c ", (int)(vetor[i])); } else { if (vetor[i] == 0) { printf("NUL "); } else { printf("??? "); } // endif } // end if } // end for printf("\n"); return; } // end mostra_vetor() int completar_com(char c, char* v, int t) { // completa o vetor v de tamanho t com o caracter c // retorna -1 se deu erro // retorna o numero de caracteres inseridos int i; if (t < 1) return -1; // parametro errado if (v == NULL) return -1; for (i = 0; i < t; i++) { if (v[i] == 0) break; } // end for // aqui ou i aponta para o zero ou chegou ao fim e nao achou if (i ==(t-1)) return 0; // ou nao achou nenhum ou estava cheio for (int j = i; j < t - 1; j++) v[j] = c; // completa v[t-1] = 0; // claro, tem que ter um zero no final return (t-i-1); // desconta o zero no final } // end completar_com() int main(int argc, char** argv) { char vetor[10]; char* nome = "abcde"; int i; strcpy(vetor, nome); // completa a partir de "abcde" mostra_vetor(vetor, 10, "(1) vetor com \"abcde\""); i = completar_com('-', vetor, 10); printf("\n\"completar_com('-', vetor, 10)\" retornou %d\n", i); mostra_vetor(vetor, 10, "no retorno da rotina"); vetor[0] = 0; // completa a partir do vetor vazio mostra_vetor(vetor, 10, "(2) depois de colocar um '0' no inicio, vetor vazio"); i = completar_com('*', vetor, 10); printf("\n\"completar_com('*', vetor, 10)\" retornou %d\n", i); mostra_vetor(vetor, 10, "no retorno da rotina"); // agora testa com a string completa mostra_vetor(vetor, 10, "(3) ja com o vetor preenchido com asteriscos ate o fim"); i = completar_com('+', vetor, 10); printf("\n\"completar_com('+', vetor, 10)\" retornou %d\n", i); mostra_vetor(vetor, 10, "no retorno da rotina"); return 0; }
  19. Olá! Em C vetores --- strings --- são declaradas como char* ou char[] e são apenas uma sequência de bytes terminadas por um byte com valor 0, que você pode escreer 0, \0, NULL, mas é só isso: um byte com valor zero. Quando você usa scanf() no seu programa a rotina lê uma sequência de caracteres da entrada e coloca a partir do endereço apontado pela variável, como char nome[31] no seu caso. E acrescenta o terminador 0 no final. Então o seu vetor nome pode ter até 30 caracteres. Pra você "completar" com '- ' precisa saber quanto já foi usado da área que declarou, e o tamanho da área que declarou --- 31 bytes --- e "completar" colocando os '-' e depois o 0 no final Eis a saída de um programa de exemplo Conteudo original do vetor no formato int 0 1 2 3 4 5 6 7 8 9 Posicao -52 -52 -52 -52 -52 -52 -52 -52 -52 -52 Depois de ler [abcde] 0 1 2 3 4 5 6 7 8 9 Posicao 097 098 099 100 101 000 -52 -52 -52 -52 vetor em formato string:[abcde] com 5 bytes Preenchendo com '-' ate o final... vetor em formato string:[abcde-----------------------------------] com 40 bytes E o programa int main(int argc, char** argv) { //int v; char vetor[41]; char* pVetor = vetor; char* nome = "abcde"; printf("\nConteudo original do vetor no formato int\n"); printf("\n 0 1 2 3 4 5 6 7 8 9 Posicao\n"); for (int i = 0; i < 10; i++) { printf("%03d ", (int)(vetor[i])); } // end for printf("\n"); printf("\nDepois de ler [%s]\n", nome); strcpy(vetor, nome); printf("\n 0 1 2 3 4 5 6 7 8 9 Posicao\n"); for (int i = 0; i < 10; i++) { printf("%03d ", (int)(vetor[i])); } // end for printf("\n"); printf("\nvetor em formato string:[%s] com %d bytes\n", vetor, strlen(vetor)); printf("\nPreenchendo com '-' ate o final...\n"); for (int i = strlen(vetor); i < 41; i++) { vetor[i] = '-'; } // end for vetor[40] = 0; printf("\nvetor em formato string:[%s] com %d bytes\n", vetor, strlen(vetor)); return 0; } Deve ajudar a entender. Veja lá a posição do 0 depois de ler "abcde" Sobre os códigos veja a tabela ASCII em http://www.asciitable.com por exemplo. 'a' = 97 por exemplo
  20. Olá! Você quer criar arquivos distintos com os vetores de 500 números, um número por linha, um conjunto de números por arquivo? talvez pudesse explicar um pouco mais... E sobre os números serão inteiros entre maior e menor? inclusive os extremos? O mais comum pra gerar é usar um prefixo e numerar os vetores, tipo de vetor001.txt até vetor500.txt
  21. Olá! Na sua rotina() você declarou S[] como char. Então S é um ponteiro para char. E assim S[0] que também pode ser escrito como S é um char. Em main() você declara char str[4] e chama rotina(str) passando str como parâmetro para sua rotina(). Então em rotina() você pode usar acessar S[0] ou S, S[1] e S[2] e S[3]. Por outro lado "SIM" é uma string, char*. Mesmo caso de "SAIR" e de "NAO". Então você não pode escrever if(S=="SIM") ou if(S=="NAO") porque do lado esquerdo tem um char e do lado direito tem um ponteiro para char. Você pode escrever if(S == 'S') porque S é char e 'S' é char ou if(strcmp(S,"SIM) == 0) porque essa rotina aceita dois parâmetros do tipo char*, ponteiros para char. E "SIM" é do tipo char*, uma string. E S é do tipo char* declarado como S[]. strcmp() retorna 0 se as duas strings são iguais, algum valor < 0 se a primeira for menor e algum valor >0 se a segunda string for maior que a primeira Seu enunciado diz claramente para aceitar "SIM" ou "NAO" então eu não recomendo ir além do que está escrito e se preocupar com maiúsculas e minúsculas... Mas não sou seu professor Assim sendo você tem duas opções: pode usar o que alguns chamam de árvore de decisão e ir vendo se o cara digitou S depois I ou A e tal... Testando uma letra por vez. Ou usar strcmp() e testar as strings. Seu enunciado diz claramente que não é pra retornar exceto com "SIM" ou "NAO" e que não pode voltar a ler quando ler um "SAIR", de modo que deve ser o caso de encerrar o programa sem retornar chamando exit(). Assim essas duas serviriam int rotina() { const char* SIM = "SIM"; const char* NAO = "NAO"; const char* SAIR = "SAIR"; char entrada[40]; do { printf("rotina(): Entre string: "); scanf("%s", entrada); if (strcmp(entrada, "SIM") == 0) return 1; if (strcmp(entrada, NAO) == 0) return 0; if (strcmp(entrada, SAIR) != 0) continue; printf("Leu \"SAIR\". Encerrando\n"); exit(0); } while (1); } // end rotina() usando strcmp() ou int rotina_b() { char entrada[40]; do { printf("rotina(): Entre string: "); scanf("%s", entrada); if (entrada[0] == 'S') { if ( (entrada[1] == 'A') && (entrada[2] == 'I') && (entrada[3] == 'R') ) { printf("Leu \"SAIR\". Encerrando\n"); exit(0); } else { if ((entrada[1] == 'I') && (entrada[2] == 'M') ) { return 1; } else { continue; } } // end if } else { // nem SIM nem SAIR: pode SER NAO if ((entrada[0] == 'N') && (entrada[1] == 'A') && (entrada[2] == 'O') ) return 0; else continue; } // end if 'S' } while (1); } // end rotina_b() Usando os char apenas Essa simples função main() int main(int argc, char** argv) { int v; while (1) { v = rotina_b(); printf("main(): rotina() retornou %d\n", v); } // end while() return 0; } // end main() mostraria isso rotina(): Entre string: 12 rotina(): Entre string: 12 rotina(): Entre string: 12 rotina(): Entre string: SIM main(): rotina() retornou 1 rotina(): Entre string: NAO main(): rotina() retornou 0 rotina(): Entre string: SAIR Leu "SAIR". Encerrando Como esperado. Note que em C 1 é sempre verdade então while(1) é comum de se escrever quando se sabe que um loop vai terminar por alguma maneira dentro dele, como por uma chamada a exit().
  22. Olá Imagino que esteja falando da console e não da interface gráfica Dia atrás postei um programa que precisava disso. Era uma animação de um jogo de bingo e está aqui. A parte relevante é essa eu acho nome = "Clube do Bingo"; total_cartelas = t; // agora cria as cartelas todas pCartelas = new (Cartela[total_cartelas]); string prefixo = "Cartela "; string nome = ""; // agora a cor: precisamos saber a cor que esta em uso // para definir nas cartelas a cor certa HANDLE H = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(H, &info); // define as cores cor_nao_sorteados_ainda = (WORD)info.wAttributes; cor_sorteados = FOREGROUND_GREEN; total_cartelas_completas = 0; Em resumo você chama GetConsoleScreenBufferInfo() e recebe a estrutura preenchida... No caso de janelas comuns acho que basta chamar GetSystemMetrics() como descrito na documentação aquic com os parâmetros corretos. No caso de Linux vai depender do que estiver usando para a interface gráfica... No caso da console no linux recomendo muito dar uma olhada em ncurses, sucessora de curses que vem desde o Unix nos '90 ou antes e é muito ampla... Note que as funções de console operam a partir de handles, as SystemMetrics em pixels, e curses em muitos e muitos ponteiros para estruturas também. No fundo tudo bem parecido.
  23. Olá Esqueci de postar o programa. Se interessar para alguém tem um link para download no botão verde
  24. Olá! Este é um jeito clássico de escrever a função int retorna_um_se_primo(unsigned int n) { if (n < 2) return 0; if (n == 2) return(1); if (n % 2 == 0) return(0); unsigned int maior = (unsigned int) sqrt( (double) n); unsigned int fator = 3; while (fator <= maior) { if (n % fator == 0) return 0; fator += 2; } // end while return 1; } // end retorna_zero_se_primo() Muitos dos exemplos online tem preguiça de calcular o maior fator, outros testam o loop para todos os pares inutilmente já que de início se sabe que 2 é o único primo par. Outros testam com o fator 2 talvez sem necessidade Essa função aí então, como dá pra imaginar pelo nome, retorna um se o número é primo Convém usar unsigned int porque dá pra usar até números maiores, até... UINT_MAX o maior valor que dá pra usar em uma variável dessas. Esse trecho i = retorna_um_se_primo(UINT_MAX); printf("\n\n retorna_um_se_primo(UINT_MAX=%u) retornou %u\n", UINT_MAX, i); mostraria retorna_um_se_primo(UINT_MAX=4294967295) retornou 0 São dez dígitos. Essas constantes tipo UINT_MAX estão em geral em limits.h e convém incluir isso no programa por segurança #include "limits.h" adicionado 51 minutos depois Não vi problema em postar um exemplo porque tem milhões desses online Mas fiquei pensando: como conferir um trem desses? Como em geral a gente aprende sobre números primos antes de aprender sobre programação e isso está no ensino fundamental, pensei no Crivo de Eratóstenes que a gente vê no ensino fundamental: Você pega uma folha de papel e escreve uma lista de números e separa o dois como primo. Aí marca os múltiplos de 2. Pega o próximo não marcado: 3. E marca os múltiplos, e continua até ficarem só os primos na tabela. Foi criado há mais de 2 mil anos. Eis um desses para 100 Sobre o crivo de Eratóstenes na WikiPedia Aí pensei que seria legal poder conferir a função retorna_um_se_primo(unsigned int); usando um crivo. Claro que marcar uns 10 números tudo bem, mas uns 900 já não dá né? Uma ocasião para escrever um crivo virtual grande. Em C, porque não. E aí pegar os primos e conferir na tabela gigante. E para não ficar na dúvida conferir a tabela gigante vendo se os números são mesmo primos chamando nossa função.... Pensei numa função assim: unsigned int proximo_primo(unsigned int); que eu pudesse chamar e que a cada vez ela me retornasse o próximo primo. Para iniciar eu chamaria com o próprio número como argumento e a partir daí eu chamaria com argumento 0 e ela devolveria o próximo. Bem conveniente. Se ela existisse, eu poderia escrever essa outra: unsigned int mostra_os_primos(unsigned int); que faria exatamente o que o problema pedia: mostrar os primos de 2 até n inclusive. Podia ser assim escrita: unsigned int mostra_os_primos(unsigned int n) { unsigned int l = limita_memoria(n); if (l < n) { // nao deu: o valor foi limitado printf( "Limite de memoria %dKB: o maior primo foi limitado de %u para %u", LIMITE_A_ALOCAR_KB, n, l ); } unsigned int r = proximo_primo(l); if (r < 0) { printf("Erro ao iniciar sequencia: %d\n", r); return(r); } printf("\n\nPrimos ate %u (inclusive)\n\n", n); unsigned int i = 0; while ((r = proximo_primo(0)) != 0) { printf("%10u ", r); i += 1; if (i % 10 == 0) printf("\n"); } while (r > 0); return i; } // end mostra_os_primos() Ficou até grande porque eu inseri uns testes. Mas é só isso: inicia a sequência chamando por exemplo mostra_os_primos(900); e aí a cada vez que chamar com mostra_os_primos(0) volta o próximo primo ou zero se acabaram. Se estiver tudo certo, esse trecho de programa i = mostra_os_primos(lim); printf("\n\nEncontrados %u primos\n", i); mostraria Primos ate 900 (inclusive) 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 Encontrados 154 primos Como esperado. O argumento %u para printf() indica um valor inteiro sem sinal. São 10 valores por linha e tem tantos espaços entre os dígitos porque está preparado para listar primos de até 10 dígitos. Não muito útil aqui, admito. Como conferir isso? Agora ficou fácil: temos duas fontes de primos: usamos o crivo e pegamos um por vez ou pegamos os números e chamamos a função: então podemos jogar um contra o outro e não pode haver diferença, já que falamos de matemática inteira. Confere os primos contra o crivo int compara_primos_com_crivo(unsigned int n) { proximo_primo(n); // prepara crivo for (unsigned int i = 2; i <= n; i++) { int r = retorna_um_se_primo(i); if (r == 1) { // primo. então deve ser o proximo d lista int s = proximo_primo(0); if (i != s) return 0; } // end if } // end for return 1; // tudo ok: valores indenticos } // end compara_primos_com_crivo() Essa testa os números do crivo usando a função. compara_primos_com_crivo(900) por exemplo monta a tabela e depois no loop compara cada primo encontrado com o próximo do crivo. Claro, deve ser o mesmo número. Compara todos e retorna zero se deu m#$% ou 1 em caso de esperado sucesso. Testa os números no crivo usando a função retorna_um_se_primo(): int testa_crivo_contra_funcao(unsigned int n) { unsigned int r = proximo_primo(n); // prepara crivo if (r != 0) return 1; // deu erro unsigned int i = 0; while ((r = proximo_primo(0)) != 0) { i = retorna_um_se_primo(r); if (i != 1) { return 0; // deu pau: no crivo diz que e primo mas a funcao nao } // end if } // end while return 1; } // end testa_crivo_contra_funcao() O simples: pega cada primo que veio do crivo ao chamar proximo_primo(0) e testa com a função. Tem que ser todos bem iguais certo? Então se eu rodar isso para lim=900 i = mostra_os_primos(lim); printf("\n\nEncontrados %u primos\n", i); // agora testa a funcao e compara com os valores obtidos do crivo de eratostenes i = compara_primos_com_crivo(lim); if (i == 1) printf("Testando primos contra os marcados no crivo: sem surpresas. Todos os valores coincidem\n"); else printf("Testando primos contra os marcados no crivo: Algo errado!\n"); // agora testa o crivo e com a funcao verifica se todos sao primos i = testa_crivo_contra_funcao(lim); if (i == 1) printf("Testando os valores do crivo com a funcao: sem surpresas. todos os valores confirmados\n"); else printf("Testando os valores do crivo com a funcao: Algo errado\n"); i = retorna_um_se_primo(UINT_MAX); printf("\n\n retorna_um_se_primo(UINT_MAX=%u) retornou %u\n", UINT_MAX, i); return 0; devo ver Primos ate 900 (inclusive) 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 Encontrados 154 primos Testando primos contra os marcados no crivo: sem surpresas. Todos os valores coincidem Testando os valores do crivo com a funcao: sem surpresas. todos os valores confirmados E as duas linhas no final garantem que está tudo ok. E a tal função que cria o Crivo de Eratóstenes? São duas coisas distintas: quando chama com o valor cria a tal estrutura, quando chama com zero vai devolvendo os caras, como faz rand(). Essa abaixo funciona unsigned int proximo_primo(unsigned int n) { static unsigned int* valores; static unsigned int proximo, limite, indice, tamanho; unsigned int j, k; ////////////////////////////////// prepara tudo e retorna unsigned int i = 0; static int eraDois; if (n == 1) return (-1); if (n > 0) { // chamada inicial: prepara tudo if (n == 2) { eraDois = 1; return 0; } else { eraDois = 0; if (valores != NULL) free(valores); // se chamou de novo apaga tudo tamanho = ((n - 1) / 2); // so os impares i = tamanho * sizeof(unsigned int); valores = malloc(i); // aloca o necessario if (valores == NULL) return -1; for (j = 0; j < tamanho; j++) valores[j] = 3 + j + j; limite = n; proximo = 2; indice = 0; } return 0; } // end if ////////////////////////////////// devolve o proximo primo if (eraDois == 1) { proximo = 0; eraDois = 0; return (2); } if (proximo == 0) return( 0); if (valores == NULL) return(-2); if (proximo == 2) { proximo = 3; return 2; // unico primo par } k = proximo; // a partir de 3 for (j = indice + k; j < tamanho; j += k)valores[j] = 0; // marca os multiplos for (j = indice + 1; j<tamanho; j++) { if (valores[j] <= 0) continue; proximo = valores[j]; indice = j; return k; } // end for proximo = 0; return k; } // end proximo_primo() Nada mágico. Note que não tem multiplicações ou módulo % ou funções exóticas. Apenas soma e tabula, exatamente como Eratóstenes fez entre 285 e 194 a.c. Mas usa memória e tem uma constante mágica que limita o tamanho do crivo virtual em K bytes #define LIMITE_A_ALOCAR_KB (32768) Mas dá pra ir bem longe. Até uns 10 dígitos. E depois é só um passatempo. O código de main() abaixo aceita o limite como argumento na linha de comando e assume 900 que é o valor pedido. Assim a gente pode testar com facilidade sem ter que compilar o programa de novo. E já usa a função para testar o crivo e vice e versa. Se você usar crivo ou crivo 900 vai gerar o que está acima int main(int argc, char** argv) { unsigned int n; if (argc > 1) n = strtoul(argv[1], 0, 0); else n = 900; unsigned int i = 0; unsigned int lim = limita_memoria(n); printf("\n\nTestando com n=%u\n", lim); if (lim < n) { printf("Valor original %u truncado por falta de memoria para o crivo\n", n); printf("Memoria reservada = %uKB\n", LIMITE_A_ALOCAR_KB ); } // end if i = mostra_os_primos(lim); printf("\n\nEncontrados %u primos\n", i); // agora testa a funcao e compara com os valores obtidos do crivo de eratostenes i = compara_primos_com_crivo(lim); if (i == 1) printf("Testando primos contra os marcados no crivo: sem surpresas. Todos os valores coincidem\n"); else printf("Testando primos contra os marcados no crivo: Algo errado!\n"); // agora testa o crivo e com a funcao verifica se todos sao primos i = testa_crivo_contra_funcao(lim); if (i == 1) printf("Testando os valores do crivo com a funcao: sem surpresas. todos os valores confirmados\n"); else printf("Testando os valores do crivo com a funcao: Algo errado\n"); i = retorna_um_se_primo(UINT_MAX); printf("\n\n retorna_um_se_primo(UINT_MAX=%u) retornou %u\n", UINT_MAX, i); return 0; } // end main() E se fosse um milhão? eis o final para crivo 1000000 Ainda bem que uma função conferiu a outra !!! Eis o final para 1 milhão, já conferidos 998857 998861 998897 998909 998917 998927 998941 998947 998951 998957 998969 998983 998989 999007 999023 999029 999043 999049 999067 999083 999091 999101 999133 999149 999169 999181 999199 999217 999221 999233 999239 999269 999287 999307 999329 999331 999359 999371 999377 999389 999431 999433 999437 999451 999491 999499 999521 999529 999541 999553 999563 999599 999611 999613 999623 999631 999653 999667 999671 999683 999721 999727 999749 999763 999769 999773 999809 999853 999863 999883 999907 999917 999931 999953 999959 999961 999979 999983 Encontrados 78498 primos Testando primos contra os marcados no crivo: sem surpresas. Todos os valores coincidem Testando os valores do crivo com a funcao: sem surpresas. todos os valores confirmados Para quem queria saber o maior primo menor que 1 milhão: 999983.
  25. Olá! Mas não era pra usar while() e if() ?

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!