C++ frågor

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Zkronk
Inlägg: 1423
Blev medlem: 23 augusti 2005, 16:44:36
Ort: Uppsala

Re: C++ frågor

Inlägg av Zkronk »

Det jag tyckte var knepigt med dina push- och pop-funktioner var att du håller koll på elementet som ligger högst upp i stacken med hjälp av pekare.
Att göra jämförelsen om det är fullt i stacken eller inte t.ex. blir lite svårare då.
Användarvisningsbild
4kTRB
Inlägg: 18279
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Jag tror inte själva upp och nedräkningen blir fel
men den pekaren ställer till det på något annat vis
eftersom det inte går skapa ett nytt objekt med
en egen definierad stack/buffert.
Användarvisningsbild
4kTRB
Inlägg: 18279
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Det fungerar!
Lite för mycket c++ ett tag här men hade utfört push och pop
på fel stack i main därför ett underligt resultat.

Din variant testade jag också och den funkar kanonbra.
Sedan förstår jag nu tack vare din kod vad den extra
funktionen med tildetecknet är till för. Eclipse autogenererade
den och jag tog bort den.

Nu ska jag gå vidare och bygga en enkel räknemaskin med polsk notation!
M.h.a stack så klart!

:)
Användarvisningsbild
4kTRB
Inlägg: 18279
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Har lärt mig en del nytt.
Har lite svårt att komma överens med C++, Java-utbildad som jag är.
Har försökt mig på att skapa en stränganalysator att använda till en
omvänd polsk kalkylator av enklare slag, man får inte knappa in vad som
helst utan ska helst hålla sig till syntaxen.

Exempelvis:
beräkna
(2.25 - 1) * (8 + 3.5)
knappa in
2.25 1 - 8 3.5 + *

tolken hanterar inga negativa tal än så länge och beräknar inget utan
den enbart talar om vad som knappats in. Sedan ska jag ha switch/case
för de olika symbolerna plus en funktion som gör om decimaltalstecknen
till double.

Testkörning
Ange ett tal: 2.25 8.7 - 7 6.2 + /
entered string is : 2.25 8.7 - 7 6.2 +

digit
period
digit
digit
space
digit
period
digit
space
op
space
digit
space
digit
period
digit
space
op
space


pop d
pop p
pop d
pop d
pop s
pop d
pop p
pop d
pop s
pop o
pop s
pop d
pop s
pop d
pop p
pop d
pop s
pop o
pop s
pop


main

Kod: Markera allt


#include <string>
#include "StackChar.h"
#include "Operand.h"

using namespace std;

int main() {

	Operand lineanalyzer;
	StackChar symbolstack(50);

	char tecken[50];
	cout << "Ange ett tal: ";
	cin.getline(tecken,20);
	cout << "entered string is : " <<  tecken;

	cout << NEWLINE;
	cout << NEWLINE;

	symbolstack = lineanalyzer.getOperand(tecken);

	cout << NEWLINE;
	cout << NEWLINE;

	symbolstack.invert();

	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;
	cout << "pop " << symbolstack.pop() << NEWLINE;

	return 0;
}
Operand

Kod: Markera allt

#include "Operand.h"

using namespace std;

Operand::Operand() {
	//cout << "En instans av Op" << NEWLINE;
}

Operand::~Operand() {
	//cout << "En instans av Op har tagits bort." << endl;
}

StackChar Operand::getOperand(char tecken[]){
	int charindex = 0;
	bool spaceflag;
	bool periodflag;
	bool numberflag;
	bool opflag;
	StackChar symbolstack(50);

	numberflag=number(tecken,charindex);
	periodflag=period(tecken,charindex);
	spaceflag=space(tecken,charindex);
	opflag=operand(tecken,charindex);
	while(numberflag || periodflag || spaceflag || opflag){
		if(opflag){
			symbolstack.push('o');
			charindex++;
			numberflag=number(tecken,charindex);
			periodflag=period(tecken,charindex);
			spaceflag=space(tecken,charindex);
			opflag=operand(tecken,charindex);
		}
		if(periodflag){
			symbolstack.push('p');
			charindex++;
			numberflag=number(tecken,charindex);
			periodflag=period(tecken,charindex);
			spaceflag=space(tecken,charindex);
			opflag=operand(tecken,charindex);
		}
		if(spaceflag){
			symbolstack.push('s');
			charindex++;
			numberflag=number(tecken,charindex);
			periodflag=period(tecken,charindex);
			spaceflag=space(tecken,charindex);
			opflag=operand(tecken,charindex);
		}
		if(numberflag){
			symbolstack.push('d');
			charindex++;
			numberflag = number(tecken,charindex);
			periodflag = period(tecken,charindex);
			spaceflag = space(tecken,charindex);
			opflag = operand(tecken,charindex);
		}
	}
	return symbolstack;
}

bool Operand::number(char tecken[],int i){
	bool flag = false;
	if(isdigit(tecken[i])){
		cout << "digit" << NEWLINE;
		flag = true;
	}
	return flag;
}

bool Operand::operand(char tecken[],int i){
	bool flag = false;
	if((tecken[i] != ' ') && (tecken[i] != '\t') && (tecken[i] != '\0')
			&& (tecken[i] != '.') && (!isdigit(tecken[i]))){
		cout << "op" << NEWLINE;
		//	if(tecken[i] == '\0')
		//		cout << "NULL " << tecken[i]+'0' << NEWLINE;
		flag = true;
	}
	return flag;
}
bool Operand::period(char tecken[],int i){
	bool flag = false;
	if(tecken[i] == '.'){
		cout << "period" << NEWLINE;
		flag = true;
	}
	return flag;
}
bool Operand::space(char tecken[], int i){
	bool flag = false;
	if((tecken[i] == ' ') || (tecken[i] == '\t')){
		cout << "space" << NEWLINE;
		flag = true;
	}
	return flag;
}
StackChar

Kod: Markera allt

#include "StackChar.h"
using namespace std;

StackChar::StackChar(int stacksize) {
	stackSize = stacksize;
	allocbuf = new char[stacksize];
	for (int i=0; i<stacksize; i++) {
		allocbuf[i] = '\0';    				// Initialize all elements to NULL.
	}
	stackTopPointer = allocbuf;				// peka på element noll i allocbuf
	//	stackTopPointer = &allocbuf[0];		// fungerar också
	bool b = allocdouble();					// allokera en stack om stacksize char
	if(!b){
		cout << "Allokering av stack överskred STACKSIZEMAX" << NEWLINE;
		cout << "STACKSIZEMAX = " << STACKSIZEMAX << NEWLINE;
		cout << STRING  << NEWLINE;
	}
}
StackChar::~StackChar(){
	delete [] allocbuf;
	//cout << "En instans av StackChar har tagits bort." << endl;
}

int StackChar::getSize(){
	return stackSize;
}

void StackChar::invert(void){
	int index = 0;
	char c;
	char temp[index];
	while(index < stackSize){
		temp[index] = '\0';
		c = this->pop();
		if(c == '\0'){
			break;
		}
		temp[index] = c;
		++index;
	}
	index = 0;
	while(index < stackSize){
		c = temp[index];
		if(c == '\0'){
			break;
		}
		this->push(c);
		++index;
	}
}

/**
 * Allokera ett minnesområde för att lagra char.
 * Avancera pekaren stackTopPointer n steg för att peka på
 * start av stacken.
 * Returnera true om den allokerade stacken håller
 * sig inom ramen för STACKSIZEMAX annars returnera false
 */
bool StackChar::allocdouble(){
	if ((allocbuf + STACKSIZEMAX - stackTopPointer) >= stackSize){
		stackTopPointer += stackSize;			// peka på stackens början
		return true;
	} else
		return false;
}

void StackChar::push(char ch){
	if(stackTopPointer > allocbuf){
		*stackTopPointer = ch;
		stackTopPointer--;
	}
	else{
		cout << "Stacken är full" << NEWLINE;
	}
}

char StackChar::pop(){
	if(stackTopPointer < (allocbuf + stackSize)){
		++stackTopPointer;
		return *stackTopPointer;
	}
	else{
		//cout << "Stacken är tom så " << '\0' << " returneras" << NEWLINE;
		return '\0';
	}
}
Användarvisningsbild
4kTRB
Inlägg: 18279
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Trodde att en array måste initieras till det antal element som ska ingå
men icke. Räcker med 1.

int array[1] tar hand om fler int än ett.

int array[0] fungerar inte och
samma med int array[].

Den här koden omvandlar en radda med tecken till en double.

Kod: Markera allt

double Operand::calcDouble(char tecken[]){
	int index;
	int temp;
	int u = 0;
	int heltal[1];
	int decimaltal[1];
	double decimaldel;
	double heltalsdel;
	double result;
	for(index=0;index<10;++index){
		heltal[index] = 0;
		decimaltal[index] = 0;
	}
	index = 0;
	temp = 0;
	while(isdigit(tecken[index])){
		heltal[temp] = tecken[index] - '0';
		index++;
		temp++;
	}
	heltalsdel = 0;
	while(temp>0){
		heltalsdel += pow (10,u)*heltal[temp-1];
		temp--;
		u++;
	}
	index++;
	while(isdigit(tecken[index])){
		decimaltal[temp] = tecken[index] - '0';
		index++;
		temp++;
	}
	decimaldel = 0;
	u=0;
	while(temp>0){
		decimaldel += pow (10, 0-u-1)*decimaltal[u];
		temp--;
		u++;
	}
	result = 0.0;
	result = heltalsdel + decimaldel;

	return result;
}
Anrop

Kod: Markera allt

	char decimalnumber[1];

	decimalnumber[0] = '6';
	decimalnumber[1] = '7';
	decimalnumber[2] = '.';
	decimalnumber[3] = '4';
	double d = lineanalyzer.calcDouble(decimalnumber);
	cout << "d = " << d << NEWLINE;

	for(int i = 0; i < 5; i++){
		decimalnumber[i] = 0;
	}

	decimalnumber[0] = '.';
	decimalnumber[1] = '4';
	decimalnumber[2] = '5';
	double f = lineanalyzer.calcDouble(decimalnumber);
	cout << "f = " << f << NEWLINE;

	cout << "d / f = " << d/f << NEWLINE
Utskrift
d = 67.4
f = 0.45
d / f = 149.778
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1339
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Re: C++ frågor

Inlägg av baron3d »

Gjorde ett försök till tolk en gång i tiden.
Om nu den är värd att visa. Det finns en bugg någonstans.

"text" är en sträng.
Funktionen Berakna anropas rekursivt.

Kod: Markera allt

double TForm1::Berakna(void){
   double b=0,    d[50], e[50];
   int    tal=0;
   char   a,      t[50], u[50];
   bool   go=true, opr=false, minus=false;

   for(int i=0; i<50; i++) {
      d[i]=0;
      e[i]=0;
      t[i]=' ';
      u[i]=' ';
   }


// Tolka --------------------------------------

   int len=text.Length() ;

   while(go==true && pos<=len){
      a=text[pos];
      pos++;
      if(a>='0' && a<='9') {
         b= b*10 + a - '0';
         opr=false;
      }
      else {
         switch (a){
            case '-':
               if(opr==true) {
                  minus=true;
                  break;
               }
               // OBS inget break här
            case '+':
            case '*':
            case '/':
               if(minus==true) {
                  b=-b;
               }
               d[tal]=b; b=0;
               t[tal]=a;
               tal++;
               opr=true;
               minus=false;
               break;

            case ')':
               go=false;
               break;

            case '(':
               opr=false;
               b=Berakna();
               break;
         }
      }
   }

   if(minus==true) {
      b=-b;
   }
   
   d[tal]=b;
   t[tal]= ' ';
   tal++;


// Beräkna --------------------------------------

   //   * och /
   int k=0;
   b=d[0];
   for( int i=0 ; i<tal ; i++){
      if(t[i]=='*'){
         b=b*d[i+1];
      }
      else if(t[i]=='/'){
         b=b/d[i+1];
      }
      else {
         e[k]=b;
         u[k]=t[i];
         k++;
         b=d[i+1];
      }
   }

   //   + och -
   b=e[0];
   for( int i=0 ; i<k ; i++){
      if(u[i]=='+'){
         b+=e[i+1];
      }
      else if(u[i]=='-'){
         b-=e[i+1];
      }
   }

   return(b);
}
//---------------------------------------------------------------------------

Senast redigerad av baron3d 16 februari 2019, 19:42:18, redigerad totalt 1 gång.
Mr Andersson
Inlägg: 1394
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: C++ frågor

Inlägg av Mr Andersson »

4kTRB skrev:Trodde att en array måste initieras till det antal element som ska ingå
men icke. Räcker med 1.

int array[1] tar hand om fler int än ett.
Nej nej nej. Det här är helt fel. Skriver du mer än 1 int skriver du över minne som någon annan variabel använder.
Språket hindrar dig inte från att accessa en array utanför gränserna (för det finns vissa specifika användningsområden) men det är en livsfarlig bugg att göra som du gör.
Findecanor
Inlägg: 982
Blev medlem: 2 juli 2010, 23:04:07

Re: C++ frågor

Inlägg av Findecanor »

@4kTRB: Jag tror du har missuppfattat hur arrayer funkar i C. De är inte objekt som är smarta på något vis. En array har fått precis så många element som du har deklarerat, dvs. 1, i det här fallet. Tyvärr har C inte någon automatisk kontroll på att man går utanför arrayens gränser. Sen kan det ligga vad som helst bredvid den, och om arrayen är en icke-statisk lokal variabel så ligger den på CPU-stacken. Att C och C++ inte har "bounds checking" i språket anses av många som den största anledningen till varför man inte borde använda de språken.
För C++ rekommenderas klassen std::vector , som kan öka i storlek dynamiskt men du måste fortfarande ändra storlek med anrop för just det: indexera högt funkar inte.

Buffertöverskridning på Wikipedia ...
Bufferöverskridningar ("Buffer overflow") är orsaken till en stor del av alla säkerhetshål i programvara.
I C och C++ måste du alltid ha koll på dina index, storlekar och pekare!
Senast redigerad av Findecanor 15 februari 2019, 14:42:50, redigerad totalt 2 gånger.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43147
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: C++ frågor

Inlägg av sodjan »

> "Buffer overflow" är orsaken till en stor del av alla säkerhetshål...

Ja, det och "zero terminated strings". Glöm bort "null" och det händer
spännande saker med många minnes kopierings rutiner...
Användarvisningsbild
4kTRB
Inlägg: 18279
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

baron3d skrev:Gjorde ett försök till tolk en gång i tiden.
Om nu den är värd att visa. Det finns en bugg någonstans.
Det där får du nog rita ett flödesschema på för att kunna reda ut.
Användarvisningsbild
MJH
Inlägg: 31
Blev medlem: 26 maj 2018, 12:05:29

Re: C++ frågor

Inlägg av MJH »

Men C är ju utformat för maskinnära programmering, är väl därför den ligger på botten av alla (flesta) operativsystem.
Sen att skylla på språket för att man inte kan hantera det är väl lite fel!

Lite förenklat så får C eller C++ programmerare (C++ är en utveckling av C) se till att städa efter sig samt se till att ha kontroll på sin minnes hantering, vilket inte är ett större problem om man vet vad man sysslar med.

Finns i tråden ett skräckexempel på minnes hantering som skriver i otillåten minnes area, rådet till dessa är att använda något högnivås språk som tar hand om dessa misstag.
Styrkan i C, C++ är att jag som programmerare har total kontroll av hårdvaran men som vid okunskap skapar problem.

C eller C++ är lite som är du verkligen mogen att ta detta ansvar eller skall du låta andra ta ansvaret?
Användarvisningsbild
ffredrik
Inlägg: 340
Blev medlem: 20 oktober 2009, 17:52:18
Ort: Göinge

Re: C++ frågor

Inlägg av ffredrik »

MJH: :tumupp:
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43147
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: C++ frågor

Inlägg av sodjan »

Visst, gör rätt så blir det rätt. Spelar ingen roll, man kommer inte
förbi att det är lättare att göra misstag (missstag har ingenting med
kompetens att göra) i C än i många andra språk/verktyg. Och det
är inte heller någon tvekan att detta har orsakat många problem
med applikationer och system. Det är bara att acceptera att det
har blivit så populärt och bita ihop... :-)
Användarvisningsbild
MJH
Inlägg: 31
Blev medlem: 26 maj 2018, 12:05:29

Re: C++ frågor

Inlägg av MJH »

Ja är väl därför dagens programmerare föredrar ramverk som hanterar alla svårigheter som en själv lärde sig under 80 talet :)
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1339
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Re: C++ frågor

Inlägg av baron3d »

Med kompetens så vet du vilka (skit) bibliotek som har osäkra funktioner samt hur man undviker problem.
Skriv svar