Meneer van Dalen wacht op antwoord rekenmachine

@sterretje

Ik will proberen met een led screen een rekenmachine te maken die werkt volgens het principe Meneer van Dalen wacht op antwoord.

Eerste goede stap leek mij om te kijken of ik een getal kan inlezen.
Maar helaas doe ik wat verkeerd hier : Wokwi - Online ESP32, STM32, Arduino Simulator

Kan iemand me vertellen wat ik verkeerd gedaan heb.

Oke

Dit lijkt te werken alleen zie ik nu steeds dat als input 0 wordt afgedrukt.D
Denk dat dit door de enter komt.

Hoe kan ik dit oplossen ?

Code :


void setup() {

  Serial.begin(9600); 


}

void loop() {
  // input some mumber and it gets parsed to a nummmer
  Serial.print("Mag ik het eerste getal"); 
  // wachtenn op de input
  while (Serial.available() == 0) {}

  int getal = Serial.parseInt(); 

  Serial.println(getal);

}

Die extra 0 is zeer waarschijnlijk het resultaat van een linefeed <LF> of carriage return <CR> die de seriële monitor in wokwi stuurt en aangezien dat geen nummer tussen 0 en 9 is wordt er 0 van gemaakt.
Je moet dus testen of het ontvangen karakter inderdaad een numerieke waarde is.

Je kunt Robin's updated Serial Input Basics eens lezen om wat ideeën te krijgen hoe je seriële invoer kunt afhandelen.

ga ik doen

Een vraagje.

Ik ben nu example2 aan het bestuderen maar ik zie dat de output lijkt op een string
is er ook een manier waarop ik het als array kan zien ?

Ik snap de vraag niet helemaal. Een string is een array (van karakters).

oke

Dan ben ik toe aan het parsen.

Nu zie ik twee problemen.

Hoe weet ik of het een getal, een + of een = is
En ga ik alles parsen naar de polish methode of gebruik ik 2 stacks om te parsen en dan alles uit te rekenen.

Wat is jouw idee ?

Elk teken heeft een eigen ASCII code.
Je moet dus niet op zoek gaan naar de 1 of de +, maar naar 49 (0x31) of 43 (0x2B).
De getallen die als 0x.. worden geschreven zijn hexadecimale getallen die dezelfde waarde hebben als de decimale getallen.

Je kunt deze tekens opzoeken in een ASCII tabel (klik !), daar zijn er een heleboel van te vinden dus zoek er 1 op die je handig vindt om te gebruiken.

Het is dus raadzaam om alle ASCII tekens die binnenkomen maar die je niet wil gebruiken, weg te gooien en daarmee jezelf een beetje hoofdzorgen te besparen.
Misschien wil je nog wel 3 tekens extra gebruiken, eentje die enter vertegenwoordigt om de berekening te starten, eentje die je in staat stelt het laatste teken dat je (dan per ongeluk) hebt ingegeven weer wist (de C op je calculator), en eentje dat alles weer naar nul zet (de CE op je calculator).

Wanneer je tekens binnen hebt gekregen die je wel wil gebruiken, zul je die alsnog moeten omzetten, eerst naar losse cijfers, en dan naar getallen of operators voor je rekenmachine.

Je kunt ieder binnengekomen karakter testen. Als je een 0 invoert wordt het karakter '0' gestuurd, voor 1 wordt het karakter '1' gestuurd enz. Voor een + wordt het karakter '+' gestuurd.

Om te controleren of een karakter een nummer is kun je een simple if gebruiken waar je een reeks test; ch in onderstaand voorbeeld is een enkel karakter dat je ingelzen hebt met Serial.read().

if (ch >= '0' && ch <= '9')
{
  // het is een nummer
}
else
{
  // het is geen nummer
}

Er is ook een standaard functie isDigit() die hetzelfde doet.

Om te controleren welke wiskundige functie uitgevoerd moet worden kun je een simpele if gebruiken. B.v.

if (ch == '+')
{
  // plus ontvangen
}

Als je een nummer ontvangt kun je dat toevoegen aan een array zodat je dat later kunt omzetten naar een integer of float.

Er zijn wat probleem met het bovenstaande.

  1. Als je floating point getallen wilt invoeren moet je de decimale punt (komma) ook afhandelen.
  2. Een '-' kan niet alleen een bewerking aanduiden maar ook een negatief getal.

Voor later:
Ik denk dat de beste oplossing is om een kleine finite state machine (FSM) te gebruiken die bijhoudt wat je aan het invoeren bent

  1. Lees eerste getal (met bv Robin's tweede voorbeeld).
    Test if het een getal is. Indien ja, ga naar het lezen van het tweede getal.
  2. Lees het tweede getal.
    Test of het een getal is. Indien ja, ga naar het lezen van de bewerking
  3. Lees de bewerking.
    Ga naar uitvoeren
  4. Voer de bewerking uit en toon resultaat.
  5. Terug naar lezen eerste getal.

Voor wat ik begrepen heb, is het de bedoeling dat de bewerking complex gemaakt wordt en dat er dan toch de juiste rekenmethode wordt gebruikt, vandaar de Meneer van Dalen.
Daarmee is de laatst genoemde handelswijze een begin, maar niet hetgeen wat uiteindelijk de bedoeling is.
Aan de hand van die handelswijze, is overigens wel een iets gewijzigde variant te bedenken, namelijk afwisseling van getal en bewerking, waarbij het gelijk aan teken dan het geheel afsluit en het resultaat getoond kan worden.

Dat klopt.

Uiteindelijk wil ik graag dat bijvoorbeeld 2 + 3 * 4 en 3 * 4 + 2 goed uitgerekend worden.

In een eerder privé bericht (voordat dit onderwerp gestart was) was er sprake van Poolse notatie. Vandaar mijn benadering.

Klopt, dat is denk ik een manier om de sommen op te lossen denk ik.

De andere manier die ik kan bedenken is twee stacks te gebruiken maar misschien is er wel een "betere" manier om dit op te lossen.

Wat zijn 'stacks' in dit geval?

Voor zover ik het snap is een stack eigenlijk een array die werkt volgens het LIFO systeem.
Dus alleen de eerste item kun je eruit halen.

Zie voor meer info: C++ Stacks

OK, dan begrijp ik waar je het over hebt. Op dit moment nog niet zeker hoe dat van toepassing is; maar dat kan goed aan mij liggen.

Als voorbeeld :

Stel je voor dat je de som 2 + 3 * 4 wilt oplossen met 2 stacks.

Dan zou je het zo kunnen doen:

  • lees het getal 2 en stop het in de nummers stack.
  • lees de + en stop die in de operators stack
  • lees de 3 en stop die ook in de nummers stack
  • lees de * en omdat die een hogere prioriteit heeft lees je daarna de 4
  • haal de 4 van de nummers stack
  • haal de 3 van de nummers stack
  • haal de * van de operators stack
  • reken het uit en stop het getal weer in de nummers stack.
  • haal de 12 er weer uit
  • haal de 2 eruit
  • haal de + uit de operators stack
  • reken het uit en omdat beide stacks leeg ziin, weet je de uitkomst.

Moet je dan je operators stack niet ook nog gaan beheren om de prioriteiten juist te krijgen ?
Of ga je niet meer dan 3 getallen en 2 operators toestaan ?

Daarvoor zou je een array kunnen gebruiken denk ik met de operator en de priority

Maar zoals ik al een paar keer gezegd hebt, als er een betere manier is gooi het hier in de groep.

Sta ervoor open

Klinkt eenvoudig maar het is geen stack (LIFO). Als je 3 * 4 + 2 wilt berekenen zul je niet de laatste invoer van de stack moeten halen maar de eerste invoer zodat je de vermenigvuldiging kunt doen voor de optelling.

Ik weet niet of er eenvoudigere oplossing zijn; nooit over nagedacht.

Wil je ook het gebruik van haakjes wilt toestaan zoals in (2+3) * 4? En/of machtsverheffen en worteltrekken?