Jump to content

thoga31

Staff
  • Posts

    6,712
  • Joined

thoga31's Achievements

unsigned user

unsigned user (4/5)

  • 10 Years
  • 1 Year
  • Author Bronze
  • Author Silver
  • Voter Bronze

Recent Badges

598

Reputation

26

Community Answers

  1. A Embarcadero tem estado com problemas nos seus servidores desde 17 de janeiro. É possível que essa versão ainda estivesse a ser afectada quando publicaste este tópico, apesar de a maioria ter sido reposta (segundo actualizado pela Embarcadero no dia 7).
  2. O desenvolvimento é feito por empresas selecionadas em concursos públicos. (exemplo no base.gov.pt).
  3. Podes-nos mostrar o que já tens feito até ao momento? Quais são as dúvidas específicas que gostarias de ver esclarecidas?
  4. No título dizes que precisas de "ajuda", mas no tópico pedes que te "mandem um exemplo" de uma calculadora, e já agora "mais bonita". Cortando os meandros, esse é um trabalho que tens de entregar até quando? Mostra-nos o que já fizeste até ao momento para podermos ter um ponto de partida para ajudar. Tens um ponto de partida na Wiki.
  5. Muitas bibliotecas utilizam ANSI Escape Codes, cujo comportamento é muito dependente da plataforma. No Windows funciona com a PowerShell >= 5.1 (se não estou em erro) e em particular com o Windows Terminal. Talvez a biblioteca colorama se encaixe nas tuas necessidades, assumindo que não te é viável usar bibliotecas baseadas em AECs.
  6. O que era suposto acontecer e o que está a ocorrer? Sem algum nível de detalhe na dúvida não podemos ajudar.
  7. Quando dizes "fazer os inputs", referes-te a receber input do utilizador? A minha regra é sempre separar a lógica da interação com o utilizador. Se a classe Interface é a que tem os menus com a navegação para o utilizador, podes utilizá-la para obter os inputs do programa. Não uses as classes responsáveis pela lógica do programa para esse fim. Existem modelos de programação dedicados a este tema (por exemplo, MVC, Model-View-Controller). Recomendo vivamente fazer um estudo sobre o assunto quando puderes.
  8. Precisas para Windows, Linux, ou macOS?
  9. Entretanto consegui resolver 😄 Primeiro, defini duas interfaces: IAnsiCode = interface['{eeb511e3-0dbe-4fec-a72f-473f8bf8a8de}'] function AsString : string; function AsByte : byte; function WithColor(const color : byte) : IAnsiCode; overload; function WithColor(const r, g, b : byte) : IAnsiCode; overload; end; IAnsiColor = interface['{a9f9f329-e69f-436c-b17f-ee0b962c1486}'] function AsString : string; function ColorMode : TAnsiColorEnum; function AsColor : TAnsiColorRec; end; Como as cores podem sempre mudar, o que faço é modificar a vString do TAnsiCode com o método WithColor, o qual apenas se aplica caso seja um código válido: function TAnsiCode.WithColor(const r, g, b : byte) : IAnsiCode; overload; begin if self.vHasColor then with TAnsiColor.New(r, g, b) do self.vString := IntToStr(self.vCode) + ANSI_SEPARATOR + AsString; Result := self; end; A verificação é feita no construtor e é imutável após a alocação de recursos: constructor TAnsiCode.Create(const code : byte); begin self.vHasColor := code in VALID_ANSI_COLOR_CODES; self.WithCode(code); end; // onde: VALID_ANSI_COLOR_CODES : set of byte = [38, 48]; Teste: {$mode delphi} program test; uses escape; begin writeln( Ansify([BOLD, FG_RED], 'Fatality!'), ' An error has not occurred! :(' ); writeln( 'And here is a ', Ansify([ITALIC, FG(69)], 'Color Test, Standard'), '.' ); writeln( Ansify([UNDERLINE, BG(100, 50, 9), ITALIC], 'Color Test, RGB'), ', and also ', Ansify([UNDERLINE, FG(9, 100, 50), ITALIC], 'Color Test, RGB') ); end. Resultado: Bem haja @nunopicado 🙂 Depois investigarei o possível uso de outra alternativa que não um array dinâmico, agradeço a sugestão.
  10. Não sei o que fiz de diferente de quando tinha isso feito (tinha o New como indicaste, mas nem a primeira chamada ao Ansify funcionava), mas agora aparentemente está a funcionar. Surgiu-me, contudo, um outro problema: as cores 😄 Defini desta forma a classe de cores: TAnsiColor = class(TInterfacedObject, IAnsiCode) private vCode : byte; vString : string; vColor : TAnsiColorRec; function WithCode(const code : byte) : IAnsiCode; procedure Reset; public constructor Create(const code : byte); class function New(const code : byte) : IAnsiCode; function AsString : string; function AsByte : byte; function WithColor(const color : byte) : IAnsiCode; overload; function WithColor(const r, g, b : byte) : IAnsiCode; overload; function ColorMode : TAnsiColorEnum; function AsColor : TAnsiColorRec; end; Para usar as cores, estou a usar as funções e variáveis que se seguem: interface function FG(const color : byte) : IAnsiCode; overload; function FG(const r, g, b : byte) : IAnsiCode; overload; function BG(const color : byte) : IAnsiCode; overload; function BG(const r, g, b : byte) : IAnsiCode; overload; // ... implementation var _FG : IAnsiCode; _BG : IAnsiCode; function FG(const color : byte) : IAnsiCode; begin Result := TAnsiColor(_FG).WithColor(color); end; function FG(const r, g, b : byte) : IAnsiCode; begin Result := TAnsiColor(_FG).WithColor(r, g, b); end; function BG(const color : byte) : IAnsiCode; begin Result := TAnsiColor(_BG).WithColor(color); end; function BG(const r, g, b : byte) : IAnsiCode; begin Result := TAnsiColor(_BG).WithColor(r, g, b); end; // ... initialization _FG := TAnsiColor.New(38); _BG := TAnsiColor.New(48); A chamada é feita, conforme visto na primeira mensagem, desta forma: writeln( Ansify([ITALIC, FG(69)], 'Color Test, Standard') ); writeln( Ansify([UNDERLINE, BG(100, 50, 9)], 'Color Test, RGB') ); O compilador já me avisou que algo poderia correr mal nas funções FG e BG 😄 escape.pas(172,15) Warning: Class types "IAnsiCode" and "TAnsiColor" are not related escape.pas(178,15) Warning: Class types "IAnsiCode" and "TAnsiColor" are not related escape.pas(184,15) Warning: Class types "IAnsiCode" and "TAnsiColor" are not related escape.pas(190,15) Warning: Class types "IAnsiCode" and "TAnsiColor" are not related Ao executar, mais uma vez tenho Access Violation, mas desta vez entendo as possíveis causas. Contudo, estou sem ideias concretas de como posso fazer isto funcionar e continuar a ser minimamente simpático ao programador. P.S.: Depois analisarei a possibilidade de usar uma TCollection, uma TList e/ou enumeradores.
  11. Para quem usa Free Pascal, fica a dica do equivalente ao ReportMemoryLeaksOnShutdown: {$mode delphi} program test; uses escape, heaptrc; // <-- módulo necessário ao FPC e Lazarus begin writeln( Ansify([BOLD, FG_RED], 'Fatality!') ); writeln( Ansify([ITALIC], 'Color Test, Standard') ); writeln( Ansify([BOLD, BG(100, 50, 9)], 'Color Test, RGB') ); DumpHeap; // <-- Mostra a heap no final do programa end. Este foi o resultado: An unhandled exception occurred at $00000000004272CC: EAccessViolation: Access violation $00000000004272CC $000000000042439F $0000000000401135 Heap dump by heaptrc unit of /home/user/dev/Escape/delphi/teste.bin 5 memory blocks allocated : 277/288 2 memory blocks freed : 85/96 3 unfreed memory blocks : 192 True heap size : 458752 (12640 used in System startup) True free heap : 445248 Should be : 445344 Call trace for block $00007FACE4135100 size 128 $00000000004141E1 $000000000042439F $0000000000401135 Call trace for block $00007FACE415D600 size 40 $00000000004141E1 $000000000042439F $0000000000401135 Call trace for block $00007FACE415D500 size 24 $000000000042439F $0000000000401135 Tenho aqui uns memory leaks a resolver 😄
  12. Sim! Na segunda linha, por exemplo, não usei nada da primeira, e crashou logo no ITALIC. Todos os objectos desaparecem 😕
  13. Mas todos os objectos que implementam aquela interface são libertados da memória em simultâneo? O facto de eles serem libertados aquando do array dinâmico faz todo o sentido, mas está-me a escapar o facto de irem todos de vela 😄
  14. Caríssimos, decidi desenferrujar algumas linguagens nas quais não tive a chance de pegar há muito. Chegou a hora do Delphi / Object Pascal. Ora bem, estou a fazer uma pequena biblioteca que me permite aplicar ANSI escape codes (AECs) no output, e tenho uma situação muito peculiar. De notar, estou a usar o Free Pascal 3.2.2. Indo directo ao problema: writeln( Ansify([BOLD, FG_RED], 'Fatality!') ); writeln( Ansify([ITALIC, FG(69)], 'Color Test, Standard') ); writeln( Ansify([UNDERLINE, BG(100, 50, 9)], 'Color Test, RGB') ); Quando executo este código de teste, a primeira chamada a Ansify funciona sem problemas. Contudo, a segunda chamada, independentemente do array que passo no primeiro argumento, dispara um Access Violation: \x[1;31mFatality!\x[0m An unhandled exception occurred at $00000000004124CA: EAccessViolation: Access violation $00000000004124CA $00000000004243FC $00000000004011AB Nota: forcei o output dos AECs para debugging durante o desevolvimento. Esta é a definição de Ansify: function Ansify(const codes : array of IAnsiCode; const msg : string) : string; begin Result := Codify(codes) + msg + Codify([RESET]); end; Onde: function Codify(const codes : array of IAnsiCode) : string; var code : IAnsiCode; begin Result := '\x['; // Result := ANSI_BEGIN; // TODO: switch when finishing first version for code in codes do begin Result += code.AsString; Result += ANSI_SEPARATOR; end; Delete(Result, Length(Result), 1); Result += ANSI_END; end; A ideia é ter IAnsiCode como uma interface comum a duas classes que implementam AECs, mas que apenas obriga ao mínimo: IAnsiCode = interface['{eeb511e3-0dbe-4fec-a72f-473f8bf8a8de}'] function AsString : string; function AsByte : byte; end; Não estou a usar uma class function construtora que permita gerir automaticamente a libertação de recursos uma vez que posso precisar de qualquer código a qualquer momento por N vezes num programa, pelo que estou a alocar os objectos na inicialização do módulo e a "destruí-los" na finalização: initialization RESET := TAnsiCode.Create(0); BOLD := TAnsiCode.Create(1); FAINT := TAnsiCode.Create(2); // etc... Aparentemente os objectos parecem ser todos destruídos após a primeira chamada a Ansify, tenham sido ou não usados na primeira chamada. A classe TAnsiCode está definida da seguinte forma: TAnsiCode = class(TInterfacedObject, IAnsiCode) private vCode : byte; vString : string; function WithCode(const code : byte) : IAnsiCode; public constructor Create(const code : byte); function AsString : string; function AsByte : byte; end; A minha questão é simples: Por quê Access Violation? Para onde foram os objectos todos? 😄 Cumprimentos.
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.