-
Posts
6.526 -
Cadastrado em
-
Última visita
Tipo de conteúdo
Artigos
Selos
Livros
Cursos
Análises
Fórum
Tudo que arfneto postou
-
Não consegui entender printf() é uma função,o resultado vai para a saída padrão. control C é uma combinação de teclas, e dependendo da configuração e do sistema pode gerar uma interrupção, um sinal no Linux que você pode interceptar e associar a uma função em seu programa. No Windows não funciona assim. Estaria usando Windows e quer copiar um texto para a área de transferência? Se for esse o caso a documentação está toda aqui em https://docs.microsoft.com/en-us/windows/win32/dataxchg/about-the-clipboard
-
Porque em java seria mais simples? Tem um exemplo? Porque não usou strings em C++? Em java não poderia alocar nada, e então não precisaria liberar nada. Mas não fez isso em seu programa então não faria muita diferença, eu acho. Foi a diferença que me ocorreu. Não sei se consegui entender ao certo o que quer fazer mas parece ser um tema útil para outros também, então escrevi um programa de exemplo "retornar um array 2D de funções" --- o que está no título --- Seria como retornar uma matriz MxN de endereços de funções. Não é o que seu programa faz e acho que não é o que pretende. Mas vou mostrar esse caso. "passar arrays 2D de char por funções" Pelo seu código char** createTable(int m, int n) { int total = m*n; arr = new char* [m]; for (int i = 0; i < m; i++) { arr[i] = new char[n]; for (int j = 0; j < n; j++) { arr[m][n] = '0'; } } return arr; } parece pretender retornar um array de strings, como o argv do C/C++, com uma string para cada linha. Ou seria o caso de retornar uma matriz (MxN) de char com '0'? Considere M = 6 e N = 4 nesse exemplo adiante. 1: Como sua rotina parece fazer: O resultado aparentemente esperado para createTable() seria então 000 000 000 000 000 000 onde arr[0] até arr[5] seriam strings e temos 4 bytes para cada uma. Como tem que ter um null para terminar a string restam 3 para colocar o '0' cujo valor é 48 na tabela, e o 0 vem depois. seu programa cancela por isso (ou pela falta disso: o null ao final)... Assim funcionaria: char** createTable(int m, int n) { char** arr; arr = new char* [m]; for (int i = 0; i < m; i++) { arr[i] = new char[n]; for (int j = 0; j < n - 1; j++) arr[i][j] = '0'; arr[i][n - 1] = 0; }; return arr; } 2: Uma matriz de char MxN Esse é o caso mais comum. O resutado esperado seria uma coisa assim, usando '0' como fez para preencher: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Assim funcionaria: char* createTableXY(const int m, const int n) { char* arr = new char[m*n]; memset(arr,'0', m*n); return arr; } E poderia chamar assim, e mostra a matriz a seguir: char* coisa = createTableXY(m,n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { cout << *(coisa + i*n + j) << " "; }; // for (j) cout << endl; }; // for(i) // game over: apaga os caras delete coisa; O que importa aqui é isso: *(coisa + i*n + j); // para acessar o elemento (i,j) da matriz (Dias atrás teve uma discussão aqui nesse forum de como acessar um elemento para uma matriz com qualquer número de índices, e tem lá um programa de teste e referências.) 3: Um array 2D de funções Esse é mais raro e mais enjoado. É absolutamente essencial em C, C++, java e o diabo, mas em geral é transparente para quem usa. No caso de java e C++ é a maneira de se implementar funções virtuais, classes abstratas, aquelas coisas. É criada uma tabela de funções, chamada VFT --- virtual function table --- que define qual função vai ser chamada para uma certa classe virtual. Postei um exemplo disso aqui um dia desses. Vou dar um exemplo aqui pra ficar mais completo, ainda que poucos tenham paciência de ler. Respostas curtas são tão mais legais! Em C/C++ Isso declara pFteste como o endereço de uma função que retorna int e recebe dois int como argumentos int (*pFteste)(int, int); Então você pode escrever typedef int (*pF)(int, int); E pF** cria_vetor_2D(const int, const int); E esse poderia ser o protótipo de uma função que retornaria um vetor 2D de ponteiros para função. Você chamaria assim, no nosso exemplo: pF** teste_v2D = cria_vetor_2D(M,N); Para não complicar, considere essa função int modelo(int a, int b) { cout << "funcao(" << a << "," << b << ")" << endl; return a * b; }; // modelo() Ela recebe dois int mostra os valores e retorna o produto deles. E serve para o nosso pF. Claro que normalmente se usa (void*) para as funções e depois converte para o que for preciso, como o qsort() no C por exemplo. Veja uma implementação de cria_vetor_2D() que preenche a matriz de funções com o endereço dessa aí e retorna o endereço da tal matriz // cria vetor 2D de funcoes pF** cria_vetor_2D(const int x, const int y) { pF** v2D = new pF* [x]; for (int i = 0; i < x; i++) { v2D[i] = new pF[y]; for (int j = 0; j < y; j++) v2D[i][j] = modelo; }; // for (i) pF a = modelo; (*a)(1, 2); return v2D; }; // cria_vetor_2D() E Como chama um trem desses? Simples. No exemplo MxN que temos essas 3 linhas criam a matriz e chamam a primeira e a última função na matriz, só para testar: pF** teste_v2D = cria_vetor_2D(M,N); (*teste_v2D[0,0])(3,8); (*teste_v2D[M - 1, N - 1])(M - 1, N - 1); Como apagar essas coisas? Atente para o fato de que ao alocar um array em C++ depois PRECISA usar colchetes no delete. Então para apagar a matriz por exemplo precisa escrever assim: // game over: apaga os caras for (int i = 0; i < M; i++) delete[] arr[i]; delete arr; Eis o resultado do programa exemplo, que usa as 3 opções Testando para M = 6 e N = 4 1: uma string por linha linha: 0 [000] linha: 1 [000] linha: 2 [000] linha: 3 [000] linha: 4 [000] linha: 5 [000] 2: matriz MxN de caracteres 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3: array 2D de funcoes funcao(3,8) retornou 24 funcao(5,3) retornou 15 E o programa #define _CRT_SECURE_NO_WARNINGS // https://www.clubedohardware.com.br/forums/topic/ // 1427656-retornando-array-2d-de-fun%C3%A7%C3%B5es/ // ?tab=comments#comment-7699344 #include <iostream> #include <string.h> typedef int (*pF)(int, int); char** createTable(int, int n); char* createTableXY(const int, const int); pF** cria_vetor_2D(const int, const int); int modelo(int, int); using namespace std; int main(int argc, char** argv) { int M = 6; int N = 4; cout << "Testando para M = " << M << " e N = " << N << endl; cout << "\n1: uma string por linha\n\n"; char** arr = createTable(M, N); for (int i = 0; i < M; i++) { cout << "linha: " << i << " [" << arr[i] << "]" << endl; } // game over: apaga os caras for (int i = 0; i < M; i++) delete[] arr[i]; delete arr; // cout << "\n2: matriz MxN de caracteres\n\n"; char* coisa = createTableXY(M, N); for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { cout << *(coisa + i * N + j) << " "; }; // for (j) cout << endl; }; // for(i) // game over: apaga os caras delete coisa; cout << "\n3: array 2D de funcoes\n\n"; pF** teste_v2D = cria_vetor_2D(M, N); int r = (*teste_v2D[0, 0])(3, 8); cout << "retornou " << r << endl; r = (*teste_v2D[M - 1, N - 1])(M - 1, N - 1); cout << "retornou " << r << endl; for (int i = 0; i < M; i++) delete[] teste_v2D[i]; delete teste_v2D; return 0; }; // main() char** createTable(int m, int n) { char** arr; arr = new char* [m]; for (int i = 0; i < m; i++) { arr[i] = new char[n]; for (int j = 0; j < n - 1; j++) arr[i][j] = '0'; arr[i][n - 1] = 0; }; return arr; }; //createTable() char* createTableXY(const int m, const int n) { char* arr = new char[m * n]; memset(arr, '0', m * n); return arr; }; // createTableXY() pF** cria_vetor_2D(const int x, const int y) { int (*pFteste)(int, int); pF** v2D = new pF * [x]; for (int i = 0; i < x; i++) { v2D[i] = new pF[y]; for (int j = 0; j < y; j++) { v2D[i][j] = modelo; }; // for (j) }; // for (i) return v2D; }; // cria_vetor_2D() int modelo(int a, int b) { cout << "funcao(" << a << "," << b << ")" << endl; return a * b; }; // modelo()
-
postei aqui --- no ano pasado --- nesse forum duas soluções para números primos que pode adaptar para esse exercicio, afinal basta contar os fatores. Uma usava o crivo de eratostenes e a outra era convencional. pode pesquisar aqui por esse tema
-
C++ como passar uma classe de objetos para uma funcao
arfneto respondeu ao tópico de Jonathas David em C/C#/C++
A resposta curta é sim. Note que em C++ objetos são chamados classes então uma classe inteira de objetos seria uma classe. Só isso. E que poderia conter outras classes, que poderiam conter outras classes e tal. E você não passa uma classe inteira de objetos, passa uma instância da classe --- ou do objeto, se preferir chamar assim. Hoje não posso escrever um exemplo, mas entenda que ao usar algo como void funcao_carro( carro um_carro ){ return; }; vai estar copiando a variável para outro local e então construtores serão invocados, e você precisa entender os custos e os efeitos colaterais disso. Apenas usando ponteiros vai deixar de usar esses mecanismos --- construtores --- e nem sempre a lógica permite usar ponteiros, então é preciso se acostumar com esses casos. -
Esqueci de comentar isso, mas ao inserir em uma lista você parece ter optado pelo caminho curto, inserir no início. Mas no propósito geral de usar uma lista encadeada muitas vezes se espera manter a ordem de inserção --- a lista é dita estável --- de modo que ao percorrer a lista você vê os elementos na ordem em que foram inseridos. O primeiro listado será o primeiro inserido e assim por diante. manter a lista ordenada --- e se usa claro algum campo e uma função de comparação --- de modo que ao percorrer a lista os elementos vem classificados, por ordem crescente, por CEP, por endereço de entrega, por algo útil na aplicação que usa sua lista. E nesses casos você precisaria inserir de acordo...
-
Ainda não tenho uma máquina com windows 7 pra rodar isso. Mas nesse computador que eu uso em geral para acessar o forum configurei o VSCode sem problemas para compilar no Ubuntu, no SUSE, e no Windows hoje. É uma máquina antiga mas que roda WIndows 10 e o tal WSL2, o subsistema para Linux da Microsoft. Para compilar no Windows não precisa de muito. Para usar para compilar C e C++ em Windows no Windows 7 você pode usar qualquer compilador. O VS Code não tem um. Tudo o que precisa fazer é ver o caminho certinho para seu compilador e colocar no arquivo c_cpp_properties.json que é um formulário assim { "configurations": [ { "name": "Win32", "defines": ["_DEBUG", "UNICODE", "_UNICODE"], "compilerPath": "Compilador", "windowsSdkVersion": "10.0.17763.0", "intelliSenseMode": "msvc-x64", "cStandard": "c11", "cppStandard": "c++17" } ], "version": 4 } JSON --- JavaScript Object Notation --- é um formato comum para texto em pares chave/valor e em compilerPath você coloca o caminho completo para o compilador que quer usar e preenche o resto de acordo. Para usar o compilador da Microsoft você precisa segundo a documentação chamar o vscode a partir de um prompt de desenvolvedor do Windows. Para ter isso você tem duas opções: ou instala o Visual Studio ou apenas o kit de build da Microsoft para o seu sistema. É de graça. Está em https://visualstudio.microsoft.com/pt-br/downloads/ e deve rodar no windows 7. Não se esqueça que precisa também do .Net A documentação mais precisa está em https://code.visualstudio.com/docs/cpp/config-msvc adicionado 4 minutos depois Pode ser uma vantagem para poder testar programas de console em C ou C++ em distribuições Linux E no Windows usando o novo Terminal e a nova API sem sair do VS Code. Bem moderno achei.
-
Mude a declaração de Inserir() para retornar o novo endereço do início da lista ou ele vai se perder... Use Valor* Inserir(Valor*, int ); Declare a lista em main(), mais seguro. Declare apenas estruturas e protótipos fora de main(). Imprima a lista lista antes de inserir. É um bom começo saber que pode listar uma lista vazia Com algo assim você progride mais depressa: int main(void) { Valor* aLista = NULL; imprimeEncadeada(aLista); for(int i=0; i<5; i+=1) { aLista = Inserir(aLista, i); imprimeEncadeada(aLista); } return 0; } Escreva a função que apaga a lista toda, com o mesmo protótipo que inserir()
-
Tem um exemplo aqui e mais documentação https://docs.microsoft.com/pt-br/windows/win32/psapi/enumerating-all-processes E o programa que eu postei para ajudar foi em 12/dez. Ele faz o seguinte: Cria o que se chama de snapshot que deve ter visto na documentação, e grava em uma estrutura bem simples: struct snapshot { int total; time_t hora; PROCESSENTRY32** processo; }; typedef struct snapshot Snapshot; Depois espera um ENTER e cria uma nova lista e compara. Eis o final de uma execução O programa pode ver visto visto aqui ou baixado aqui Eu acho que postei um outro mais sofisticado mas ainda não consegui me lembrar dos detalhes nem da linguagem. Eu aviso se me lembrar e achar algo adicionado 19 minutos depois Achei o outro, mas foi escrito em C também. Rodar em C++ é trivial no entanto. Acho que não vi nenhuma razão na época para escrever em C++. A diferença entre os dois é que esse roda continuamente e vai comparando as listas de processos para mostrar os que foram encerrados ou iniciados no intervalo, e mostra com umas cores na tela porque eu queria deixar as funções como exemplo para escrever assim, já que muitos aqui neste forum parecem gostar de escrever assim na console então deixei as funções de exemplo disponíveis. E esse programa também usa alarmes e timers e eventos e sei que é difícil achar exemplos disso Eis um trecho O programa esta aqui adicionado 33 minutos depois minha memória está voltando Esse segundo programa inclui também uma função de exemplo cls() para limpar a tela da console do jeito oficial no Windows, ao invés do ingênuo system("cls") E uma função mostra_grade_256_cores() que... mostra a grade de cores para a antiga console do Windows --- o novo terminal tem 16.7 milhões de cores. Ela mostra isso para se saber como seria escrever em 15 sobre 3, por exemplo: texto branco sobre fundo azul claro, como está no gabarito aí acima. E uma função void gotoYX(l, c); que afinal escreve texto na linha l e coluna c afinal ao invés da gotoxy() dos anos 80 que vem sendo preservada nos programas de console aqui no forum
-
A fonte mais comum desse tipo de informação é a PSAPI, Process Status API documentada em https://docs.microsoft.com/en-us/windows/win32/psapi/process-status-helper e C ou C++ seriam bem adequadas para ler essas coisas. Sugiro ler as informações sobre as estruturas e a lista de funções e escrever alguns programas de teste, assim vai se acostumando e pode postar aqui se algo sair errado. Acho que no ano passado eu postei nesse forum alguns programas que usavam isso, mas agora não sei o que era
-
Em https://code.visualstudio.com/docs/setup/windows tem um link para uma versão do instalador para a versão de 32 bits. Note que você deve ter .NET Framework 4.5.2 ou mais recente para rodar isso. O que exatamente acontece em sua máquina? Eu nunca usei nesse ambiente, 32 bits windows 7. O grande lance disso --- VS Code --- é usar o WSL para compilar no Windows programas em C ou C++ rodando no Linux via WSL em tempo real sem sair do WIndows, mas acho que o WSL não roda no Windows 7. Para usar o VS Code no Windows o Visual Studio não seria a opção? Vou tentar instalar no Windows 7 depois
-
Erro no Win 7: Você não tem permissão para desligar o computador
arfneto respondeu ao tópico de Abner-Augusto31 em Versões até Windows 8
não creio que estejam Apenas recrie os indices e tudo deve voltar ao normal. Pode usar Painel de Controle opções de indexacao avançado recriar E esperar terminar Sobre não ter permissão para desliga, se for seu caso, veja no painel de controle ferramentas administrativas opções de segurança local politicas locais atribuição de direitos de usuário desligar o sistema e inclua sua conta ou exclua e inclua de novo se ja estiver la -
Erro no Win 7: Você não tem permissão para desligar o computador
arfneto respondeu ao tópico de Abner-Augusto31 em Versões até Windows 8
Entendo. Não é como está no tópico, mas de todo modo acho que o acesso a pastas do sistema também está nas políticas de segurança local. Tente criar um novo grupo e colocar um usuário de teste nele para ver o que acontece. Acho que algo interferiu com essas políticas numa alteração recente. SecPol. Um vírus nocivo não iria se anunciar assim. Seria muito ingênuo afinal -
Erro no Win 7: Você não tem permissão para desligar o computador
arfneto respondeu ao tópico de Abner-Augusto31 em Versões até Windows 8
Olá! Não acredito que alguém iria se preocupar em escrever um vírus assim inócuo, já que desligar o sistema pode ser feito de maneiras mais, digamos, assertivas, como puxar o cabo de força. Pode ser só algum problema com a verificação dos direitos de uso. Desligar o sistema é validado nos direitos do usuário e é atribuído a cada conta no sistema. Não tenho nenhuma máquina com Windows 7 aqui para ajudar, mas o que posso recomendar é fazer o simples em uma máquina dessas: painel de controle ferramentas administrativas política de segurança local E dentro de políticas locais abrir atribuição de direitos de usuário Vai abrir um formulário assim onde estão, como imaginado, listados direitos de usuário na máquina local, em ordem alfabética. E lá está "DESLIGAR O SISTEMA". Tecle ENTER e deve ver Isso. Pode ser que algo tenha sumido aí. Apenas reintroduza usuários ou insira sua conta explicitamente e veja o que acontece adicionado 5 minutos depois ah claro você pode usar Windows+R e mandar rodar SecPol.msc que vai abrir direto a janela de políticas de segurança local -
Acho que não leu direito ... Talvez pudesse ler de novo o que eu escrevi. Onde leu sobre controlar computador de alguém? Estava só tentando te explicar que esse seu "script" --- em C++? --- pode ser usado a partir de outros computadores com outros endereços MAC, através de acesso remoto... E expliquei algo mais que talvez não tenha lido. E para poder te ajudar melhor te pedi mais informações, que você não deu...
-
Talvez pudesse explicar mais sobre o que quer dizer com isso. Computadores não tem endereços MAC. Adaptadores de rede sim. E um computador pode ter vários, reais ou virtuais. E várias contas de usuários. E o login pode ser feito via domínio usando contas de usuário que não são locais. E o computador pode ser acessado remotamente, de modo que alguém pode estar usando seu micro de um outro lugar. Você quer vincular a cópia de seu programa a um determinado computador?
-
Isso vai depender do jogo e da situação. Se estiver simulando movimento, partículas ou coisas assim não há qualquer problema em repetir números e por outro lado você pode criar problemas ao evitar a repetição. Imagine por exemplo vento, fogo, inimigos...
-
Você provavelmente não leu com cuidado a documentação de rand()/srand()... Quando você chama isso --- srand() --- com um certo valor a sequência é reiniciada. Isso se chama seeding, de semear. Como você chama srand() de novo com o mesmo valor fica tudo igualzinho de novo Veja a saída Vai usar srand(time(NULL) para iniciar a sequencia!... rand() 9 rand() 4 rand() 3 rand() 1 rand() 5 rand() 4 rand() 10 rand() 3 rand() 10 Vai usar o mesmo srand() para iniciar a sequencia... EntÒo vai gerar a mesma sequencia!... rand() 9 rand() 4 rand() 3 rand() 1 rand() 5 rand() 4 rand() 10 rand() 3 rand() 10 para o programa #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include "time.h" int main(int argc, char* argv) { printf("Vai usar srand(time(NULL) para iniciar a sequencia!...\n"); srand(time(NULL)); for (int i = 0; i < 9; i += 1) printf("rand()%10 %d\n", rand() % 10 + 1); printf("Vai usar o mesmo srand() para iniciar a sequencia...\n"); printf("Então vai gerar a mesma sequencia!...\n"); srand(time(NULL)); for (int i = 0; i < 9; i += 1) printf("rand()%10 %d\n", rand() % 10 + 1); return 0; }; // main() Agora se você mudar... printf("srand(2002021355) para iniciar a sequencia!...\n"); srand(2002021355); for (int i = 0; i < 9; i += 1) printf("rand()%%10 %d\n", rand() % 10 + 1); printf("Continua usando rand() para a nova sequencia...\n"); for (int i = 0; i < 9; i += 1) printf("rand()%%10 %d\n", rand() % 10 + 1); return 0; vai ver srand(2002021355) para iniciar a sequencia!... rand()%10 3 rand()%10 7 rand()%10 4 rand()%10 6 rand()%10 5 rand()%10 4 rand()%10 2 rand()%10 9 rand()%10 6 Continua usando rand() para a nova sequencia... rand()%10 2 rand()%10 6 rand()%10 8 rand()%10 6 rand()%10 6 rand()%10 8 rand()%10 7 rand()%10 3 rand()%10 5 Que significa? Qual seria o problema em geral? adicionado 2 minutos depois As vezes você quer exatamente isso: poder reproduzir uma sequência "aleatória" para novos testes. Mas em muitos casos não é o que você quer. Então você chama srand() de acordo com sua intenção. Qualquer integer serve como parâmetro.
-
Na verdade a fórmula dá 2 possibilidades para algum número estar na sequência de Fibonacci e daí a encontrar o n-ésimo não-Fibonacci é um grande salto... E sai caro esse salto porque a maioria dos números está fora dessa sequência e não o contrário. Sobre o círculo de Josephus por coincidência postei duas soluções nesse forum, semanas atrás. Se quiser ver estão em adicionado 0 minutos depois Bom trabalho em sua solução!
-
O código original parecia um "código muito eficiente", mas com aquelas contas todas e funções demora quase 40 vezes mais, então é algo pra pensar. Mas o resultado está certo nos dois casos. Os não-Fibonacci Talvez o jeito mais simples de considerar a lógica de achar o n-ésimo não-Fibonacci seja simplesmente considerar que você conta todos os números, exceto os que estão na sequência de Fibonacci, e nesse caso você avança para o próximo. Então ou faz uma coisa ou outra para todos os números. E assim deve ser um if dentro de um loop. E é mesmo. As contas A função double testa_funcao(uint64_t(*funcao)(uint64_t), uint64_t limite){} recebe o endereço (nome) da função que você quer testar e retorna o tempo gasto então dá um número mais objetivo da diferença de tempo adicionado 15 minutos depois Note que você pode escrever sua função e testar usando esse programa aí, chamando bool resultado_identico(int limite){} Para comparar com a original e usando testa_função() como declarada acima para comparar os tempos entre sua solução e essas duas que discutimos aqui. Ou mudar o programa e tabelar as 3 claro...
-
C Como abrir os pixels de uma imagem e comparar com outra
arfneto respondeu ao tópico de Mayrinck Bernardo em C/C#/C++
No caso de gravar os pixels na memória no formato clássico RGBA veja a saída Valor original: 123456ff vermelho: 00000012 verde: 00000034 azul: 00000056 alfa: 000000ff desse programa #include <iostream> #include <iomanip> using namespace std; int main() { // 0x123456FF { unsigned int color = 0x123456FF; int red = (color & 0xFF000000) >> 24; int green = (color & 0x00FF0000) >> 16; int blue = (color & 0x0000FF00) >> 8; int alpha = (color & 0x000000FF); cout << "Valor original: " << setfill('0') << setw(8) << hex << color << endl; cout << "vermelho: " << setfill('0') << setw(8) << hex << red << endl; cout << " verde: " << setfill('0') << setw(8) << hex << green << endl; cout << " azul: " << setfill('0') << setw(8) << hex << blue << endl; cout << " alfa: " << setfill('0') << setw(8) << hex << alpha << endl; } return 0; } e vai entender como montar os pixels Essa outra classe aqui grava bitmaps. Veja essas funções em especial void fillBitmap(uint8_t, uint8_t, uint8_t); void setPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue); Para definir um pixel --- setPixel() ---ou encher um bitmap --- fillBitmap() --- com uma cor RGB #include <fstream> #include <string> #include <cstdint> #include <memory> using namespace std; #pragma pack(push, 2) class Bitmap { private: struct FileHeader { char header[2]{ 'B', 'M' }; int32_t fileSize; int32_t reserved{ 0 }; int32_t dataOffset; }; private: struct InfoHeader { int32_t headerSize{ 40 }; int32_t width; int32_t height; int16_t planes{ 1 }; int16_t bitsPerPixel{ 24 }; int32_t compression{ 0 }; int32_t dataSize{ 0 }; int32_t horizontalResolution{ 2400 }; int32_t verticalResolution{ 2400 }; int32_t colors{ 0 }; int32_t importantColors{ 0 }; }; private: int data_size{ 0 }; int width{ 0 }; int height{ 0 }; unique_ptr<uint8_t[]> pPixels{ nullptr }; public: Bitmap(int width, int height); virtual ~Bitmap(); public: void fillBitmap(uint8_t, uint8_t, uint8_t); void setPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue); bool write(string filename); }; #pragma pack(pop) using namespace std; Bitmap::Bitmap(int width, int height) : data_size(width*height*3), width(width), height(height), pPixels( new uint8_t[data_size] { } ) {} // end Bitmap(int,int) Bitmap::~Bitmap() {} bool Bitmap::write(string filename) { FileHeader fileHeader; InfoHeader infoHeader; fileHeader.fileSize = sizeof(FileHeader) + sizeof(InfoHeader) + data_size; fileHeader.dataOffset = sizeof(FileHeader) + sizeof(InfoHeader); infoHeader.width = width; infoHeader.height = height; ofstream file; file.open(filename, ios::out | ios::binary); if (!file) return false; file.write((char*)&fileHeader, sizeof(fileHeader)); file.write((char*)&infoHeader, sizeof(infoHeader)); file.write((char*)pPixels.get(), data_size); file.close(); if (!file) return false; return true; } void Bitmap::fillBitmap(uint8_t red, uint8_t green, uint8_t blue) { uint8_t* pPixel = nullptr; for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { pPixel = pPixels.get() + (y * 3) * width + (x * 3); pPixel[2] = red; pPixel[1] = green; pPixel[0] = blue; }; // for x }; // fillBitmap() void Bitmap::setPixel ( int x, int y, uint8_t red, uint8_t green, uint8_t blue ) { uint8_t* pPixel = pPixels.get(); pPixel += (y * 3) * width + (x * 3); pPixel[0] = blue; pPixel[1] = green; pPixel[2] = red; return; }; // setPixel() Esse programa por exemplo gera dois bitmaps e pode ver que comparar não é complexo: basta endereçar os pixels como está em setPixel() int main(int argc, char** argv) { Bitmap bitmap(800, 600); bitmap.write("test.bmp"); bitmap.fillBitmap(128, 128, 128); bitmap.write("test128.bmp"); cout << "Finished." << endl; return 0; } // main() -
C Como abrir os pixels de uma imagem e comparar com outra
arfneto respondeu ao tópico de Mayrinck Bernardo em C/C#/C++
Algo assim? Como vai comparar se não salvou? Mesmo que esteja na memória tem que estar em algum formato... -
C Como abrir os pixels de uma imagem e comparar com outra
arfneto respondeu ao tópico de Mayrinck Bernardo em C/C#/C++
Eu sei que já perguntei isso, mas em que formato vai gravar essas imagens? Você não vai ter controle sobre o jogo então precisa antes de tudo encontrar a janela do jogo na tela. Como tem interesse em imagens de certo modo estáticas é bem mais simples. Nesse caso que descreveu apenas tem interesse em um painel estático. É muito diferente de acompanhar a tela como seria o caso de buscar um sprite ou ou um personagem em movimento. Apenas precisa identificar a janela e a partir dela identificar onde está esse painel e ir atrás das cores. Isso vai se resumir a buscar as informações de cor para um certo pedaço da janela. A cor em geral é codificada como 4 bytes de cor para cada pixel. Um formato comum é o chamado RGBA onde você tem os valores para vermelho, verde, azul e um " canal alpha" que é um canal de transparência. -
Estou imaginando que está lendo tudo que eu escrevo. Mas não me perguntou nada. Deu uma olhada naquele documento sobre o formato csv? Entendeu o primeiro post quando te falei que poderia usar qualquer programa para importar seus dados de entrada ou de saida se estivessem no formato correto? E assim usar o trabalho dos outros para testar o seu programa... Entendeu o que está errado no enunciado? Escrevi um pequeno programa para ler o seu gdp.csv para você entender o que eu quero dizer por escrever uma parte a cada vez. A saida do programa deve ser um csv bem formado, ainda sem aquela bobagem do N. Essa é a primeira fase do enunciado, o pre-processamento. veja as primeiras linhas que o programa mostra na tela veja o arquivo de saida importado pelo Sheets Isso quer dizer que o formato está ok, os dados iniciais foram extraídos do primeiro arquivo veja o programa de teste #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> struct registro_saida { char* Pais; char* GDP; char* LS; }; typedef struct registro_saida OutRec; int main(int argc, char* argv) { // para scanf() char* mascara = "%[^;]%c%[^;]%c%[^;]%c%[^;]%c%[^;]%c%s%c"; // o GDP.csv char* GDP_file_name = "gdp.csv"; FILE* GDP_file; char grade[8][80]; char delim1 = '?'; int n = 0; // para a saida char* CSV_output_file_name = "saida.csv"; FILE* CSV_out; char* header_csv = "Pais;GDP;Life Satisfaction\r"; OutRec* p = (OutRec*)malloc(sizeof(OutRec)); GDP_file = fopen(GDP_file_name, "r"); // trata o header if (GDP_file == NULL) { printf("nao abriu %s\n", GDP_file_name); perror("Erro:"); return -1; } else { printf("abriu %s\n", GDP_file_name); }; // if() n = fscanf(GDP_file, mascara, &grade[0][0], &delim1, &grade[1][0], &delim1, &grade[2][0], &delim1, &grade[3][0], &delim1, &grade[4][0], &delim1, &grade[5][0], &delim1 ); printf("fscanf() retornou %d. Esperados 12\n", n); if (n != 12) exit(-1); printf("Eis os campos do CSV\n"); for (int i = 0; i < (n / 2); i += 1) printf("Campo %d: [%s]\n", i, &grade[i][0]); // // agora le a entrada e cria uma struct para cada linha // e por enquanto vai gravando no csv de saida so pra // ver se o mecanismo esta ok // CSV_out = fopen(CSV_output_file_name, "w"); if (CSV_out == NULL) { printf("nao abriu %s\n", CSV_output_file_name); perror("Erro:"); return -1; }; // if() printf("abriu %s\n", CSV_output_file_name); fwrite(header_csv, strlen(header_csv), 1, CSV_out); char* LS_dummy = "A Calcular"; int rec = 0; while (!feof(GDP_file)) { n = fscanf(GDP_file, mascara, &grade[0][0], &delim1, // pais &grade[1][0], &delim1, &grade[2][0], &delim1, &grade[3][0], &delim1, &grade[4][0], &delim1, &grade[5][0], &delim1 // GDP ); if (n != 12) break; printf("Eis os campos do CSV\n"); for (int i = 0; i < (n / 2); i += 1) printf("Campo %d: [%s]\n", i, &grade[i][0]); rec += 1; printf("Registro %d: fscanf() retornou %d. Esperados 12\n", rec, n); p->Pais = (char*) malloc( strlen(&grade[0][0]) + 1); strcpy(p->Pais, &grade[0][0]); p->GDP = (char*) malloc( strlen(&grade[5][0]) + 1); strcpy(p->GDP, &grade[5][0]); p->LS = (char*) malloc(strlen(LS_dummy) + 1); strcpy(p->LS, LS_dummy); fprintf(CSV_out, "%s;%s;%s\n", p->Pais, p->GDP, p->LS); free(p->Pais); free(p->GDP); free(p->LS); }; // while() printf("\nGRAVADOS %d registros\n", rec); free(p); fclose(GDP_file); fclose(CSV_out); return 0; }; // main() // https://www.clubedohardware.com.br/forums/topic/ // 1422433-manipula%C3%A7%C3%A3o-de-arquivos-csv/? // tab=comments#comment-7683079 Atente para a formatação do arquivo de saída por exemplo char* header_csv = "Pais;GDP;Life Satisfaction\r"; Esse é o header do arquivo de saída. Depois disso o programa lê a entrada e prepara as estruturas seguindo esse formato. O arquivo CSV é uma tabela (X,Y) então o scanf() pode ler todas os campos do registro de uma vez, TODA VEZ. scanf() foi feita para isso: Scan Formatted Fields e quando scanf() foi escrita o formato CSV já existia Esse scanf() n = fscanf(GDP_file, mascara, &grade[0][0], &delim1, &grade[1][0], &delim1, &grade[2][0], &delim1, &grade[3][0], &delim1, &grade[4][0], &delim1, &grade[5][0], &delim1 ); printf("fscanf() retornou %d. Esperados 12\n", n); le a linha todinha. Essa é a máscara: char* mascara = "%[^;]%c%[^;]%c%[^;]%c%[^;]%c%[^;]%c%s%c"; Pense bem e vai entender que é a mesma coisa que você fez, só que mais segura e curtinha. E entenda porque há uma razão séria para scanf() retornar o número de itens lidos. E deve ser um problema sério a gente nunca ver aqui nos programas esse valor sendo usado... Numa primeira fase a struct de saída pode ser só isso: struct registro_saida { char* Pais; char* GDP; char* LS; }; typedef struct registro_saida OutRec; Veja o código para extrair os dados while (!feof(GDP_file)) { n = fscanf(GDP_file, mascara, &grade[0][0], &delim1, // pais &grade[1][0], &delim1, &grade[2][0], &delim1, &grade[3][0], &delim1, &grade[4][0], &delim1, &grade[5][0], &delim1 // GDP ); Veja a declaração char grade[8][80]; Vai ler seis campos de até 80 caracteres. E aí o programa aloca as strings na struct{} no tamanho certinho. Muito mais fácil. Sugiro ler, testar, e talvez perguntar algo. Veja se ajuda em alguma coisa e se consegue imaginar o próximo passo...
-
sim. parece longe de funcionar ainda vou te mandar um outro exemplo
-
Acho melhor checar os parâmetros para scanf() por exemplo. E os valores de retorno. Nenhum destes será um csv, como já expliquei. Mas é possível, claro. Não se esqueca dos headers!
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