BrunoJunior Posted April 9, 2024 at 09:30 AM Report Share #632984 Posted April 9, 2024 at 09:30 AM Sempre que seleciono a sobremesa número 1, em vez de aparecer apenas a frase "Iremos trazer agora o seu arroz doce então.", ela entra em conflito com a número 4 aparecendo tanto a frase da 1 como a da 4, porém todas as outras funcionam perfeitamente, incluindo que se eu escolher a 4 nenhum erro ocorre. Encontrei a solução de trabalhar com variáveis Char em vez de Real, mas queria entender o que causa este conflito Uses Crt; Const Sopa_Legumes = 2; Camarao = 8; Enchidos = 7; Pao_Alho = 3; Creme_Marisco = 4; Salada = 3; Pasteis_Bacalhau = 3.50; IceTea = 1.50; Coca_Cola = 1.50; Cerveja = 2; Agua = 1; Cha = 1.50; Vinho_Rose = 7; Whisky_Velho = 13; Nenhuma_Bebida = 0; Bitoque = 10; Carne_Alentejana = 15; Francesinha = 13; Peito_Frango = 10; Filete_Robalo = 13; Ameijoa = 11; Bacalhau_Espiritual = 12; Bacalhau_Natas = 12; Arroz_Doce = 3; Leite_Creme = 2.50; Bolo_Bolacha = 4; Doce_Casa = 3; Cafe = 1.20; Gelado = 1.30; Nenhuma_Sobremesa = 0; Pedidos = 0; Var Cliente_1, Cliente_2, Cliente_3, Cliente_4, Cliente_5: String; Num_Pedidos: Integer; Registro_Conta_1, Registro_Conta_2, Registro_Conta_3, Registro_Conta_4, Registro_Conta_5: Real; Quer_Entrada_1, Quer_Entrada_2, Quer_Entrada_3, Quer_Entrada_4, Quer_Entrada_5, Quer_Sobremesa_1, Quer_Sobremesa_2, Quer_Sobremesa_3, Quer_Sobremesa_4, Quer_Sobremesa_5: Integer; Pedidos_Entrada, Pedidos_Sobremesa: Integer; Entrada_1, Entrada_2, Entrada_3, Entrada_4, Entrada_5: Real; Prato_Principal_1, Prato_Principal_2, Prato_Principal_3, Prato_Principal_4, Prato_Principal_5: Real; Sobremesa_1, Sobremesa_2, Sobremesa_3,Sobremesa_4, Sobremesa_5: Real; Bebida_1, Bebida_2, Bebida_3, Bebida_4, Bebida_5: Real; Avaliacao_1, Avaliacao_2, Avaliacao_3, Avaliacao_4, Avaliacao_5: Real; Begin WriteLn('Espero que tudo tenha estado do seu agrado :)'); WriteLn; WriteLn('Iremos agora mostrar as sobremesas.'); WriteLn; WriteLn('======================'); WriteLn('MENU DO RESTAURANTE'); WriteLn('======================'); WriteLn; WriteLn('SOBREMESAS'); WriteLn; WriteLn('(1) Arroz Doce- 3$'); WriteLn; WriteLn('(2) Leite Creme- 2,50$'); WriteLn; WriteLn('(3) Bolo de Bolacha- 4$'); WriteLn; WriteLn('(4) Doce da Casa(Serradura)- 3$'); WriteLn; WriteLn('(5) Café- 1,20$'); WriteLn; WriteLn('(6) Gelado- 1.30$'); WriteLn; WriteLn; Write('Deseja uma sobremesa? (1=Y/2=N) '); Read(Quer_Sobremesa_1); WriteLn; WriteLn; If(Quer_Sobremesa_1 = 1) Then Begin Write('Que sobremesa deseja? '); Read(Sobremesa_1); If(Sobremesa_1 = 1) Then Begin Sobremesa_1 := Sobremesa_1 + Arroz_Doce; WriteLn; WriteLn('Iremos trazer agora o seu arroz doce então.'); End; If(Sobremesa_1 = 2) Then Begin Sobremesa_1 := Sobremesa_1 + Leite_Creme; WriteLn; WriteLn('Iremos trazer agora o seu leite creme então.'); End; If(Sobremesa_1 = 3) Then Begin Sobremesa_1 := Sobremesa_1 + Bolo_Bolacha; WriteLn; WriteLn('Iremos trazer agora o seu bolo de bolacha então.'); End; If(Sobremesa_1 = 4) Then Begin Sobremesa_1 := Sobremesa_1 + Doce_Casa; WriteLn; WriteLn('Iremos trazer agora o doce da casa então.'); End; If(Sobremesa_1 = 5) Then Begin Sobremesa_1 := Sobremesa_1 + Cafe; WriteLn; WriteLn('Iremos trazer agora o seu café então.'); End; If(Sobremesa_1 = 6) Then Begin Sobremesa_1 := Sobremesa_1 + Gelado; WriteLn; WriteLn('Iremos trazer agora o seu gelado então.'); End; End; End. BrunoJnr. Link to comment Share on other sites More sharing options...
iznougudpt Posted April 9, 2024 at 01:08 PM Report Share #632986 Posted April 9, 2024 at 01:08 PM Em 09/04/2024 às 10:30, BrunoJunior disse: If(Sobremesa_1 = 1) Then Begin Sobremesa_1 := Sobremesa_1 + Arroz_Doce; WriteLn; WriteLn('Iremos trazer agora o seu arroz doce então.'); End; Sobremesa_1 começa com valor 1, mas depois somas o valor do arroz doce logo Sobremesa_1 = 4. Como usas IF sem condição ELSE, quanto termina de processar o valor 1 vai entrar no if do valor 4 porque entretanto Sobremesa_1 passou a 4. 1 Report Link to comment Share on other sites More sharing options...
Solution nunopicado Posted April 9, 2024 at 03:24 PM Solution Report Share #632988 Posted April 9, 2024 at 03:24 PM O que respondeu o @iznougudpt está corretíssimo. É esse o problema deste código específico. No entanto quero ir um pouco mais a fundo no caso, pois parece-me que há aí um problema de raciocínio que deve ser corrigido. O que estás a fazer, e que causou o problema descrito, é a usar a mesma variável que serve para ler a opção, para acumular o preço. E pior, estás a somar o preço à opção, o que claro, vai dar um preço errado. Obviamente estás a começar, e este tipo de problema todos por lá passámos. Mas é mesmo por isso que é importante corrigir já, antes que se instituam maus hábitos. Os computadores atuais têm muitos recursos. A sério, mesmo muitos. No contexto de um programa deste tipo, os recursos de um computador atual são virtualmente infinitos. E antigamente, quando os computadores eram infinitamente mais limitados, já aí a regra era não reaproveitar variáveis. Isto é importante, pelo que vou repetir: Nunca deves reaproveitar uma variável. Quando crias uma variável, ela deve ter um, e um só objetivo. Se é para a opção do menu, é para a opção do menu. Se é para o preço, é para o preço. Não interessa para que é, mas a partir do momento que é para uma coisa, é só para essa coisa. Cria quantas variáveis a tua imaginação ditar, o computador aguenta. Neste caso concreto, se a variável sobremesa_1 fosse usada apenas para ler a opção, nunca terias problemas, independentemente de usar um else ou não. Cria uma nova variável para o preço a pagar, inicializa-a a 0, e dentro do IF, somas o preço do arroz doce (ou do que for) a essa variável, e não à Sobremesa_1. Tens o problema resolvido. --------------------- Bónus: Corrigindo a situação das variáveis, o teu código vai funcionar, mas não é um código optimizado. Como eu dizia, os computadores têm recursos quasi-infinitos, mas o nosso código deve sempre procurar ser o mais optimizado possível. Em vez de IFs, substitui por um CASE ... OF. Ficaria algo como isto: ... case Sobremesa_1 of 1: Begin Total := Total + Arroz_Doce; WriteLn; WriteLn('Iremos trazer agora o seu arroz doce então.'); End; 2: Begin Total := Total + Leite_Creme; WriteLn; WriteLn('Iremos trazer agora o seu leite creme então.'); End; 3: Begin Total := Total + Bolo_Bolacha; WriteLn; WriteLn('Iremos trazer agora o seu bolo de bolacha então.'); End; 4: Begin Total := Total + Doce_Casa; WriteLn; WriteLn('Iremos trazer agora o doce da casa então.'); End; 5: Begin Total := Total + Cafe; WriteLn; WriteLn('Iremos trazer agora o seu café então.'); End; 6: Begin Total := Total + Gelado; WriteLn; WriteLn('Iremos trazer agora o seu gelado então.'); End; else begin WriteLn; WriteLn('Opção inválida.'); end; end; Neste código, além de esteticamente mais apelativo e organizado, o compilador não precisa percorrer todas as opções, avaliando a cada uma se a opção é correta ou não. Entra no case, vai à opção cerca, e faz o que tem a fazer. E ainda ficas com a possibilidade de alertar o utilizador caso a opção escolhida não seja nenhuma das propostas, algo que de contrário precisarias de IFs encadeados para fazer, o que deixaria o código ainda mais frágil. 1 Report "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to comment Share on other sites More sharing options...
BrunoJunior Posted April 10, 2024 at 11:46 AM Author Report Share #632989 Posted April 10, 2024 at 11:46 AM Em 09/04/2024 às 16:24, nunopicado disse: O que respondeu o @iznougudpt está corretíssimo. É esse o problema deste código específico. No entanto quero ir um pouco mais a fundo no caso, pois parece-me que há aí um problema de raciocínio que deve ser corrigido. O que estás a fazer, e que causou o problema descrito, é a usar a mesma variável que serve para ler a opção, para acumular o preço. E pior, estás a somar o preço à opção, o que claro, vai dar um preço errado. Obviamente estás a começar, e este tipo de problema todos por lá passámos. Mas é mesmo por isso que é importante corrigir já, antes que se instituam maus hábitos. Os computadores atuais têm muitos recursos. A sério, mesmo muitos. No contexto de um programa deste tipo, os recursos de um computador atual são virtualmente infinitos. E antigamente, quando os computadores eram infinitamente mais limitados, já aí a regra era não reaproveitar variáveis. Isto é importante, pelo que vou repetir: Nunca deves reaproveitar uma variável. Quando crias uma variável, ela deve ter um, e um só objetivo. Se é para a opção do menu, é para a opção do menu. Se é para o preço, é para o preço. Não interessa para que é, mas a partir do momento que é para uma coisa, é só para essa coisa. Cria quantas variáveis a tua imaginação ditar, o computador aguenta. Neste caso concreto, se a variável sobremesa_1 fosse usada apenas para ler a opção, nunca terias problemas, independentemente de usar um else ou não. Cria uma nova variável para o preço a pagar, inicializa-a a 0, e dentro do IF, somas o preço do arroz doce (ou do que for) a essa variável, e não à Sobremesa_1. Tens o problema resolvido. --------------------- Bónus: Corrigindo a situação das variáveis, o teu código vai funcionar, mas não é um código optimizado. Como eu dizia, os computadores têm recursos quasi-infinitos, mas o nosso código deve sempre procurar ser o mais optimizado possível. Em vez de IFs, substitui por um CASE ... OF. Ficaria algo como isto: ... case Sobremesa_1 of 1: Begin Total := Total + Arroz_Doce; WriteLn; WriteLn('Iremos trazer agora o seu arroz doce então.'); End; 2: Begin Total := Total + Leite_Creme; WriteLn; WriteLn('Iremos trazer agora o seu leite creme então.'); End; 3: Begin Total := Total + Bolo_Bolacha; WriteLn; WriteLn('Iremos trazer agora o seu bolo de bolacha então.'); End; 4: Begin Total := Total + Doce_Casa; WriteLn; WriteLn('Iremos trazer agora o doce da casa então.'); End; 5: Begin Total := Total + Cafe; WriteLn; WriteLn('Iremos trazer agora o seu café então.'); End; 6: Begin Total := Total + Gelado; WriteLn; WriteLn('Iremos trazer agora o seu gelado então.'); End; else begin WriteLn; WriteLn('Opção inválida.'); end; end; Neste código, além de esteticamente mais apelativo e organizado, o compilador não precisa percorrer todas as opções, avaliando a cada uma se a opção é correta ou não. Entra no case, vai à opção cerca, e faz o que tem a fazer. E ainda ficas com a possibilidade de alertar o utilizador caso a opção escolhida não seja nenhuma das propostas, algo que de contrário precisarias de IFs encadeados para fazer, o que deixaria o código ainda mais frágil. Eu lembro-me que em outras linguagens de programação usava uma função chamada break, para parar o programa caso por exemplo alguém escolhesse uma opção inválida, mas ainda não encontrei nada parecido aqui, se alguém souber se é possível fazer. BrunoJnr. Link to comment Share on other sites More sharing options...
nunopicado Posted April 11, 2024 at 12:45 AM Report Share #632995 Posted April 11, 2024 at 12:45 AM O Pascal dispõe de 4 comandos para controlo de fluxo não ortodoxo, Break, Continue, Exit e Halt. O Break sai de um ciclo, o Continue passa para a próxima iteração de um ciclo, o Exit sai da função atual e o Halt sai do programa. Mas a sua disponibilidade depende de qual compilador estás a usar. De qualquer forma, não recomendo que uses nenhum deles na fase atual em que te encontras, a julgar pelo código que mostraste. Qualquer delas é um pesadelo para debug, e é preciso ter alguma prática para não seres enganado pela sua presença, em caso de ocorrer algum erro que estejas à procura da causa. Este tipo de programa (menu + seleção de opções) é um exercício muito usado no início exatamente porque te força a detetar os problemas que uma programação básica te trás neste cenário. Todos os problemas que te possam ocorrer para este tipo de programa resolves facilmente com recurso a ciclos e funções: Os ciclos para controlar o fluxo do programa de uma forma mais ortodoxa, e as funções para que possas criar um código 'menos pastoso', em que possas reutilizar código comum sem recurso ao copy/paste (regra de outro da boa programação: pensa 20 vezes antes de fazeres copy/paste de um código. Se estás a fazer copy/paste, há uma boa chance de estares a fazer algo mal). Pensa no menu como se fosse um mordomo, a perguntar-te o que queres. Ele diz-te as opções e pergunta o que queres. Tu respondes. Mediante a tua resposta, ele vai perguntar oura coisa qualquer, num ciclo que só termina quando a tua opção escolhida for 'sair'. Assim, se todas as perguntas forem feitas dentro de um loop (o REPEAT...UNTIL é muito bom para isto) e a cada resposta ele chama a função adequada, eventualmente até usando um outro loop para obrigar a que a resposta seja uma das possíveis, o menu funcionará corretamente. "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to comment Share on other sites More sharing options...
pwseo Posted April 29, 2024 at 03:34 PM Report Share #633067 Posted April 29, 2024 at 03:34 PM Ao já referido pelo @nunopicado acrescentaria o seguinte: será boa ideia planear o fluxo do programa em papel antes de o transcrever para código. Durante essa fase de planeamento, deve ser especificado o tipo de dados e o significado de cada variável (apenas e só um por cada variável). O problema seria assim auto-evidente: não só Quer_Sobremesa_1 nunca seria do tipo de dados Integer ou Real (mas sim Boolean, para representar um valor dicotómico Sim/Não), como seria impossível reutilizar variáveis -- pois obrigaria a dar duas funções/significados a uma variável durante o planeamento referido. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now