-
Posts
6.526 -
Cadastrado em
-
Última visita
Tipo de conteúdo
Artigos
Selos
Livros
Cursos
Análises
Fórum
Tudo que arfneto postou
-
Pessoas tem níveis distintos de atenção e compreensão. Deve ser impossível atingir 100% do público. Mas eu acho que consegui trazer mais um para o grupo dos que entenderam o que o autor do tópico precisa fazer: trata-se de extrair matrizes a partir da original. Uma projeção.
-
Não é o caso O autor do tópico ofereceu dois exemplos desse "fracionamento" ou "divisão". Talvez estivesse melhor expressado como extração ou projeção, mas com os exemplos eu acho que ficou claro o que ele precisa fazer.
-
Mas você postou um programa em C Não é bem assim Os jogos precedem em muito a noção de programação orientada a objetos. A primeira versão de Unix na Bell Labs nos '60 foi escrita por Ken Thompson para faciliar escrever jogos num PDP-11... E para facilitar isso foi criada a linguagem e o primeiro compilador C Tem razão. Mas isso não é OOP. Para implementar o jogo como objeto você cria uma Classe Jogo e coloca dentro dela os tabuleiros, a noção de fase e os movimentos do jogo. E cria os métodos associados a cada instância da classe. No construtor da classe cria o tabuleiro e preparar o jogo. É mais difícil, mas implica diretamente em repetir várias vezes o mesmo código. Veja fases com loop e sem repetição em C int passou = 0; fase1: // 1 // logica da fase 1 // ... passou = 1; goto fase2; // ... // logica da fase 1 if (!passou) goto fase1; fase2 : passou = 0; // 2 // logica da fase 2 // ... passou = 1; goto fase3; // ... // logica da fase 2 // ... if (!passou) goto fase2; fase3:
-
Apenas use os índices e copie os valores
-
Não é para testar se o valor inicial é maior que o final: Está garantido no enunciado Sim, x%5 == 0 indica que é múltiplo de 5 x%2 == 1 indica que é ímpar, mas talvez não seja preciso usar isso Sim, mas pode não ser preciso fazer isso dentro do loop porque iria fazer muitos cálculos desnecessários. Basta saber o primeiro ímpar múltiplo de 5 A solução comum, sem pensar nos dados // sem pensar nos dados int soma = 0; for (int n = inicial; n <= final; n += 1) if ((n%5 == 0) && ((n%2 == 1) || (n%2 == -1))) { printf("%d\n", n); soma += n; }; printf("\nSoma dos multiplos = %d\n", soma); Pois é: identificados os valores inicial e final entra no loop e mostra os caras e vai somando. No final mostra a soma. Mas era pra ser um while() então // sem pensar nos dados int soma = 0; n = inicial; while (n <= final) { if ((n % 5 == 0) && ((n % 2 == 1) || (n % 2 == -1))) { printf("%d\n", n); soma += n; }; n += 1; } printf("\nSoma dos multiplos = %d\n", soma); Pensando um pouco nos dados É claro de de todos os números apenas um em 10 é ímpar e múltiplo de 5, então esse loop é meio best@. Vai calcular toda hora a mesma coisa de que não precisa mais. Do ensino fundamental: a tabuada do 5 0,5,10,15,20,25,30,35,40,45 Da aritmética elementar: os múltiplos de 5 ímpares terminam em 5. Talvez não seja preciso usar duas vezes módulo e fazer aquelas contas sugeridas aqui. Da matemática elementar: vendo a tabuada do cinco, os múltiplos ímpares de 5 tem diferença de 10. De um modo mais chique, eles Mas porque tudo isso? E o programa? Simples: Se a gente souber qual o primeiro ímpar múltiplo de 5 no intervalo então o while() é bem simples: basta ir somando 10 até passar do valor final. E somar. Então o while() que é o objetivo do programa seria apenas // o tal while afinal while (n <= final) { printf("%d\n", n); soma += n; n += 10; }; Falta só achar o primeiro n. Claro, pode não ter nenhum número. Pegadinhas de exemplo entre -4 e 4 não tem nenhum entre -5 e 5 tem dois: o inicial e o final entre 1 e 5 tem só o 5, o final entre 5 e 10 tem só o 5, o inicial Mas como achar o primeiro cara? Usando o mesmo programa Pode criar uma variável prim e dentro do while marcar quando achou o primeiro e a partir daí andar de 10 em 10. Bem mais esperto e vai fazer no máximo 4 testes para achar o primeiro. Nada de calcular módulo isso e aquilo dentro do loop, nada de contar de 1 em 1. Algo assim // pensando um pouco nos dados int soma = 0; n = inicial; int prim = 0; // nao achou ninguem while (n <= final) { if (prim == 0) { // procura o primeiro if ((n % 5 == 0) && ((n % 2 == 1) || (n % 2 == -1))) { // o primeiro printf("%d\n", n); soma += n; prim = 1; n += 10; } else // continua n += 1; } else { // mais um printf("%d\n", n); soma += n; n += 10; } } printf("\nSoma dos multiplos = %d\n", soma); Mas está comprido e complicado. Mais esperto seria calcular antes de entrar no loop o primeiro cara, e desistir do programa inicial que foi escrito pensando em C e não no problema Pensando mais nos dados: algumas outras soluções int soma = 0; // encontra o primeiro n = (vi / 10) * 10 + (vi < 0) * (-10) + 5; if (n < vi) n += 10; // o tal while afinal while (n <= vf) { printf("%d\n", n); soma += n; n += 10; }; printf("\nSoma dos multiplos = %d\n", soma); Bem menor hein? E nem precisou de módulo. Claro, a conta é a mesma. O loop é sempre o mesmo: while (n <= vf) { printf("%d\n", n); soma += n; n += 10; }; printf("\nSoma dos multiplos = %d\n", soma); Outras opções para achar o primeiro múltiplo ímpar de 5 maior ou igual ao valor inicial Em uma linha só talvez? // opcao 3 n = ((vi / 10) * 10 + (vi < 0) * (-10) + 5) + (((vi / 10) * 10 + (vi < 0) * (-10) + 5) < vi) * 10; Mais difícil de ler, mas é a mesma coisa Um pouco mais legível, com dois if() // opcao 1 if (vi <= 0) n = (vi / 10) * 10 - 5; else n = (vi / 10) * 10 + 5; if (n < vi) n += 10; Um pouco mais legível: // encontra o primeiro n = (vi / 10) * 10 + 5; n += (vi < 0) * (-10); n += (n < vi) * 10; // o primeiro n Um programa assim Estou postando isso como parte da minha campanha pela criação dos programas em torno dos dados e não da linguagem
-
Não mudou nada. Apenas tem mais camadas e a cada camada uma "restrição. Se pude julgar que é mais fácil ou mais difícil, mas dá na mesma. Buffers, memória e registradores. conio não é uma biblioteca gráfica. Eu até fazia isso nos 90 para a NCR.
-
Dev-C++ é um IDE, Sublime text um editor de texto. Nenhum deles tem efeito sobre acentos. Provavelmente você nunca tinha rodado seus programas do jeito que era pra ser normal: como um programa e não como um arquivo dentro do IDE. A vida de um programa era pra começar quando ele fica pronto. Mas para muita gente, estudantes e pessoal que programa por hobby ou curiosidade, acontece o contrário: a vida do programa termina quando ele fica pronto e depois ele nunca mais é executado O programa pronto era pra ser entregue, vendido, distribuído. E claro testado em outros ambientes que não o computador em que foi escrito, dentro da janelinha do IDE em que ele foi escrito. Dentro do IDE o código em geral é bem diferente do que sai para uso "oficial", o tal Release Build. E é possível que seu programa que roda certinho no IDE não rode mais em Release mode até. Para que os acentos sejam exibidos numa aplicação de console você deve confirmar a página de saída, e a fonte da console além da configuração de locale. Essa rotina abaixo lê esses valores. Pode te servir como exemplo. _cs_status* guarda(_cs_status* antes) { antes->cp_original = GetConsoleCP(); antes->ocp_original = GetConsoleOutputCP(); strcpy(antes->local_original, setlocale(LC_ALL, NULL)); HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); char buffer[80]; char* pBuffer = buffer; int res = 0; res = GetCurrentConsoleFont(h, 0, &(antes->font_info)); // pois e: mas qual a fonte? Tem que ver na tabela // precisa da versao ex da rotina e eu nao sabia antes->font_infoEx.cbSize = sizeof(CONSOLE_FONT_INFOEX); res = GetCurrentConsoleFontEx(h, 0, &(antes->font_infoEx)); // A fonte em uso fica aqui no registro // Computador\HKEY_LOCAL_MACHINE\SOFTWARE\ // Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont // GetConsoleMode(h, &antes->mode_original); // agora falta SCREEN BUFFER antes->infoEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); GetConsoleScreenBufferInfoEx(h, &antes->infoEx); return antes; }; // guarda() No terminal pode rodar CHCP e ver a página que está em uso no momento, e depois ver na WikiPedia por exemplo se tem as letras que você quer... 1252 é uma escolha comum no Brasil. A página 65001 que usa Unicode está se tornando a opção comum. E a fonte? Se ela não tiver as letras de nada adianta... Nas propriedades da janela você vê a fonte que está em uso. Aí pode usar o mapa de caracteres do Windows e ver se tem as letras que quer mostrar... Use Windows 10. E o terminal do windows para rodar seus programas. Veja que essa fonte tem até os caracteres em braille, o que faz pouco sentido sem uma certa reflexão, já que eles são lidos por relevo... Mas os programas que leem texto podem imprimir texto, por exemplo. Veja quantos símbolos tem só nesse pedaço... Mostrar isso na tela é outro pesadelo e gravar em arquivo outro maior. O caminho mais simples é esquecer isso e usar o navegador. O mais seguro é usar o Terminal do Windows para rodar seus programas. É muito mais rápido --- usa aceleração gráfica por hardware, como os games --- e tem todos símbolos, usando Unicode --- hoje mais de 1.1 milhão de símbolos. Usar um Editor e rodar seus programas assim vai te mostrar muitas coisas que ficavam ocultas nos IDE.
-
Acompanhou a discussão toda? São vários pre-requisitos para voltar no tempo. Não basta um programa e uma biblioteca. Mesmo em 2020 um programa de console rodando no Terminal do Windows pode mostrar uma coisa e na tela do CMD outra e na tela do IDE outra. Você precisa controlar a fonte, a CodePage e a CodePage de saída que o DOSBOX usa... adicionado 9 minutos depois Voltando no tempo, acho que a primeira vez que escrevi isso foi em época anterior ao Turbo C, para escrever caixas de menu para mostrar na tela do terminal no tempo em que os terminais eram,digamos, terminais. E tinham teclado. E alguns, não todos, tinham tela. E gerava um trecho de código depois para incorporar no programa. Isso pra não ter que ficar editando o programa toda hora pra aumentar uma linha ou coluna. E podia gerar o código em C, Pascal ou Assembler para ir "direto" para a memória do vídeo, de uns poderosos 8 ou 16k --- quase tudo read-only --- de memória ou algo assim que o monitor de vídeo tinha. Assim o monitor podia mostrar aquelas telinhas de set-up com a moldura na tela, como o setup dos PCs anos depois. "direto" com aspas porque era preciso gravar na EPROM, um chip que levava o firmware do vídeo. E depois encaixar na placa lógica do vídeo. Então era bom ter certeza de que tinha testado antes de ir para produção.
-
C estou tentando rodar uma string em um for, mas não vai
arfneto respondeu ao tópico de DanielSantDev em C/C#/C++
main() { char str[15]; int i; printf("Digite um nome: "); scanf("%s", str); for(i=0;i<10;i++); { printf("valor do elemento %d da string = %c\n",i,str[i]); } } Imagino que a partir de todas as sugestões que recebeu já tenha entendido o que houve com seu programa e tenha feito ele funcionar Mas vou deixar uma análise do que você escreveu e umas notas a mais int i; Como está aprendendo é uma boa hora para novos costumes. Sempre inicialize as variáveis. No caso de uma variável que só vai ser usada como índice em um loop, desde 1990 se pode declarar a variável no próprio comando for, escrevendo for(int i=0; i<10;i++); E se tivesse escrito assim não teria errado no seu programa: ao encontrar o ';' terminaria o for e então o printf() printf("valor do elemento %d da string = %c\n",i,str[i]); ia dar erro. A variável 'i' que só deveria existir dentro do loop não estaria declarada. E você teria notado o ';' ou não ia conseguir compilar o programa. Erros de compilação são muito melhores que erros de execução, como você viu aqui. scanf() scanf() é problemática para ler coisas do teclado. Essa função foi escrita para ler entrada formatada --- scan formatted input --- e a entrada pelo teclado não é nada formatada. O usuário tem 105 teclas ou mais de liberdade para digitar qualquer m#$d@. Evite usar. É possível mas só vai te dar dor de cabeça. Entenda também que scanf() retorna um valor e você deveria tratar isso. Muitas vezes ela não lê nada e se você não testar não vai saber. Muitas vezes ela não lê tudo e logo depois você vai saber. E você pode limitar o tamanho de cada campo a ser lido, usando o tamanho como em %14s no seu exemplo. for(i=0;i<10;i++); Em programas não é assim incomum esse comando estar certo. Mas entenda que ';' indica o final do comando em C. De qualquer comando. Uma maneira de diminuir a chance de você digitar isso por engano é escrever o loop sempre já com as chaves e depois digitar dentro... for( ;; ){ }; Se não precisar das chaves depois você apaga. Mas assim não vai esquecer delas ou colocar o ';' no lugar errado... Acho que entendeu. Se ficou curioso por isso poder estar certo, entenda que o comando for tem 3 partes, todas opcionais, separadas por dois ';' esses sim obrigatórios. Muitas vezes a lógica do loop está toda contida aí e não sobra nada para ficar dentro das { } e elas podem ser então omitidas e fica só o ';' Em seu programa pode ler até 14 letras, já que str é char[15] e tem que ter espaço para o zero no fim. Mas usou o limite de 10 fixo no loop. E se o cara digitar apenas 2? Ou 13? Ou teclar ENTER direto? Na verdade você quer rodar o loop para mostrar o que tem na string e isso vai até o zero final, exclusive. Quase todo mundo iria rodar strlen(str) para ver o tamanho da string. E você pode fazer isso e ficar seguro de que o loop estará dentro dos limites do que foi digitado. Como você está começando agora pode ser boa hora de evitar também esse hábito. strlen() é uma função. Um pedaço de código escrito por alguém e que vai ser chamado, como scanf(). e vai retornar um valor, como scanf(). E tem um custo chamar uma função. E não é pequeno, em especial em um programa... pequeno E no seu caso ela vai ser chamada uma vez para cada letra. Pense nisso. Dentro do loop o tamanho da string pode ser alterado afinal. E você não precisa nesse caso saber o tamanho da string: só quer mostrar o que tem dentro e ela termina com um zero. Isso quer dizer que você pode escrever for (int i = 0; str[i] != 0; i++) simplesmente, já que o zero marca o fim da string. i++ Evite essa construção. Pode usar: ++i i++ i+=1 i = i + 1 Não faltam opções. Por razões históricas esse operador pós- é o mais usado. Mas é o menos esperto. O i++ ou i-- indica que a operação vai ser feita depois de o operando ser usado. Pesquise isso. Esse trecho de programa int j = 2; int k = 3; printf("j = %d j++ = %d k = %d e ++k = %d\n", j, j++, k, ++k); printf("k = %d\n", k); Mostra j = 3 j++ = 2 k = 4 e ++k = 4 k = 4 Não escreva essas coisas. É só um exemplo. Mas entenda que toda vez que escreve isso o compilador salva e usa o valor da variável para depois fazer a soma. Use ++x se gosta desses, porque aí a operação é executada direto no operando. printf("valor do elemento %d da string = %c\n",i,str[i]); Você está tentando mostrar algo que pode estar em branco, é uma string afinal. Se acostume a usar nesses casos um delimitador, tipo '%c' e assim saberá que está funcionando mesmo que na posição tenha um espaço ou um TAB por exemplo. Escreva por exemplo printf("valor do elemento %d da string = '%c'\n", i, str[i]); Seu programa um pouco diferente #include <stdio.h> int main(void) { char str[15]; printf("Digite um nome: "); scanf("%14s", str); for (int i = 0; str[i] != 0; i++) printf("valor do elemento %d da string = '%c'\n", i, str[i]); } Mostra Digite um nome: abcdeABCDE1234 valor do elemento 0 da string = 'a' valor do elemento 1 da string = 'b' valor do elemento 2 da string = 'c' valor do elemento 3 da string = 'd' valor do elemento 4 da string = 'e' valor do elemento 5 da string = 'A' valor do elemento 6 da string = 'B' valor do elemento 7 da string = 'C' valor do elemento 8 da string = 'D' valor do elemento 9 da string = 'E' valor do elemento 10 da string = '1' valor do elemento 11 da string = '2' valor do elemento 12 da string = '3' valor do elemento 13 da string = '4' Pressione qualquer tecla para continuar. . . Não evite enquanto não entender De todo modo é bobagem. Use scanf() quando a entrada for formatada, como ler uma tabela ou um arquivo csv. Use fgets() para ler linhas e fgetc() para ler letras sempre que sua lógica permitir. No "mundo profissional" não se lê valores do teclado para mostrar na tela desde os 90. Quanto são poucos argumentos são passados direto na linha de comando, como um MKDIR c:\teste no Windows. Quando são muitos e tem uma tela mesmo, e não tem MESMO jeito de usar uma interface gráfica, o que se faz é separar teclado e tela: você uma tecla por vez mas não mostra se for algo válido aí sim você mostra e avança o cursor se for inválido você apaga e pisca a tela ou toca um bip e continua Usando scanf() sempre tem chance de zoar a tela. fgetc() e fgets() são mais seguras nesse aspecto mas não 100% Não, não vai apagar um enter. O que está entre colchetes é uma lista dos caracteres que serão aceitos por scanf() para montar o campo. [1234] aceita só esses números, por exemplo. Mas se o primeiro caracter for ^ inverte o significado e passa a ser a lista dos caracteres que NÃO são aceitos. [ ^1234] vai ler em str até o primeiro desses dígitos aparecer: se o cara digitar 1234x scanf() vai ler "1234" em str. E vai retornar 1 o que deveria er lido e tratado pelo programa como eu expliquei. E vai deixar o 'x' lá para ser lido depois. Então esse especificador que mostrou lê tudo que vier, até o ENTER, exclusive. Porque a lista tem só o '\n'. Só que se o cara digitar ENTER direto scanf() não vai ler nada. Vai retornar zero só que você não está testando, como ninguém aparentemente testa. E eu programa vai imprimir um monte de bobagens provavelmente. -
C Comparando duas strings com condicional IF
arfneto respondeu ao tópico de DanielSantDev em C/C#/C++
adicionado 14 minutos depois Como o problema já foi resolvido vou postar duas soluções seguindo o que expliquei antes O Simples int main(int argc, char** argv) { char uma[20]; char outra[20]; printf("Primeira string: "); fgets(uma, 20, stdin); int N = strlen(uma); printf("Segunda string: "); fgets(outra, 20, stdin); if (N != strlen(outra)) { printf("As strings sao diferentes\n"); return 0; // se os comirmentos sao diferentes ja era }; // if() for (int i = 0; i < (N-1); i += 1) if (uma[i] != outra[i]) { printf("As strings sao diferentes\n"); return 0; // basta uma letra diferente }; printf("As strings sao iguais\n"); return 1; // comparou todas }; Se os comprimentos diferem não há razão para um loop. Retorna 0 que equivale a falso em C Se os comprimentos são iguais compara as letras, mas apenas até encontrar a primeira diferença Se chegou ao fim do loop é porque as strings são iguais e retorna não-zero, verdadeiro em C E se não for diferenciar maiúsculas de minúsculas? Nesse caso muda a comparação, mas apenas para o caso de ter letras na mesma posição das duas strings. Ela pode ter números por exemplo... É claro que se pode chamar uma função, mas não faz sentido chamar uma função dentro de uma coisa tão simples. Eis uma função dessas int main(int argc, char** argv) { char uma[20]; char outra[20]; printf("Primeira string: "); fgets(uma, 20, stdin); int N = strlen(uma); printf("Segunda string: "); fgets(outra, 20, stdin); if (N != strlen(outra)) { printf("As strings sao diferentes\n"); return 0; }; // if() // se forem duas letras ignora a diferenca entre // maiusculas e minusculas for (int i = 0; i < (N-1); i += 1) { char a = uma[i]; char b = outra[i]; char letras = ((a >= 'a') && (a <= 'z') || (a >= 'A') && (a <= 'Z')) && ((b >= 'a') && (b <= 'z') || (b >= 'A') && (b <= 'Z')); if ( ( letras && ((a & 95) != (b & 95)) ) || (!letras && (a != b)) ) { printf("As strings sao diferentes\n"); return 0; }; }; // for() printf("As strings sao iguais\n"); return 1; }; Sim, podia ser escrito sem as variáveis a, b e letras. Ia ficar ruim de ler o if gigante. E ia calcular os índices umas 16 vezes. Então assim deve ser mais eficiente e dá até pra ler... E de onde vem o 95? A diferença entre uma maiúscula e uma minúscula na tabela,('a' - 'A') por exemplo, é de 32. No popular o bit 5. Nos 7 bits de um char cabe até 127. Então 127-32 = 95 é o número que tem todos os bits 1 exceto o 5: 0101 1111 em binário. Se você fizer um AND de um char então com esse valor vai zerar o que tem no bit 5 E o resto vai ficar igualzinho. E nesse caso é o que queremos: comparar as letras sem diferenciar maiúsculas de minúsculas. -
Mudanças na configuração da console permanecem depois da execução do programa. Essa é a razão de chamar sempre aos pares Get e Set em programas de console: você tem que salvar tudo como era antes e depois restaurar. E pode ter que mudar muito mais coisas, porque pode ter que garantir que a fonte em uso na console também tenha as letras que quer, pode não poder usar as barras de scroll na lateral da janela e coisas assim. Pode precisar de um tamanho mínimo ou máximo de janela. Pode ter que garantir que o cara não mudou o tamanho durante a execução do programa, ou reagir a uma mudança. Tudo que o Windows faz de graça. E só pode usar uma codepage por vez. . . Note que a página 437 tem as intersecções entre barras simples e duplas para poder usar dois níveis de linhas na tela. Veja alguns: Para a época era bem esperto. Encontrei o programa de que falei e está disponível em https://github.com/ARFNeto-CH/chc20-0722-box para baixar ou https://github.com/ARFNeto-CH/chc20-0722-box/blob/master/box.c para dar uma olhada. Eis uma tela E outra Isso é na verdade um programa de teste de anos atrás. Era um pouco diferente e mais flexível porque gerava o trecho de código em C ou Pascal, mas assim serve para mostrar alguns desses detalhes. De uma olhada se se interessar. Ele aceita os comandos que estão lá, de 0 a 5 para usar os 6 caracteres de desenho, c para mudar a cor e t para mudar o tempo. q para encerrar, h para help. Mas ele não lê nenhum comando, como um jogo. E usa esses caracteres de box-drawing dos anos 80. E muda a fonte da console, a página de saída, retira a barra de scroll e coisas assim. É um exemplo.
-
C Comparando duas strings com condicional IF
arfneto respondeu ao tópico de DanielSantDev em C/C#/C++
Sim. Tempos atrás. Não faz diferença. A menos que esteja falando em considerar iguais maiúsculas e minúsculas. Nesse caso o que se faz é observar que a diferença entre 'A'e 'a' é 32. Então para comparar duas letras sem diferenciar 'x' de 'X' você simplesmente compara zerando esse bit antes. Claro que pode chamar funções como tolower() ou toupper() ou usar usar qualquer outra técnica desde que funcione. Mas isso é o ótimo. O código que postou é mais eficiente. Mas não muito não precisa do fflush() e nem deveria usar de todo modo. fflush() só está definido para fluxos de saída. Se os comprimentos são diferentes simplesmente retorne. Para que um else? Ao invés de testar se todos são iguais teste se algum é diferente. É mais esperto. Qual o propósito de saber se 8 letras de uma string de 9 são diferentes se só quer saber se elas são diferentes? -
Sim. Mas só a codepage não é suficiente como eu falei. Pode ser que a fonte não tenha os caracteres e troque por outros. Pode sair diferente na tela da console ou na tela do IDE ou no Terminal do Windows. Um inferno. E se comparar por exemplo com o mapa de carateres de uma fonte qualquer hoje em dia vai ver a diferença Veja tahoma por exemplo, só um pedaço Então pode usar o Terminal do Windows que tem aceleração gráfica e escrever em Unicode na codepage 65001. Mas isso é algo estranho. Por um lado ninguém usa isso desde os 90. Mas o interesse nesses programas de console aumentou muito nesses últimos anos. Muito mesmo. A Microsoft gastou milhões e milhões nisso. Mas no desktop isso não tem interesse. O lance é que com as máquinas indo aos milhões para a nuvem ficou importante ter uma interface portável e segura porque as máquinas em geral são acessadas via web para qualquer uso. Menos para administração e precisam de algo portável a nível de caracter porque elas não tem interface gráfica.
-
Os caracteres abaixo de 32 são problemáticos como eu disse. Vai depender de coisas como a codepage, a codepage de saida E a fonte em uso na console. Um inferno. Eu pensava em outro, que criava Snapshots dos processos rodando. Mas esse aí tem mais a ver porque o tópico tem mais detalhes, muito embora eu acho que não tenha conseguido explicar ao autor do tópico porque precisa de peek() afinal Ficou meio escuro na imagem e me esqueci de citar: na tabela tem 4 blocos para desenho que preenchem o espaço do cursor todo. São os que aparecem no fim. Eram bem legais em jogos. Eu escrevi um programa de demonstração desses blocos e dessas linhas. Não sei pra que mas também não achei quando eu achar te mostro.
-
C Comparando duas strings com condicional IF
arfneto respondeu ao tópico de DanielSantDev em C/C#/C++
Está bem assim. Eis o que eu poderia acrescentar: scanf() não é uma boa opção. scanf() foi escrita, como o nome diz, para ler entrada formatada --- scan formatted input.. E o teclado é tudo menos isso. É mais simples e seguro usar gets() ou fgets() fflush(stdin) não é certo. Pelo padrão fflush() só atua em arquivos de saída e o funcionamento em entrada é incerto. E de todo modo não precisava disso Você naturalmente lê as strings uma depois da outra. Ao ler a primeira já sabe o tamanho dela e então ao ler a segunda sabe o tamanho das duas e então deve imaginar que é meio ingênuo entrar em um loop para comparar as duas se elas tem tamanhos diferentes. Não acha que podia comparar os tamanhos e retornar a resposta de vez? Economizando uns ciclos de CPU? Na primeira diferença entre as duas strings você já pode retornar. Pra que seguir o loop e contar todos que são iguais se basta um diferente? Não acha que seria melhor seguir o caminho contrário? Se tem tamanhos diferentes são diferentes. Se tem tamanhos iguais, na primeira letra diferente você diz que são... diferentes, Isso não vai mudar. E encerra o programa: return 0; Se chega ao final do loop é porque nenhuma letra era diferente e aí sim você diz que são iguais e retorna. Pense nisso -
Esse é o visual típico dos programas de console dos anos 80. Até as cores são familiares. Hoje em dia temos muito mais opções. Unicode tem hoje pouco mais de 1.1 milhão de cacteres. Um pouco de história Naquela época a tabela ASCII, que tinha ganho minúsculas poucos anos antes, foi estendida, e alguns caracteres foram criados antes do valor 32, o espaço, e depois de 127, o DELETE. Antes de espaço só ficavam caracteres de controle, como só ETX ACK NAK e tal, e eles só tinham sentido para o pessoal de telecomunicação. Não havia TCP/IP ou internet. Comunicação aí era em geral via linhas telefônicas e modems. E a comunicação era sinalizada por esses caracteres. ACK era a resposta positiva, NAK pedia retransmissão e coisas assim. Hoje não mudou tanto assim. Só tem mais camadas. Foi então criado o conceito de CodePage no Windows e uma das primeiras foi a da IBM, 437, e ela tinha alguns caracteres especias que todo mundo passou a usar. Estavam abaixo de 32 e depois de 127 claro, e a tabela ASCII cresceu de 7 para 8 bits. Alguns desses caracteres eram para desenho. Veja abaixo: Com eles se podia ter dois tipos de caixa, com linhas simples ou duplas. E as intersecções. Era o máximo porque antes só tinha barra ponto , traços e a imaginação. E apareceram algumas letrinhas novas no lugar dos caracteres de controle Veja o 16 acima. É o que está no menu que mostrou. Aqui tem a página toda para ver: https://en.wikipedia.org/wiki/Code_page_437#Character_set De volta ao programa Não precisa ser nada assíncrono porque o programa está sempre lendo. Veja que na imagem que postou está lendo uma matrícula. Na tela principal estaria lendo apenas 10 coisas: F1..F4 1..4 TAB ou ESC. E se entrar em um menu vai estar lendo dados relativos ao menu então vai poder tratar ESC ou TAB ou qualquer coisa. Esse tipo de programa está sempre lendo. Em geral o que se faz hoje nos programas de console nada mudou. A lógica é simples: separa a leitura da exibição. Você lê as teclas e aceita só as que fazem sentido. Mas não mostra e não move o cursor de jeito nenhum. Se for inválida pode enviar aquele clássico BEEP, o BEL o ASCII 7. Para o óbvio efeito. Note que o Beep até outro dia ia para o alto-falante do PC Se for o caso de mostrar, como a matrícula no exemplo, e o caracter for válido, aí sim você mostra a letra e avança o cursor Se for uma tecla de função ou um TAB você age de acordo e move o cursor. O clássico persiste até hoje na web: TAB avança campo, shift TAB volta o campo. E o formulário tem essa noção de TAB Order. É assim em java, em DELPHI, em dotNet curses era uma biblioteca que ajudava bem a fazer esse tipo de coisa. Depois evoluiu para ncurses e está disponível até hoje. Não sei como é ncurses em Windows, nem se roda. Era uma coisa de Unix quando eu usava. O grande lance era que o Unix --- Linux OSX Android -- não tem essa noção de console que tem no Windows, e curses evitava que você tivesse que guardar a imagem da tela você mesmo. Porque alguém faria isso? Simples: se o terminal desligasse e ligasse de novo sumia tudo, mas o programa estava normal. No Windows não. Acende tudo igualzinho. Na verdade hoje o padrão do Windows é de pouco mais de 9000 linhas de memória. Esse programa mostra esses caracteres. Os abaixo de 32 são um pesadelo e é melhor nem tentar a menos de um pagamento ou uma aposta ou uma nota. Dias atrás acho que eu postei um programa que faz essa "leitura assíncrona" como falou. É a solução para games, claro, porque você não pode usar um simples read() como deve imaginar. Se tem interesse em ver me avise e eu procuro por ele. A lógica é simples. E não é assíncrono na verdade: você usa PeekConsole Input() e lê o buffer de teclado antes de ler via read() ou scanf() ou getc(0 ou sei lá. E então você age de acordo. Isso no Windows. Se tem algo para ler você já sabe o que é e pode até apagar Só que o programa continua rodando. Acho que deu pra entender. No Linux é diferente: você manipula o tty, o terminal, usando acho que ioctl() e muda o timeout de leitura para 0. Asim o read sempre retorna na hora, tendo ou não algo pra ler. Acho que eu também devo ter algum exemplo, mas nunca postei nada aqui relativo a Unix/Linux então teria que ver.
-
C Comparando duas strings com condicional IF
arfneto respondeu ao tópico de DanielSantDev em C/C#/C++
Exato. Se fosse possível comparar apenas usando if(A==B) provavelmente ninguém ia fazer disso um exercício afinal. Em C uma string é uma sequência de zero ou mais bytes terminada por um 0. E é identificada pelo seu endereço de início. -
C Problema em ordenação de registro (por parametro) bubble sort
arfneto respondeu ao tópico de Luiz Paulo Escobar em C/C#/C++
Vai se sair bem. Escreveu um bom código para quem programa há semanas apenas. No entanto recomendo entender que cada linha de um programa tem um sentido ou não deveria estar lá. Então não escreva sem saber o que é. Recomendo muito ter um livro ou mais. E alguma referência, um site como o Tutorial's Point ou o Geeks For Geeks. E frequentar forums como esse ou o StackOverflow. E ter amigos que programam ou gostam de programar também ajuda muito. Muito bem! Teste seu programa com aquele de 4 linhas que te mostrei. Não perca tempo. Não sou um cara político, de opinião. O que eu escrevo aqui é em geral o padrão da indústria e da academia há décadas. Teste seu programa em partes. Use o que já tem, como as 2 funções que recebeu. Incorpore a terceira, que ordena, e teste sua função nova em um programa de 4 linhas... Que eu também já te mostrei. -
Isso existe há uns 5 anos. É melhor escrever com isso do que usar dirent.h como antes. Isso é o padrão ISO. Não precisa baixar nada.Faz parte da biblioteca padrão, STL. Que versão de compilador está usando? Que opções de compilação está usando? Eu em geral só uso o CL, hoje na versão 19.26, no Windows. Mas esse programa fez parte de um teste e foi compilado com gcc 9.2.0 também. Você deve usar a opção -std=c++17 para compilar. Muitos desses IDE vem configurados para a versão de C++ de 98. Sim, 1998. De 2017 para cá a linguagem já tem várias coisas novas. De 1998 para cá deve imaginar que tem mais Outros ambientes mais modernos vem configurados para o padrão latest, o mais novo. adicionado 1 minuto depois Sério? Leu isso? adicionado 19 minutos depois Pois é. Direto de https://gcc.gnu.org/gcc-9/ Use um desses ao menos, né? Ou Clang ou O Cl da Microsoft. Deve imaginar que o Windows foi escrito com esse, afinal...
-
Muito bem! C++ é muito flexível para criar abstrações e modelos assim rapidamente. Talvez porque tenha sido escrita exatamente para isso, como sempre diz o Prof. Stroustrup, que criou C++: abstrações de custo zero. Se você tem a classe recurso pode ir construindo em torno dela o que precisa. É muito mais simples. Mesmo. Uma classe assim: class Recurso { friend void loadFromMemory(Recurso*); private: unsigned char* conteudo; std::string nome; int tamanho; public: Recurso() = delete; Recurso(string, string); // variavel, arq Recurso(string, int, void*); Recurso(string, int, unsigned char const*); ~Recurso(); int Dump(); int GeraTrecho(string); int GeraDeclaracao(string,string,string); }; // class Você vê que há 3 maneiras de criar um Recurso, mas podiam ser 300. Ou uma só. E a classe é isso: dados e comportamento. Variáveis e métodos. As variáveis Até aqui apenas o óbvio: um nome, um tamanho e o conteúdo que corresponde ao.... conteúdo. Sem novidades. Tanto faz o que é: um cursor, um ícone, uma imagem, um texto, são só bytes. Os métodos Para testar, o que é necessário? Criar um menu e pedir pro usuário teclar valores? Não. Claro que não. Os dois primeiros construtores usam um vetor de char comum, ou um ponteiro void para alguma coisa, e transferem cegamente para o recurso. Dump() E dump mostra os valores em hexadecimal na tela, 16 por linha. E assim dá pra conferir se está tudo funcionando. Depois dos testes, um terceiro construtor Recurso tres("png1", "trecho.txt"); E daí? Já que provavelmente funciona porque foi testado com os Dump() e os dois primeiros construtores, o próximo passo é o simples: carregar o Recurso direto a partir do arquivo como acima. Assim poderia chamar por exemplo loadFromMemory() direto, com o recurso carregado a partir do arquivo. Geralmente é isso que se quer: na carga do programa carrega os recursos do disco para a memória e a partir daí trabalha só com a memória. Mas no caso aqui o que se quer é encapsular o recurso totalmente no executável para não precisar distribuir mais nada. Mas se esse método carrega o Recurso se pode gerar a declaração de qualquer maneira apenas lendo a classe. Por exemplo: tres.GeraDeclaracao("quatro","primeiroPNG","codigo2.txt"); Essa implementação cria o arquivo "codigo2.txt" a partir do que foi carregado a partir de "trecho.txt" na chamada anterior. Exemplo: trecho.txt 1234567890abcdefghABCDEFGH codigo2.txt Recurso quatro("primeiroPNG", 26, (unsigned char*)"\ \x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x61\x62\x63\x64\x65\x66\ \x67\x68\x41\x42\x43\x44\x45\x46\x47\x48\ "); E assim fecha o círculo. No programa distribuído basta usar #include para cada recurso. E se fosse gerar loadFromMemory()? A lógica é exatamente a mesma. Mas o resultado é melhor porque não precisa da classe Recurso no programa de destino. E usando da maneira anterior o executável teria 2 cópias do recurso a toa. Provavelmente numa implementação séria se escreveria GeraDelcaracao() para gerar uma declaração estática. Sugiro fazer isso. E como seria gerar uma declaração assim? int Recurso::GeraDeclaracao( string variavel, string nome, string arquivo) { cerr << std::dec << "Gerando declaracao para '" << nome << "'\n\tda instancia '" << variavel << "'\n\tda classe 'Recurso'\n\tEm '" << arquivo << "' com '"<< tamanho << " bytes" << endl; ofstream saida{ arquivo }; int nl = 16; // quantos por linha /* Recurso variavel ("nome", tamanho, (unsigned char*)"\ */ saida << "\tRecurso " << variavel << "(\"" << nome << "\", " << tamanho << ", (unsigned char*)\"\\ " << endl; for (int i = 0; i < tamanho; i += 1) { saida << "\\x" << hex << setw(2) << setfill('0') << (int)conteudo[i]; if ((i + 1) % nl == 0) saida << "\\" << endl; }; saida << "\\" << endl; saida << "\");\n" << endl; saida.close(); return 0; }; É bem imediato: basta ler de um lugar e gravar no outro. E loadFromMemory()? Pode ser mais simples, como int Recurso::GeraTrecho(string arquivo) { cerr << std::dec << "Gerando codigo para '" << nome << "' em '" << arquivo << "' Tamanho: " << tamanho << " bytes" << endl; ofstream saida{ arquivo }; int nl = 16; // quantos por linha saida << "\tloadFromMemory(\"\\" << endl; for (int i = 0; i < tamanho; i += 1) { saida << "\\x" << hex << setw(2) << setfill('0') << (int)conteudo[i]; if ((i + 1) % nl == 0) saida << "\\" << endl; }; saida << "\\" << endl; saida << "\", " << dec << tamanho << ");\n" << endl; saida.close(); return 0; }; Eis um programa de teste em C++ A saída de um sofisticado programa O programa int main() { Recurso tres("png1", "trecho.txt"); tres.Dump(); tres.GeraTrecho("codigo1.txt"); tres.GeraDeclaracao("quatro","primeiroPNG","codigo2.txt"); return 0; };
-
C Problema em ordenação de registro (por parametro) bubble sort
arfneto respondeu ao tópico de Luiz Paulo Escobar em C/C#/C++
Eu realmente não entendo esse lance de registro por referência de que fala. Veja os protótipos: int fscanf(FILE *stream_name, const char *set_of_characters) char *fgets(char *str, int n, FILE *stream) trata-se da realidade. fgets() espera um endereço, o lugar para onde vai transferir o que ler, saída. Um int com o limite de quanto vai ler, entrada, e um endereço da estrutura que descreve o arquivo de onde "fget" as coisas, entrada. Então é isso o que você deve fornecer. scanf() é igual. Essas rotinas não alocam memória então você tem que passar um endereço de algum lugar para elas transferirem o que conseguirem "scan" ou "get" de algum lugar que você também tem que dizer qual é. Então você sempre usa por referência. SEMPRE. Como eu te disse, scanf() foi escrita para tratar entrada formatada. O teclado não é isso: o cara pode digitar qualquer coisa. E claro que vai dar problema. Você pode tentar contornar com os especificadores, com essa gíria de limpar o buffer, com orações fervorosas, feitiços e tal. Mas sempre vai ter problemas. fgets() e fgetc() para ler linhas e letras é mais seguro para ler do teclado. Mesmo assim problemático porque o cara tem 105 teclas para experimentar. Seguro mesmo só lendo as teclas sem mostrar e só aceitar as que fazem sentido na hora. E não mostrar a letra nem avançar o cursor nesse caso. É sempre assim. Veja os caixas eletrônicos por exemplo... Sobre ordena() Tempos atrás eu postei um programa que faz isso de 4 maneiras, e uma com uma animação, umas barrinhas coloridas, Acho que se você ver rodando vai entender onde seu loop falha. E de todo modo lá tem funções que fazem isso. O programa está nesse endereço https://github.com/ARFNeto-CH/ch-191128-bubble e roda em Windows Eis um desenho: o azul é o que já classificou, as comparações são os pares em amarelo. Meigo -
C Problema em ordenação de registro (por parametro) bubble sort
arfneto respondeu ao tópico de Luiz Paulo Escobar em C/C#/C++
Acho que eu te falei um certo número de vezes, e te mostrei códigos completos e exemplos, como em E eu imaginei que tinha entendido que é sempre um atraso colocar menus e ler coisas do teclado em programas que ainda não estão prontos. Imagino que tenha referências que julgue melhores que a minha simples sugestão. Professores e livros que digam o contrário talvez. Mas eu estou certo e aqui está você com o programa igualzinho de volta Sobre a função ordena() Pois é. A cada vez que vai testar você fica aí sentado inventando esses dados? Chegou a digitar os 30 alguma vez? int ordenar (Cadastro* cad) { int i, j; Cliente troca; for (i = 0; i < 28; i++) { for (j = i + 1; j < 29; j++) { ... Se o usuário --- você --- estiver meio sem paciência e digitar apenas DOIS valores, que acha que vai rolar com esses loop com valores fixos em 28 e 29? Para que você acha que eram as variáveis cad->limite e cad->total? int novoCadastro(Cadastro* cad) { Cliente modelo1 = { .codigo = 12, .nome = "cliente 12" }; Cliente modelo2 = { 13,"cliente 13" }; cad->cl[0] = modelo1; cad->cl[1] = modelo2; cad->cl[2] = modelo2; cad->cl[3] = modelo1; cad->total = 4; cad->limite = 30; return 4; }; Sobre essa função acima eu te mostrei com detalhes e achei que você tinha entendido, já que nada mais perguntou. E aí pergunto eu: porque razão não testou a função int ordenar(Cadastro* cad) que escreveu com esse cadastro e editando nele direto com outros valores, para testar sua função em minutos ao invés de dias? Se recorda de ter aí um programa completo que roda isso? Não entendeu mesmo que seria só chamar Cadastro cad; novoCadastro(&cad); // ja vem preenchido imprimirLista(&cad); // mostra ainda fora de ordem ordena(&cad); imprimirLista(&cad); // mostra depois de ordenar ?? -
C separar números quando faço depuração
arfneto respondeu ao tópico de José Eduardo Corrêa Tavare em C/C#/C++
Você de fato leu o que eu escrevi? Vou repetir mas esta;aqui acima no tópico anterior... E não mudei de ideia nessas poucas horas. Visual Studio é o padrão da indústria e da academia. A NASA usa, a NSA usa. A Boeing usa. O bradesco usa. a Porto Seguro usa. A Mafre usa. E Visual Studio Code é muito bom. Muito mesmo. E é muito flexível. Acho que já dei muitos exemplos aqui das coisas que você pode fazer com ele. E o CLion, da JetBrains --- que por coincidência agora anuncia aqui neste forum --- é genial. Visual Studio está evoluindo para um "primo" online chamado Visual Studio CodeSpaces que deve revolucionar o desenvolvimento no geral. Visual Studio inclui um compilador sólido e sempre atualizado. VS Code permite, como eu expliquei muitas vezes, que se use outros compiladores ao mesmo tempo, compilando no Windows com gcc CLang ou o próprio compilador da Microsoft. Só que também permite que você compile e até use o debugger em sessões no Linux ou no Mac. Sem sair de sua mesa e de sua máquina Windows. São situações que nem se imaginava possíveis anos atrás. E pode ser uma máquina virtual Linux na sua própria máquina Windows 10, poruqe o Windows agora inclui um kernel Linux completo e grátis. E tal loja do Windows tem Ubuntu, Suse e Kali e outras distribuições que você pode baixar de graça. E rodam em 3 ou 4 segundos numa máquina comum, sem sair do Windows mas rodando Linux. Tipo mágica... Então é difícil dizer qual é melhor. CLion gera código pra você: interfaces de classes, getters, setters, É muito esperto e muito produtivo. O VS Code tem uma loja de extensões, com milhares delas. E algumas são geniais. O editor é muito bom e personalizável ao infinito. E também é muito integrado ao git. O Visual Studio com o vcpkg e o cmake são o padrão para projetos grandes ou enormes ou gigantes mesmo. O VS Code de um modo geral segue a ideia do Eclipse, Dev-C++ e do Code::Blocks, mas com um nível de qualidade de acordo com o dinheiro e com as pessoas que a MicroSoft tem para trabalhar nisso. Recomendo experimentar os dois. O Visual Studio é tipo turn-key: você instala e tem tudo pronto. O você Code é iterativo. Está bem documentado, mas entenda que ele funciona em torno de compiladores que você instala --- como os IDE que você usa --- e você pode claro usar os mesmos que usa no Code::Blocks por exemplo. E em torno de formulários, arquivos json que configuram tarefas como compilar, listar os arquivos de um projeto, rodar os programas e tal. Depois de configurado é como nos outros: um atalho para rodar o programa, um para build, um para o debugger... Acho que não leu o que eu escrevi antes... Então vou repetir -
Isso que eu te mostrei dá o ciclo completo: um programa em qualquer linguagem gera a tabela idx[256] que incorpora a lógica no momento. O programa que vai usar apenas inclui o texto que foi gerado. E o programa resultante já incorpora toda a lógica da tabela. É muito produtivo. Aqui tem arquivos de entrada então recomendo usar o arquivo de recursos. Claro que na verdade nem precisa existir isso, mas assim é mais flexível e mais fácil de testar... Veja esse resultado [ usando void* ] (*) Recurso png1 com 64 bytes 21 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 21 [ usando unsigned char const* ] (*) Recurso png2 com 40 bytes 21 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 21 Deste programa em C++ #include <iostream> using namespace std; #include "Recurso.h" int main() { unsigned char teste[65] = "\ !BCD5678ABCD5678\ ABCD5678ABCD5678\ ABCD5678ABCD5678\ ABCD5678ABCD567!"; void* outro = &teste[0]; string str = "png1"; Recurso um(str, sizeof(teste)-1, outro); um.Dump(); Recurso dois("png2", 64, (unsigned char*)"\ !BCD5678ABCD5678\ ABCD5678ABCD5678\ ABCD5678ABCD5678\ ABCD5678ABCD567!"); dois.Dump(); }; Aqui você vê duas maneiras de usar, e graças ao polimorfismo você tem os dois construtores já. E o construtor padrão foi apagado para evitar que você esqueça e declare algum recurso errado. Veja a classe abaixo e confirme se entendeu. Uma implementação mínima, usando o construtor 2, unsigned char* class Recurso { public: private: unsigned char* conteudo; std::string nome; int tamanho; public: Recurso() = delete; Recurso(string, int, void*); Recurso(string, int, unsigned char const*); ~Recurso(); int Dump(); }; // class E o arquivo de recurso recurso.txt tendo # uso: arquivo<TAB>instancia teste.txt dois E o arquivo teste.txt tendo 64 bytes e esse conteúdo !BCD5678ABCD5678 ABCD5678ABCD5678 ABCD5678ABCD5678 ABCD5678ABCD567! Sem as quebras de linha O programa final teria só isso #include <iostream> using namespace std; #include "Recurso.h" int main() { #include "trecho.txt" dois.Dump(); }; E o arquivo trecho.txt gerado seria Recurso dois("dois", 64, (unsigned char*)"\ !BCD5678ABCD5678\ ABCD5678ABCD5678\ ABCD5678ABCD5678\ ABCD5678ABCD567!"); E mostraria [ usando unsigned char const* ] (*) Recurso dois com 64 bytes 21 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 38 41 42 43 44 35 36 37 21 Entendeu? O que Dump() mostra é o conteúdo em hexadecimal do que estava no arquivo original teste.txt no disco. E isso é para ter certeza de que está rodando certo. Para gerar um loadFromMemory() é igualzinho, apenas vai colocar o tamanho depois da vírgula e fechar com ");" loadFromMemory("\ !BCD5678ABCD5678\ ABCD5678ABCD5678\ ABCD5678ABCD5678\ ABCD5678ABCD567!", 64 );
-
É a mesma coisa. Entendeu que vai girar tudo em torno do arquivo de recursos? # recursos teste.png png1 azul.ico ico1 outro.png png2 Você vai escrever um programa simples, em C ou C++ ou awk ou sei lá. Esse programa vai ler seu programa C++ e gerar as declarações que estão faltando, a partir dessa lista que está no arquivo e lendo os arquivos no disco e preenchendo a declaração das classes. Só isso. Quando você compilar o programa vai ter um código que que cria as instâncias da classe que te mostrei, aloca memória para os png e tudo que precisar. No código você não trata isso mais. Está tudo lá. Ao sair do programa os destrutores vão liberar a memória. Veja esse exemplo em C de algo parecido: esse programa você roda assim x saida.txt E ele cria saida.txt. Claro que é como qualquer outro programa de console: o argumento é o nome do arquivo de saída. Eis o que ele gera const char idx[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 0, 0, 0, 0, 0, 0, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // ARFNeto '20 E serve para um milhão de coisas. É uma tabela de referência. Esse é um exemplo e não me lembro agora para que era. Isso é o que sai na tela ao rodar o programa: Gerado trecho de codigo em 'saida.txt' Eis o programa #define _CRT_SECURE_NO_WARNINGS #include "stdio.h" int main(int argc, char** argv) { FILE* saida = stdout; int disco = 0; // gerou arquivo? if (argc > 1) { saida = fopen(argv[1], "w"); disco = 1; }; int out = 1; fprintf(saida, "\nconst char idx[256] =\n{\n\n"); for (int i = 0; i < 44; i = i + 1) { // 44 = . e o primeiro valido: idx = 1 fprintf(saida, "%3d, ", 0); if (out % 16 == 0) fprintf(saida, "\n"); out += 1; }; fprintf(saida, " 1, 0, 2, 0,\n"); // 46 = , idx = 2 48 = '0', idx = 3 out += 4; // loop agora para 0 a 9, idx = 3..11 int idx = 3; for (int i = '0'; i <= '9'; i += 1, idx += 1) { fprintf(saida, "%3d, ", idx); if (out % 16 == 0) fprintf(saida, "\n"); out += 1; }; // agora o intervalo entre '9'e 'A', 58..64 for (int i = 58; i < 65; i += 1) { fprintf(saida, "%3d, ", 0); if (out % 16 == 0) fprintf(saida, "\n"); out += 1; }; // agora as letras de A a Z for (int i = 'A'; i <= 'Z'; i += 1, idx += 1) { fprintf(saida, "%3d, ", idx); if (out % 16 == 0) fprintf(saida, "\n"); out += 1; }; // agora o intervalo entre 'Z' e 'a', 91..96 for (int i = 91; i <= 96; i += 1) { fprintf(saida, "%3d, ", 0); if (out % 16 == 0) fprintf(saida, "\n"); out += 1; }; // agora as letras de 'a' a 'z' for (int i = 'a'; i <= 'z'; i += 1, idx += 1) { fprintf(saida, "%3d, ", idx); if (out % 16 == 0) fprintf(saida, "\n"); out += 1; }; // agora o intervalo de 'z' ate o fim for (int i = 123; i < 255; i += 1) { fprintf(saida, "%3d, ", 0); if (out % 16 == 0) fprintf(saida, "\n"); out += 1; }; fprintf(saida, " 0\n\n}; // ARFNeto '20\n"); if (disco) { fprintf(stderr, "\nGerado trecho de codigo em '%s'\n", argv[1]); }; return 0; }; // main() É só pra você entender a ideia. Como usar isso: Vai ser um #include em seu programa. Nada mais. Veja um programa que usa isso #include "stdio.h" #include "saida.txt" int main() { int l = 0; printf("\n"); for (int i = 0; i < 256; i += 1) if (idx[i] != 0) // tem representacao { printf(" %2d:%3d %c", idx[i], i, i); if (l % 8 == 7) printf("\n"); l += 1; }; // if() printf("\n"); }; E mostra o resultado do look-up 1: 44 , 2: 46 . 3: 48 0 4: 49 1 5: 50 2 6: 51 3 7: 52 4 8: 53 5 9: 54 6 10: 55 7 11: 56 8 12: 57 9 13: 65 A 14: 66 B 15: 67 C 16: 68 D 17: 69 E 18: 70 F 19: 71 G 20: 72 H 21: 73 I 22: 74 J 23: 75 K 24: 76 L 25: 77 M 26: 78 N 27: 79 O 28: 80 P 29: 81 Q 30: 82 R 31: 83 S 32: 84 T 33: 85 U 34: 86 V 35: 87 W 36: 88 X 37: 89 Y 38: 90 Z 39: 97 a 40: 98 b 41: 99 c 42:100 d 43:101 e 44:102 f 45:103 g 46:104 h 47:105 i 48:106 j 49:107 k 50:108 l 51:109 m 52:110 n 53:111 o 54:112 p 55:113 q 56:114 r 57:115 s 58:116 t 59:117 u 60:118 v 61:119 w 62:120 x 63:121 y 64:122 z Espero que tenha ajudado você a entender: Você vai escrever um programa assim, que vai pegar seu programa em C++ e seu arquivo de recursos e vai gerar as declarações que estão faltando, já certinhas...
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