Jump to content

fredericopissarra

Membros
  • Content Count

    327
  • Joined

  • Last visited

  • Country

    Brazil

Everything posted by fredericopissarra

  1. PS: O autor desabilitou conversas em privado no Discord...
  2. O autor pode ser encontrado no Discord do Mente Binária... ele costuma escrever pra caramba por lá (chega a ser chato!)... 🤣 Quanto ao seguir o material... acho que dá. Como qualquer material, é necessário cautela!
  3. Voltemos às aulas da Tia Jandira, lá no ensino fundamental... Como é que conseguíamos subtrair 7 de 3 na subtração 33 - 17? Você "pega emprestado" 1 do 3 e faz 13-7 = 6... e na próxima posição o 3 torna-se 2 porque você "pegou 1 emprestado" e teremos 2 - 1 = 1 e, portanto o resultado e 16, não é? Esse "pega emprestado" é o borrow (literalmente, em inglês, "empréstimo"). Aliás, em binário: 0 - 0 = 0 (e o borrow [carry] = 0). PS: E sim... o lance do Borrow ser complementar ao Carry está errado, basta ver a tabela verdade das duas operações com relação aos Carry e Borrow. No texto, o imbecil do autor enfiou os pés pelas mãos ao afirmar isso... Merece um esporro! O que o autor quis dizer com complementação do carry e borrow é em relação às operações de soma e adição... No exemplo, 1 - 1 resulta em borrow zerado (não há "pegação de empréstimo"), mas na operação 1 + (-1) há o "vai um" (porque -1, em complemento 2 é ele mesmo - se usarmos apenas 1 bit)... Numa operação com mais de um bit (8, por exemplo), -1 = 0b11111111, o que causará o mesmo efeito. É apenas uma informação útil... Para entender "carry" e "borrow" basta lembrar como se faz em decimal com os "vai uns" (carry" e "pega 1" (borrow), em cada algarismo de uma operação (adição e subtração, respectivamente).
  4. PS: Você deve estar pensando: "Ahhh... mas aqui funciona!"... Eu usei "provavelmente" e "pode" em vários lugares do texto... Em alguns ambientes que seguem a SysV ABI isso ai não funciona (acho que é o caso do FreeBSD e do MacOS, por exemplo). Mas, isso aqui PODE funcionar: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> int main( void ) { int x; static unsigned char shcodep[] = "\x31\xc0" // xor eax,eax "\xc3"; // ret int (*f)(void); // FIXME: PODE ser que funcione! // Cria página com NX desligado, privada ao processo com permissão de leitura/escrita. f = mmap( NULL, sizeof shcodep, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 ); if ( (ssize_t)f == -1 ) { perror( "mmap" ); return EXIT_FAILURE; } // Copia o "código" para a página alocada. memcpy( f, shcodep, sizeof shcodep ); x = f(); // chama... munmap( f, sizeof shcodep ); printf( "%d\n", x ); return EXIT_SUCCESS; }
  5. Quanto a dúvida: A diferença é que o operador () de C realizará um CALL... No contexto acima, tanto o JMP quanto um CALL deixarão de fazer o housekeeping necessário para destruir objetos e outras coisas necessárias da libc... Desconsiderando isso, TANTO FAZ fazer um JMP ou um CALL, NESTE CASO.
  6. Isso, provavelmente, não funcionará, ou, pelo menos, não funcionará em qualquer "box" linux... Em primeiro lugar, os "segmentos" de dados, num sistema paginado, pode definir as páginas com o bit NX ligdo (NX de Non eXecutable). Isso costuma ser particularmente verdade, inclusive, para a pilha. Daí, simplesmente definir um ponteiro de função apontando para a sequência de bytes que definem as instruções simplesmente causará um segmentation fault na maioria dos "boxes" com kernels modernos. Em segundo lugar, o uso da "int 0x80", embora também exista em sistemas amd64 (x86-64), geralmente causam problemas (especialmente com uso de ponteiros). A coisa complica se quiser criar um "shellcode" no modo amd64 (x86-64), onde referências à memória costumam ser relativas ao RIP. O que se pode fazer com relação ao primeiro caso é alocar as páginas "executáveis" (com o bit NX desligado) usando as system calls mmap() e mprotect() [ativando o flag PROT_EXEC] - mesmo assim, dependendo da versão do kernel, existem proteções para esse tipo de tentativa... Depois, copia-se o conteúdo do "shellcode" para dentro dessas páginas. Daí salta-se para elas.
  7. Se isso não é um trabalho escolar, considere usar libcsv: https://github.com/rgamble/libcsv
  8. Uma última dica: Leia o volume 3 do "The Art of Computer Programming" de Donald E. Knuth. Lá você encontrará algoritmos para external sorting...
  9. O external sorting eu deixo por sua conta... Mas, eis um exemplo com letras. Suponha que tenhamos 3 arquivos ordenados: 1: ADFGS 2: HJKLQ 3: IOP Abre-se o arquivo 1 e 2 e determina-se que A < H, salva 'A' no arquivo 4, tirando-o do arquivo 1: 1: DFGS 2: HJKLQ 3: IOP 4: A Mesma coisa para o arquivo 1 e 3, e determina-se que 'D' < 'I': 1: FGS 2: HJKLQ 3: IOP 4: AD Repete-se os procedimentos acima (para 1 e 2; e 1 e 3), até que os 3 arquivos estejam vazios. No final, o arquivo 4 será o arquivo ordenado. PS: O motivo de eu ter sugerido N arquivos de 2048 registros cada é para usar a memória de maneira conveniente... 2048 registros, como eu disse, ocuparão 128 KiB de RAM. Se todos os registros de seu "banco de dados" couberem na memória, não há necessidade de um external sorting. PS2: Repare que o procedimento pode ser um cadinho mais complicado do que citei acima... imagine que o arquivo 1 fique sem registros, daí a comparação terá que ser entre os arquivos 2 e 3. De fato, as comparações deveriam ser feitas entre 1 e 2; 1 e 3 e 2 e 3, para selecionar a "menor chave"... Com N arquivos, teremos uma "combinção" de N, 2 a 2, que pode ser bem grande!
  10. Mesmo com código incompleto, existem diversos problemas aqui: system("cls"); // NÃO é recomendado! Ao invés disso você poderia usar uma função que apague a tela. Eis uma que disponibilizo em meu artigo Pare de usar system() nos seus códigos!. Como plus, vai um gotoxy() também... Outro problema é o uso da função getche() - que não existe na biblioteca padrão! Use getchar(). Quanto á ordenação. Neste código ela é problemática sob o ponto de vista de performance, uma vez que você não mantém nenhum "arquivo de índices" (com uma árvore balanceada contendo a ordem já na inserção)... Assim, terá que recorrer a algum external sorting. Um jeito de fazer é determinar quantos registros há no seu arquivo: size_t getNumRecords( FILE *f ) { long oldpos, endpos; oldpos = ftell( f ); // guarda posição atual. fseek( f, 0, SEEK_END ); // pula para o fim do arquivo. endpos = ftell( f ); // pega tamanho do arquivo. fseek( f, oldpos, SEEK_SET ); // volta para a posição original. // Retorna o número de registros no arquivo. return endpos / sizeof( struct pecas ); } De posse desse valor, você pode fazer ordenações rápidas de partições do arquivo... Por exemplo, partições de 2048 registros (isso precisa de um buffer de cerca de 128 KiB apenas, devido ao tamanho da sua estrutura), criando (recs / 2048) arquivos diferentes. A cada 2048 registros do arquivo original você os ordena, na memória, e salva os registros em cada um desses arquivos. De posse desses arquivos, você abre cada um deles, selecionando a "menor chave" que achar em todos e escreve o registro correspondente num arquivo final (eliminando esse registro do arquivo onde o obteve) - Esse é o princípio do merge external sorting... No fim das contas, seu arquivo final estará ordenado. PS: Para ordenar um grupo de N registros (ou menos) usando quicksort: static int cmp( const void *ptr1, const void *ptr2 ) { // OBS: Se desejar um "natural sorting" isso fica mais complexo! return strcmp( ((struct pecas *)ptr1)->nome, ((struct pecas *)ptr2)->nome ); } void sort( struct pecas *ptr, size_t count ) { qsort( ptr, count, sizeof *ptr, sort ); } PS2: Existem meios de fazer a mágica com apenas 3 arquivos intermediários, mas dará bem mais trabalho... Anyway... eu recomendo que você use algum "banco de dados" não relacional como o gdbm, por exemplo...
  11. PS: Huffman Encoding, LZW e DEFLATE (zlib) não são algoritmos para texto, mas para blocos binários. Os dois primeiros são usados em quase todos os utilitários de compressão existentes. Artigo sobre Huffman Encoding, que escrevi em janeiro de 2016, usando um texto como exemplo (mas pode ser um bloco binário): https://is.gd/1CUorF
  12. #include <stdlib.h> #include <limits.h> /* Troque MASK por 1 se quiser a ordem LSB para MSB. */ #define MASK ( 1 << CHAR_BITS - 1 ) /* Monta string com os bits de 'byte', no buffer apontado por 'ptr' O buffer deve ter CHAR_BITS ou mais chars... Exemplo de chamada: char s[CHAR_BITS+1]; bin2str( 0x55, s ); printf( "%s\n", s ); */ void bin2str( unsigned char byte, char *ptr ) { // Um 'char' pode ter mais que 8 bits (portabilidade)! size_t count = CHAR_BITS; while ( count-- ) { *ptr++ = !!( byte & MASK ) + '0'; byte >>= 1; } *ptr = 0; // marca fim da string. }
  13. Ahhhh... sim... outro ERRO (embora a Microsoft pareça flexível com relação a isso) é usar "Portuguese" no setlocale()... A própria documentação da MS diz que o correto é obedecer as ISO 639 e 3166. Ou seja: setlocale( LC_ALL, "pt_BR.UTF-8" ); // linux setlocale( LC_ALL, "pt_BR.1252" ); // windows (code-page: WINDOWS-1252). Referência: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=vs-2019 https://docs.microsoft.com/en-us/cpp/c-runtime-library/locale-names-languages-and-country-region-strings?view=vs-2019 PS: Isso parece ser irrelevante aqui, já que o código não usa nenhuma função da libc que necessite de locale...
  14. Nope... UMA string, como há o termino com " o início é assumido como "... Eu entendi que a rotina é ad hoc... Estou sendo apenas chato aqui! hehehe... Concordo que o uso de strtok() pode ser problemático. Mas, normalmente, não gosto muito de usar fgets() porque ele exige um buffer de tamanho conhecido... Suponha que você defina um buffer de 256 characteres e sua linha tenha 512, como fica? Para isso, prefiro a função (POSIX) getline(), que permite alocação dinâmica: char *buffer, *p; size_t size; // Prepara-se para a primeira alocação na leitura... buffer = NULL; size = 0; while ( getline( &buffer, &size, fp ) >= 0 ) { // Estirpa '\n' final. if ( p = strchr( buffer, '\n' ) ) *p = '\0'; /* ... */ // Livra-se do buffer, preparando para uma nova alocação. free( buffer ); buffer = NULL; size = 0; } Existem outras "micro-otimizações" que eu faria no código como, por exemplo, livrar-se da abundância de operadores [], substituíndo-os por uso de ponteiros, mas é só chatice minha mesmo... []s Fred
  15. Sinto dizer-lhes, mas esse parser está completamente errado... Por exemplo, a linha: fred, o bom",10,3.14 Mesmo sem o " inicial, é perfeitamente válida e com apenas 3 itens (uma string e dois valores numéricos)... E ainda existem outras construções que o código não contempla... Recomendo estudar o que deve ser feito antes de tentar fazer... Referência sobre CSV: https://tools.ietf.org/html/rfc4180
  16. Além do detalhe apontado por @mandelacruz, você declarou 'dados' como 'int' na estrutura TLDE, o que fará um 'float' ser convertido para 'int' (se possível)...
  17. Não... Se espera ajuda num forum, deve ser público.
  18. Sem ver o código é meio difícil...
  19. Sabe porquê a base numérica hexadecimal é usada em computadores?
  20. Quais são as características básicas que você citou?
  21. É meio difícil criar um algoritmo de compactação, e existem aos montes por ai: Huffman Encoding, zlib, Lempel-Zif-Welch, etc... Mas é tremendamente mais fácil criar rotinas que leiam um bitstream. Tenho lá minhas dúvidas sobre o que o Kleber tenha feito... Mesmo assim, tenho por política ajudar alguém que também ajuda os outros... Se o algoritmo é milagroso ou inovador, quero vê-lo antes... Curiosidade profissional.
  22. Como o Vinicius disse ai em cima, um "construtor" é uma função-membro que "contrói" (ou "inicializa") a "instância" (o objeto da classe)... Um exemplo de "contrutor" para uma classe (e objeto) simples: Imagine que tenhamos isso: // Usando 'struct' aqui, ao invés de 'class' pq é mais simples... struct X { int a; }; Isso é uma "classe", trata-se apenas da declaração da estrutura. Ainda nao existe um "objeto"... Ao fazer: // Criamos um "objeto" da classe X, identificando-o por x. X x; O que acontecerá se fizermos, em algum lugar: std::cout << x.a << std::endl; Provavelmente obteremos "lixo"... mas, ao ser "contruído" o objeto identificado por x da classe X podemos ter uma função membro contrutora que inicializará o objeto com um valor conhecido. Por exemplo: struct X { int a; X(); }; X::X() { a = 1; } Assim, sempre que for construída uma "instância" de X (um objeto da classe), 'a', daquele objeto, será inicializado com 1.
  23. C++ permite criar identificadores (nomes de variáveis, funções, etc) em namespaces diferentes. Por exemplo: namespace fred { int a; }; namespace nicaranha { int a; }; Aqui, a variável 'a', do tipo 'int', no namespace 'fred' (ou fred::a) é diferente de 'a' no namespace 'nicaranha' (ou nicaranha::a). :: é o operador de resolução de escopo. As bibliotecas padrão de C++ (libstdc++) definem o namespace std (de "standard"). No caso, o identificador 'string' é definido no namespace std, bem como o identificador 'cout' e 'endl'. Então você tem que especificá-los com o 'std::' na frente. A não ser que, no início do código coloque o que vai abaixo e daí pode omitir a resolução de escopo... using namespace std;
×
×
  • Create New...