XeppMedlem sedan nov. 200327 inlägg Hej hopp!
Håller på att försöka fixa en avancerad miniräknare som ska klara att räkna ut tex 3 + 4 * 5 = 23 och inte 7*5 = 35. Den avancerade miniräknaren klarar detta men inte den simpla versionen. Då blir svaret 35 i detta fall.
Någon som har nå bra tips på hur jag kan göra det?
Har försökt lite med tal1-3 och gammaloperand och nyoperand, men blir såå komplicerat. Undrar om det går att göra på nått enklare sätt..
Tacksam för svar
.:: Sebbe
PeWMedlem sedan juni 200010 432 inlägg Beror på hur du hanterar de olika prioriteterna. Multiplikation har högre prioritet än addition. Så, även om du läser in uttrycket i en radda så kan du inte utföra operationerna rakt av utan du måste dela upp det på ett lämpligare sätt. Ett sätt är att dela upp det i begreppen term, faktor och rest. Då kan man genom exempelvis rekursion vandra igenom hela uttrycket via olika funktioner som anropar varandra i en kedja så länge uttrycket inte är terminerat, tecken för tecken.
Lite knepigt att råda dig då du inte presenterat nån kod. Så det enda jag kan säga nu är att ' * / ' har högre prioritet än ' + - ' vilket ger att du måste dela upp de olika fallen på ett vettigt sätt.
Ett annat sätt är att dela upp uttrycket i symboler och sedan lägga dem i en lista. Sedan letar man igenom listan efter operatorer med högst prioritet och byter ut dem och deras argument mot resultatet i beräkningen. Tre symboler blir till en. Därefter fortsätter man med operatorer av lägre prioritet och när man bara har en symbol kvar är det svaret.
XeppMedlem sedan nov. 200327 inlägg Jo, jag vet att * och / har större prioritet... det är lixsom där utmaningen sitter.
Just nu försöker jag göra på ett sätt som är ungefär att i fallet 3 + 4 * 5 = 23
3an spars som val1 och + som gammalop.
4an spars som val3 och * som nyop.
Om gammalop är * eller / så räknar programet ut vad val1 * lr / val2 är.
Om nyop är * eller / så väntar programet med att räkna ut resultatet. Om nyop är + eller - så kan man räkna ut talet.
Typ så funkar det.. lite primitivt kanske, men jag borde få det att funka snart.
.:: Sebbe
theDTMedlem sedan nov. 20034 inlägg Det finns nångonting som heter Polsknotation som du kan använda till detta.
Det borde finnas information på webben om det, samt hur tankegången är.
Det är lite annorlunda sätt att se på operatorerna och operanderna, 1 + 1 noteras ex. som 1 1 +
Jag gjorde en snabbsökning och hittade
http://www.cs.hut.fi/Opinnot/T-106.217/Hemuppgifter/1997/ex52
http://susning.nu/Omv�nd_polsk_notation
PeWMedlem sedan juni 200010 432 inlägg För att visa vad jag menade i mitt förra inlägg så pillade jag ihop nedan fungerande program (C). Då jag inte vet om det rör sig om en skoluppgift utelämnade jag en del kommentarer, men om man tar några uttryck och följer vilken väg de tar genom funktionerna så kanske kronan ramlar ned i hur man kan göra utan att bli för komplicerad.
#include <stdio.h>
char *tok; // uttrycket, kommer att stegas tecken för tecken
int value; // värdet efter varje delberäkning
int result; // det slutliga resultatet
char mul; // flagga för att prioritera rätt vid mul och div
void term();
void factor()
{
int part;
if(*tok=='*'){
part=value;
mul=1;
tok++;
term();
value*=part;
mul=0;
}
if(*tok=='/'&&mul==0){
part=value;
tok++;
term();
value=part/value;
}
}
void rest()
{
if(*tok=='+'){
tok++;
term();
result+=value;
}
if(*tok=='-'){
tok++;
term();
result-=value;
}
if(*tok)
rest();
}
void term()
{
// plocka ut ett nummer ur sträng
if(*tok<58&&*tok>47){
value=*(tok++)-'0';
while(*tok<58&&*tok>47)
value=value*10+*(tok++)-'0';
}
factor();
}
void expr()
{
result = 0;
value = 0;
mul = 0;
term();
if(result==0)
result=value;
rest();
}
int main()
{
char input[255];
tok = input;
printf("\n>");
scanf("%s",&input);
expr(); // beräkna
printf("%d\n",result);
return 0;
}
Koden är inte menat som en färdig lösning utan som ett förtydligande till vad jag menade i ett tidigare inlägg. 'Tricket' är att låta de högre prioriterade operanderna själva utgöra en term.
PeWMedlem sedan juni 200010 432 inlägg Vet inte om det hjälpte?
Annars är följande pseudokod mall för ovan exempel
expression: term
rest
term: digits
factor => (a*b) eller (a/b)?
rest: om (+) term rest => nytt delvärde
om (-) term rest => nytt delvärde
factor: om (*) term => nytt delvärde
om (/) term => nytt delvärde
Nackdelen med den lösningen är att den använder mycket stack vid längre uttryck, vilket kan vara dumt om uttrycken man ska parsa i sig själva är rekursiva, har jag märkt.
fac(0) = 1
fac(n) = n * fac(n-1)
Dock så verkar det vara det vanligaste sättet, och det fungerar bra.
PeWMedlem sedan juni 200010 432 inlägg Detta är ett mycket vanligt sätt att parsa uttryck. Fördelen är att det lätt går att härleda grammatiskt då PDA:er arbetar med stack :)